diff --git a/cmake/modules/KDevPlatformMacros.cmake b/cmake/modules/KDevPlatformMacros.cmake index 5f536580b0..8cb9b4429e 100644 --- a/cmake/modules/KDevPlatformMacros.cmake +++ b/cmake/modules/KDevPlatformMacros.cmake @@ -1,174 +1,174 @@ # # KDevelop Platform Macros # # The following macros are defined here: # # KDEVPLATFORM_ADD_APP_TEMPLATES( template1 ... templateN ) # Use this to get packaged template archives for the given app templates. # Parameters should be the directories containing the templates. # KDEVPLATFORM_ADD_FILE_TEMPLATES( template1 ... templateN ) # Use this to get packaged template archives for the given file templates. # Parameters should be the directories containing the templates. # # Copyright 2007 Andreas Pakulat # Redistribution and use is allowed according to the terms of the BSD license. include(CMakeParseArguments) # creates a template archive from the given directory macro(kdevplatform_create_template_archive _templateName) get_filename_component(_tmp_file ${_templateName} ABSOLUTE) get_filename_component(_baseName ${_tmp_file} NAME_WE) if(WIN32) set(_template ${CMAKE_CURRENT_BINARY_DIR}/${_baseName}.zip) - else(WIN32) + else() set(_template ${CMAKE_CURRENT_BINARY_DIR}/${_baseName}.tar.bz2) - endif(WIN32) + endif() file(GLOB _files "${CMAKE_CURRENT_SOURCE_DIR}/${_templateName}/*") set(_deps) foreach(_file ${_files}) get_filename_component(_fileName ${_file} NAME) string(COMPARE NOTEQUAL ${_fileName} .kdev_ignore _v1) string(REGEX MATCH "\\.svn" _v2 ${_fileName} ) if(WIN32) string(REGEX MATCH "_svn" _v3 ${_fileName} ) - else(WIN32) + else() set(_v3 FALSE) - endif(WIN32) + endif() if ( _v1 AND NOT _v2 AND NOT _v3 ) set(_deps ${_deps} ${_file}) endif ( _v1 AND NOT _v2 AND NOT _v3 ) endforeach(_file) add_custom_target(${_baseName} ALL DEPENDS ${_template}) if(WIN32) add_custom_command(OUTPUT ${_template} COMMAND zip ARGS -r ${_template} . -x .svn _svn .kdev_ignore WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${_templateName} DEPENDS ${_deps} ) - else(WIN32) + else() if(APPLE) add_custom_command(OUTPUT ${_template} COMMAND tar ARGS -c -C ${CMAKE_CURRENT_SOURCE_DIR}/${_templateName} --exclude .kdev_ignore --exclude .svn --numeric-owner -j -f ${_template} . DEPENDS ${_deps} ) - else(APPLE) + else() add_custom_command(OUTPUT ${_template} COMMAND tar ARGS -c -C ${CMAKE_CURRENT_SOURCE_DIR}/${_templateName} --exclude .kdev_ignore --exclude .svn --owner=root --group=root --numeric-owner -j -f ${_template} . DEPENDS ${_deps} ) - endif(APPLE) + endif() - endif(WIN32) + endif() endmacro(kdevplatform_create_template_archive _templateName) # package and install the given directory as a template archive macro(kdevplatform_add_template _installDirectory _templateName) kdevplatform_create_template_archive(${_templateName}) get_filename_component(_tmp_file ${_templateName} ABSOLUTE) get_filename_component(_baseName ${_tmp_file} NAME_WE) if(WIN32) set(_template ${CMAKE_CURRENT_BINARY_DIR}/${_baseName}.zip) - else(WIN32) + else() set(_template ${CMAKE_CURRENT_BINARY_DIR}/${_baseName}.tar.bz2) - endif(WIN32) + endif() install( FILES ${_template} DESTINATION ${_installDirectory}) GET_DIRECTORY_PROPERTY(_tmp_DIR_PROPS ADDITIONAL_MAKE_CLEAN_FILES ) list(APPEND _tmp_DIR_PROPS ${_template}) SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${_tmp_DIR_PROPS}") endmacro(kdevplatform_add_template _installDirectory _templateName) macro(kdevplatform_add_app_templates _templateNames) foreach(_templateName ${ARGV}) kdevplatform_add_template(${DATA_INSTALL_DIR}/kdevappwizard/templates ${_templateName}) endforeach(_templateName ${ARGV}) endmacro(kdevplatform_add_app_templates _templateNames) macro(kdevplatform_add_file_templates _templateNames) foreach(_templateName ${ARGV}) kdevplatform_add_template(${DATA_INSTALL_DIR}/kdevfiletemplates/templates ${_templateName}) endforeach(_templateName ${ARGV}) endmacro(kdevplatform_add_file_templates _templateNames) function(kdevplatform_add_library target) set(options) set(oneValueArgs) set(multiValueArgs SOURCES) cmake_parse_arguments(KDEV_ADD_LIBRARY "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) string(REPLACE "KDevPlatform" "" shortTargetName ${target}) if (${shortTargetName} STREQUAL ${target}) message(FATAL_ERROR "Target passed to kdevplatform_add_library needs to start with \"KDevPlatform\", was \"${target}\"") endif() string(TOLOWER ${shortTargetName} shortTargetNameToLower) add_library(${target} ${KDEV_ADD_LIBRARY_SOURCES}) add_library(KDev::${shortTargetName} ALIAS ${target}) generate_export_header(${target} EXPORT_FILE_NAME ${shortTargetNameToLower}export.h) target_include_directories(${target} INTERFACE "$") set_target_properties(${target} PROPERTIES VERSION ${KDEVPLATFORM_LIB_VERSION} SOVERSION ${KDEVPLATFORM_LIB_SOVERSION} EXPORT_NAME ${shortTargetName} ) install(TARGETS ${target} EXPORT KDevPlatformTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${shortTargetNameToLower}export.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/${shortTargetNameToLower} COMPONENT Devel) endfunction() function(kdevplatform_add_plugin plugin) set(options SKIP_INSTALL) set(oneValueArgs JSON) set(multiValueArgs SOURCES) cmake_parse_arguments(KDEV_ADD_PLUGIN "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) get_filename_component(json "${KDEV_ADD_PLUGIN_JSON}" REALPATH) list(LENGTH KDEV_ADD_PLUGIN_SOURCES src_count) if (NOT ${src_count} GREATER 0) message(FATAL_ERROR "kdevplatform_add_plugin() called without passing any source files. Please uses the SOURCES parameter.") endif() # ensure we recompile the corresponding object files when the json file changes set(dependent_sources ) foreach(source ${KDEV_ADD_PLUGIN_SOURCES}) get_filename_component(source "${source}" REALPATH) if(EXISTS "${source}") file(STRINGS "${source}" match REGEX "K_PLUGIN_FACTORY_WITH_JSON") if(match) list(APPEND dependent_sources "${source}") endif() endif() endforeach() if(NOT dependent_sources) # fallback to all sources - better safe than sorry... set(dependent_sources ${KDEV_ADD_PLUGIN_SOURCES}) endif() set_property(SOURCE ${dependent_sources} APPEND PROPERTY OBJECT_DEPENDS ${json}) add_library(${plugin} MODULE ${KDEV_ADD_PLUGIN_SOURCES}) set_property(TARGET ${plugin} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS ${json}) if (NOT KDEV_ADD_PLUGIN_SKIP_INSTALL) install(TARGETS ${plugin} DESTINATION ${PLUGIN_INSTALL_DIR}/kdevplatform/${KDEV_PLUGIN_VERSION}) endif() endfunction() diff --git a/debugger/framestack/framestackmodel.h b/debugger/framestack/framestackmodel.h index 902edd4122..256215616f 100644 --- a/debugger/framestack/framestackmodel.h +++ b/debugger/framestack/framestackmodel.h @@ -1,112 +1,112 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2009 Niko Sams * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_FRAMESTACKMODEL_H #define KDEVPLATFORM_FRAMESTACKMODEL_H #include #include #include #include #include namespace KDevelop { class DebugController; /** FIXME: This class needs rework, since at present it is not true model. Client cannot just obtain frames by grabbing a thread and listing children. It should first setCurrentThread beforehand, and it is the method that will actually fetch threads. Therefore, if this model is submitted to plain QTreeView, it won't work at all. Ideally, this should hold current thread and current frame numbers, and only fetch the list of threads, and list of frames inside thread when asked for by the view. */ class KDEVPLATFORMDEBUGGER_EXPORT FrameStackModel : public IFrameStackModel { Q_OBJECT public: explicit FrameStackModel(IDebugSession* session); - virtual ~FrameStackModel(); + ~FrameStackModel() override; struct ThreadItem { int nr; QString name; }; void setThreads(const QList &threads); /** * Update frames for thread @p threadNumber * * @note The currentFrame property will be set to the first frame * containing debug information */ void setFrames(int threadNumber, QList frames); void insertFrames(int threadNumber, const QList &frames); void setHasMoreFrames(int threadNumber, bool hasMoreFrames); FrameItem frame(const QModelIndex &index) override; QList frames(int threadNumber) const; //ItemModel implementation - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override; - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; - virtual QModelIndex parent(const QModelIndex& child) const override; - virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex& child) const override; + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; void setCurrentThread(int threadNumber) override; void setCurrentThread(const QModelIndex &index) override; int currentThread() const override; QModelIndex currentThreadIndex() const override; int currentFrame() const override; QModelIndex currentFrameIndex() const override; void setCurrentFrame(int frame) override; void fetchMoreFrames() override; private Q_SLOTS: void stateChanged(KDevelop::IDebugSession::DebuggerState state); private: - virtual void handleEvent(IDebugSession::event_t event) override; + void handleEvent(IDebugSession::event_t event) override; void update(); QModelIndex indexForThreadNumber(int threadNumber); int m_currentThread; int m_currentFrame; // used to count how often a user has scrolled down and more frames needed to be fetched; // this way, the number of frames fetched in each chunk can be increased if the user wants // to scroll far int m_subsequentFrameFetchOperations; bool m_updateCurrentFrameOnNextFetch; QList m_threads; QHash > m_frames; QHash m_hasMoreFrames; }; } #endif diff --git a/debugger/framestack/framestackwidget.h b/debugger/framestack/framestackwidget.h index 115b4bf8ec..a6d8370d1c 100644 --- a/debugger/framestack/framestackwidget.h +++ b/debugger/framestack/framestackwidget.h @@ -1,70 +1,70 @@ /* * This file is part of KDevelop * * Copyright 1999 John Birch * Copyright 2007 Hamish Rodda * Copyright 2009 Niko Sams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_FRAMESTACKWIDGET_H #define KDEVPLATFORM_FRAMESTACKWIDGET_H #include #include #include class QMenu; class QTreeView; class QModelIndex; class QListView; namespace KDevelop { class IDebugController; class KDEVPLATFORMDEBUGGER_EXPORT FramestackWidget : public AutoOrientedSplitter { Q_OBJECT public: explicit FramestackWidget( IDebugController* controller, QWidget *parent=0 ); - virtual ~FramestackWidget(); + ~FramestackWidget() override; Q_SIGNALS: void requestRaise(); private Q_SLOTS: void currentSessionChanged(KDevelop::IDebugSession* session); void setThreadShown(const QModelIndex& current); void checkFetchMoreFrames(); void currentThreadChanged(int); void currentFrameChanged(int); void frameSelectionChanged(const QModelIndex& current); void frameContextMenuRequested(const QPoint &pos); void copySelection(); void selectAll(); void sessionStateChanged(KDevelop::IDebugSession::DebuggerState state); private: IDebugSession *m_session; QListView *m_threads; QWidget *m_threadsWidget; QTreeView *m_frames; QMenu *m_framesContextMenu; }; } #endif // KDEVPLATFORM_FRAMESTACKWIDGET_H diff --git a/debugger/interfaces/idebugsession.h b/debugger/interfaces/idebugsession.h index a2be95e97d..1cf73f96a3 100644 --- a/debugger/interfaces/idebugsession.h +++ b/debugger/interfaces/idebugsession.h @@ -1,201 +1,201 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2009 Niko Sams * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_IDEBUGSESSION_H #define KDEVPLATFORM_IDEBUGSESSION_H #include #include #include #include namespace KDevelop { class IVariableController; class IBreakpointController; class IFrameStackModel; class Breakpoint; class StackModel; class KDEVPLATFORMDEBUGGER_EXPORT IDebugSession : public QObject { Q_OBJECT Q_ENUMS(DebuggerState) public: IDebugSession(); - virtual ~IDebugSession(); + ~IDebugSession() override; enum DebuggerState { NotStartedState, StartingState, ActiveState, PausedState, StoppingState, StoppedState, EndedState }; enum event_t { program_state_changed = 1, program_exited, debugger_exited, // Emitted when the thread or frame that is selected in UI // changes. thread_or_frame_changed, debugger_busy, debugger_ready, // Raised when debugger believe that program start running. // Can be used to hide current line indicator. // Don't count on this being raise in all cases where // program is running. program_running, // Raise when the debugger is in touch with the program, // and should have access to its debug symbols. The program // is not necessary running yet, or might already exited, // or be otherwise dead. connected_to_program }; public: /** * Current state of the debug session */ virtual DebuggerState state() const = 0; /** * Should return if restart is currently available */ virtual bool restartAvaliable() const = 0; /** * Returns if the debugee is currently running. This includes paused. */ bool isRunning() const; /** * Returns the local Url for a source file used in the current debug session. * * The default implementation just returns the url and is sufficient for * local debuggers. Remote debuggers can implement a path mapping mechanism. */ virtual QPair convertToLocalUrl(const QPair &remoteUrl) const; /** * Returns the remote Url for a source file used in the current debug session. * * The default implementation just returns the url and is sufficient for * local debuggers. Remote debuggers can implement a path mapping mechanism. */ virtual QPair convertToRemoteUrl(const QPair &localUrl) const; /** * @return the breakpoint controller of this session * * @note Implementations must ensure that a breakpoint controller always exists (even if it * is a dummy stub implementation that does nothing), and that it does not change during * the lifetime of a session. */ virtual IBreakpointController* breakpointController() const = 0; /** * @return the variable controller of this session * * @note Implementations must ensure that a variable controller always exists (even if it * is a dummy stub implementation that does nothing), and that it does not change during * the lifetime of a session. */ virtual IVariableController* variableController() const = 0; /** * @return the frame stack model of this session * * @note Implementations must ensure that a frame stack model always exists (even if it * is a dummy stub implementation that does nothing), and that it does not change during * the lifetime of a session. */ virtual IFrameStackModel* frameStackModel() const = 0; public Q_SLOTS: virtual void restartDebugger() = 0; virtual void stopDebugger() = 0; virtual void interruptDebugger() = 0; virtual void run() = 0; virtual void runToCursor() = 0; virtual void jumpToCursor() = 0; virtual void stepOver() = 0; virtual void stepIntoInstruction() = 0; virtual void stepInto() = 0; virtual void stepOverInstruction() = 0; virtual void stepOut() = 0; Q_SIGNALS: void stateChanged(KDevelop::IDebugSession::DebuggerState state); void showStepInSource(const QUrl& file, int line, const QString &addr); void showStepInDisassemble(const QString &addr); void clearExecutionPoint(); void finished(); void raiseFramestackViews(); /** This signal is emitted whenever the given event in a program happens. See DESIGN.txt for expected handled of each event. NOTE: this signal should never be emitted directly. Instead, use raiseEvent. */ void event(IDebugSession::event_t e); public: using QObject::event; // prevent hiding of base method. QUrl currentUrl() const; int currentLine() const; QString currentAddr() const; protected: // Clear the position before running code void clearCurrentPosition(); /// Sets new position and emits showStepInSource or showStepInDisassemble (if source file is unavailable) signal void setCurrentPosition(const QUrl& url, int line, const QString& addr); /** Raises the specified event. Should be used instead of emitting 'event' directly, since this method can perform additional book-keeping for events. FIXME: it might make sense to automatically route events to all debugger components, as opposed to requiring that they connect to any signal. */ virtual void raiseEvent(event_t e); friend class FrameStackModel; private Q_SLOTS: void slotStateChanged(KDevelop::IDebugSession::DebuggerState state); private: //TODO use d-pointer // Current position in debugged program, gets set when the state changes QUrl m_url; int m_line; QString m_addr; }; } #endif diff --git a/debugger/util/pathmappings.cpp b/debugger/util/pathmappings.cpp index c7593718d1..77b93d7919 100644 --- a/debugger/util/pathmappings.cpp +++ b/debugger/util/pathmappings.cpp @@ -1,258 +1,258 @@ /* * This file is part of KDevelop * * Copyright 2009 Niko Sams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "pathmappings.h" #include "debug.h" #include #include #include #include #include #include #include #include #include #include namespace { static QUrl rebaseMatchingUrl(const QUrl& toRebase, const KConfigGroup& config, const QString& baseEntry, const QString& rebaseEntry) { const QUrl::UrlFormattingOption matchOpts = QUrl::NormalizePathSegments; foreach (const QString &group, config.groupList()) { KConfigGroup pathCfg = config.group(group); const QString baseStr = pathCfg.readEntry(baseEntry, QUrl()).url(matchOpts); const QString searchStr = toRebase.url(matchOpts); if (searchStr.contains(baseStr)) { const QUrl rebase = pathCfg.readEntry(rebaseEntry, QUrl()); return rebase.resolved(QUrl(searchStr.mid(baseStr.length()))); } } //No mapping found return toRebase; } } namespace KDevelop { const QString PathMappings::pathMappingsEntry("Path Mappings"); const QString PathMappings::pathMappingRemoteEntry("Remote"); const QString PathMappings::pathMappingLocalEntry("Local"); QUrl PathMappings::convertToLocalUrl(const KConfigGroup& config, const QUrl& remoteUrl) { if (remoteUrl.isLocalFile() && QFile::exists(remoteUrl.toLocalFile())) { return remoteUrl; } KConfigGroup cfg = config.group(pathMappingsEntry); return rebaseMatchingUrl(remoteUrl, cfg, pathMappingRemoteEntry, pathMappingLocalEntry); } QUrl PathMappings::convertToRemoteUrl(const KConfigGroup& config, const QUrl& localUrl) { KConfigGroup cfg = config.group(pathMappingsEntry); return rebaseMatchingUrl(localUrl, cfg, pathMappingLocalEntry, pathMappingRemoteEntry); } class PathMappingModel : public QAbstractTableModel { Q_OBJECT public: - virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override + int columnCount(const QModelIndex& parent = QModelIndex()) const override { if (parent.isValid()) return 0; return 2; } - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override + int rowCount(const QModelIndex& parent = QModelIndex()) const override { if (parent.isValid()) return 0; return m_paths.count() + 1; } - virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override { if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { if (section == 0) { return i18n("Remote Path"); } else if (section == 1) { return i18n("Local Path"); } } return QAbstractTableModel::headerData(section, orientation, role); } - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override { if (!index.isValid()) return QVariant(); if (index.parent().isValid()) return QVariant(); if (index.column() > 1) return QVariant(); if (index.row() > m_paths.count()) return QVariant(); if (role == Qt::DisplayRole || role == Qt::EditRole) { if (index.row() == m_paths.count()) return QString(); if (index.column() == 0) { return m_paths[index.row()].remote.toDisplayString(QUrl::PreferLocalFile); } else if (index.column() == 1) { return m_paths[index.row()].local.toDisplayString(QUrl::PreferLocalFile); } } return QVariant(); } - virtual Qt::ItemFlags flags(const QModelIndex& index) const override + Qt::ItemFlags flags(const QModelIndex& index) const override { if (index.parent().isValid()) return Qt::NoItemFlags; if (!index.isValid()) return Qt::NoItemFlags; return ( Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled ); } - virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override { if (!index.isValid()) return false; if (index.parent().isValid()) return false; if (index.column() > 1) return false; if (index.row() > m_paths.count()) return false; if (role == Qt::EditRole) { if (index.row() == m_paths.count()) { beginInsertRows(QModelIndex(), index.row()+1, index.row()+1); m_paths.append(Path()); endInsertRows(); } if (index.column() == 0) { m_paths[index.row()].remote = QUrl::fromUserInput(value.toString()); } else if (index.column() == 1) { m_paths[index.row()].local = QUrl::fromLocalFile(value.toString()); } dataChanged(index, index); return true; } return false; } - virtual bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override + bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override { if (parent.isValid()) return false; if (row+count > m_paths.count()) return false; beginRemoveRows(parent, row, row+count-1); for (int i=0; i m_paths; }; PathMappingsWidget::PathMappingsWidget(QWidget* parent): QWidget(parent) { QVBoxLayout *verticalLayout = new QVBoxLayout(this); m_pathMappingTable = new QTableView(this); m_pathMappingTable->setSelectionBehavior(QAbstractItemView::SelectRows); m_pathMappingTable->horizontalHeader()->setDefaultSectionSize(150); m_pathMappingTable->horizontalHeader()->setStretchLastSection(true); verticalLayout->addWidget(m_pathMappingTable); m_pathMappingTable->setModel(new PathMappingModel()); connect(m_pathMappingTable->model(), &QAbstractItemModel::dataChanged, this, &PathMappingsWidget::changed); connect(m_pathMappingTable->model(), &QAbstractItemModel::rowsRemoved, this, &PathMappingsWidget::changed); connect(m_pathMappingTable->model(), &QAbstractItemModel::rowsInserted, this, &PathMappingsWidget::changed); QAction* deletePath = new QAction( QIcon::fromTheme("edit-delete"), i18n( "Delete" ), this ); connect(deletePath, &QAction::triggered, this, &PathMappingsWidget::deletePath); deletePath->setShortcut(Qt::Key_Delete); deletePath->setShortcutContext(Qt::WidgetWithChildrenShortcut); m_pathMappingTable->addAction(deletePath); } void PathMappingsWidget::deletePath() { foreach (const QModelIndex &i, m_pathMappingTable->selectionModel()->selectedRows()) { m_pathMappingTable->model()->removeRow(i.row(), i.parent()); } } void PathMappingsWidget::loadFromConfiguration(const KConfigGroup& cfg) { static_cast(m_pathMappingTable->model())->loadFromConfiguration(cfg); } void PathMappingsWidget::saveToConfiguration(KConfigGroup cfg) const { static_cast(m_pathMappingTable->model())->saveToConfiguration(cfg); } } #include "pathmappings.moc" #include "moc_pathmappings.cpp" diff --git a/debugger/util/treeitem.h b/debugger/util/treeitem.h index ec652c95e4..a5540ae31d 100644 --- a/debugger/util/treeitem.h +++ b/debugger/util/treeitem.h @@ -1,128 +1,128 @@ /* * This file is part of KDevelop * * Copyright 2008 Vladimir Prus * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_TREEITEM_H #define KDEVPLATFORM_TREEITEM_H #include #include #include #include #include #include #include namespace KDevelop { class TreeModel; class KDEVPLATFORMDEBUGGER_EXPORT TreeItem: public QObject { Q_OBJECT public: - virtual ~TreeItem(); + ~TreeItem() override; // FIXME: should be protected public: // Methods that the derived classes should implement /** Fetches more children, and adds them by calling appendChild. The amount of children to fetch is up to the implementation. After fetching, should call setHasMore. */ virtual void fetchMoreChildren()=0; virtual void setColumn(int index, const QVariant& data) { Q_UNUSED(index); Q_UNUSED(data); } void emitAllChildrenFetched(); protected: // Interface for derived classes /** Creates a tree item with the specified data. FIXME: do we actually have to have the model pointer. */ TreeItem(TreeModel* model, TreeItem *parent = 0); /** Set the data to be shown for the item itself. */ void setData(const QVector &data); /** Adds a new child and notifies the interested parties. Clears the "hasMore" flag. */ void appendChild(TreeItem *child, bool initial = false); void insertChild(int position, TreeItem *child, bool initial = false); void removeChild(int index); void removeSelf(); void deleteChildren(); /** Report change in data of this item. */ void reportChange(); void reportChange(int column); /** Clears all children. */ void clear(); /** Sets a flag that tells if we have some more children that are not fetched yet. */ void setHasMore(bool more); void setHasMoreInitial(bool more); TreeModel* model() { return model_; } bool isExpanded() const { return expanded_; } Q_SIGNALS: void expanded(); void collapsed(); void allChildrenFetched(); protected: // Backend implementation of Model/View friend class TreeModel; TreeItem *child(int row); int childCount() const; int columnCount() const; virtual QVariant data(int column, int role) const; int row() const; TreeItem *parent(); bool hasMore() const { return more_; } void setExpanded(bool b); virtual void clicked() {} virtual QVariant icon(int column) const; protected: QVector childItems; QVector itemData; TreeItem *parentItem; TreeModel *model_; bool more_; TreeItem *ellipsis_; bool expanded_; }; } #endif diff --git a/debugger/util/treemodel.h b/debugger/util/treemodel.h index f531c7db19..b14addeb43 100644 --- a/debugger/util/treemodel.h +++ b/debugger/util/treemodel.h @@ -1,91 +1,91 @@ /* * This file is part of KDevelop * * Copyright 2008 Vladimir Prus * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_TREEMODEL_H #define KDEVPLATFORM_TREEMODEL_H #include #include #include #include #include #include namespace KDevelop { class TreeItem; class KDEVPLATFORMDEBUGGER_EXPORT TreeModel : public QAbstractItemModel { Q_OBJECT public: explicit TreeModel(const QVector& headers, QObject *parent = 0); void setRootItem(TreeItem *item); - ~TreeModel(); + ~TreeModel() override; void expanded(const QModelIndex &index); void collapsed(const QModelIndex &index); void clicked(const QModelIndex &index); void setEditable(bool); TreeItem* root() const; enum { ItemRole = Qt::UserRole, }; public: // QAbstractItemModel overrides QVariant data(const QModelIndex &index, int role) const override; Qt::ItemFlags flags(const QModelIndex &index) const override; - virtual QVariant headerData(int section, Qt::Orientation orientation, + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; QModelIndex parent(const QModelIndex &index) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; bool setData(const QModelIndex& index, const QVariant& value, int role) override; Q_SIGNALS: void itemChildrenReady(); public: TreeItem* itemForIndex(const QModelIndex& index) const; QModelIndex indexForItem(TreeItem *item, int column) const; using QAbstractItemModel::beginInsertRows; using QAbstractItemModel::endInsertRows; using QAbstractItemModel::beginRemoveRows; using QAbstractItemModel::endRemoveRows; using QAbstractItemModel::dataChanged; private: QVector headers_; TreeItem *root_; bool editable_; }; } #endif diff --git a/debugger/util/treeview.h b/debugger/util/treeview.h index 23749623ac..920a2f7593 100644 --- a/debugger/util/treeview.h +++ b/debugger/util/treeview.h @@ -1,60 +1,60 @@ /* * This file is part of KDevelop * * Copyright 2008 Vladimir Prus * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_TREEVIEW_H #define KDEVPLATFORM_TREEVIEW_H #include #include class QSortFilterProxyModel; namespace KDevelop { class TreeModel; class KDEVPLATFORMDEBUGGER_EXPORT AsyncTreeView : public QTreeView { Q_OBJECT public: AsyncTreeView(TreeModel* model, QSortFilterProxyModel *proxy, QWidget *parent); - virtual QSize sizeHint() const override; + QSize sizeHint() const override; void resizeColumns(); // Well, I really, really, need this. using QTreeView::indexRowSizeHint; private Q_SLOTS: void slotExpanded(const QModelIndex &index); void slotCollapsed(const QModelIndex &index); void slotClicked(const QModelIndex &index); void slotExpandedDataReady(); private: QSortFilterProxyModel *m_proxy; }; } #endif diff --git a/debugger/variable/variablecollection.h b/debugger/variable/variablecollection.h index 6089ff3e9f..ed294964c2 100644 --- a/debugger/variable/variablecollection.h +++ b/debugger/variable/variablecollection.h @@ -1,249 +1,249 @@ /* * KDevelop Debugger Support * * Copyright 2007 Hamish Rodda * Copyright 2008 Vladimir Prus * Copyright 2009 Niko Sams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_VARIABLECOLLECTION_H #define KDEVPLATFORM_VARIABLECOLLECTION_H #include #include #include #include #include #include #include "../util/treemodel.h" #include "../util/treeitem.h" #include "../../interfaces/idocument.h" #include "../interfaces/idebugsession.h" #include "../../interfaces/idebugcontroller.h" namespace GDBDebugger { class GdbTest; } namespace KDevelop { class VariableToolTip; class KDEVPLATFORMDEBUGGER_EXPORT Variable : public TreeItem { Q_OBJECT friend class GDBDebugger::GdbTest; public: protected: Variable(TreeModel* model, TreeItem* parent, const QString& expression, const QString& display = {}); public: enum format_t { Natural, Binary, Octal, Decimal, Hexadecimal }; static format_t str2format(const QString& str); static QString format2str(format_t format); QString expression() const; bool inScope() const; void setInScope(bool v); void setValue(const QString &v); QString value() const; void setType(const QString& type); QString type() const; void setTopLevel(bool v); void setShowError(bool v); bool showError(); using TreeItem::setHasMore; using TreeItem::setHasMoreInitial; using TreeItem::appendChild; using TreeItem::deleteChildren; using TreeItem::isExpanded; using TreeItem::parent; using TreeItem::model; - ~Variable(); + ~Variable() override; /* Connects this variable to debugger, fetching the current value and otherwise preparing this variable to be displayed everywhere. The attempt may fail, for example if the expression is invalid. Calls slot 'callbackMethod' in 'callback' to notify of the result. The slot should be taking 'bool ok' parameter. */ virtual void attachMaybe(QObject *callback = 0, const char *callbackMethod = 0) = 0; virtual bool canSetFormat() const { return false; } void setFormat(format_t format); format_t format() const { return m_format; } virtual void formatChanged(); // get/set 'changed' state, if the variable changed it will be highlighted bool isChanged() const { return changed_; } void setChanged(bool c); void resetChanged(); public slots: void die(); protected: bool topLevel() const { return topLevel_; } private: // TreeItem overrides QVariant data(int column, int role) const override; private: QString expression_; bool inScope_; bool topLevel_; bool changed_; bool showError_; format_t m_format; }; class KDEVPLATFORMDEBUGGER_EXPORT TooltipRoot : public TreeItem { public: explicit TooltipRoot(TreeModel* model) : TreeItem(model) {} void init(Variable *var) { appendChild(var); } void fetchMoreChildren() override {} }; class KDEVPLATFORMDEBUGGER_EXPORT Watches : public TreeItem { friend class GDBDebugger::GdbTest; public: Watches(TreeModel* model, TreeItem* parent); Variable* add(const QString& expression); void reinstall(); Variable *addFinishResult(const QString& convenienceVarible); void removeFinishResult(); void resetChanged(); using TreeItem::childCount; friend class VariableCollection; friend class IVariableController; private: QVariant data(int column, int role) const override; void fetchMoreChildren() override {} Variable* finishResult_; }; class KDEVPLATFORMDEBUGGER_EXPORT Locals : public TreeItem { public: Locals(TreeModel* model, TreeItem* parent, const QString &name); QList updateLocals(QStringList locals); void resetChanged(); using TreeItem::deleteChildren; using TreeItem::setHasMore; friend class VariableCollection; friend class IVariableController; private: void fetchMoreChildren() override {} }; class KDEVPLATFORMDEBUGGER_EXPORT VariablesRoot : public TreeItem { public: explicit VariablesRoot(TreeModel* model); Watches *watches() const { return watches_; } Locals *locals(const QString &name = QLatin1String("Locals")); QHash allLocals() const; void fetchMoreChildren() override {} void resetChanged(); private: Watches *watches_; QHash locals_; }; class VariableProvider : public KTextEditor::TextHintProvider { public: explicit VariableProvider(VariableCollection* collection); - virtual QString textHint(KTextEditor::View* view, const KTextEditor::Cursor& position) override; + QString textHint(KTextEditor::View* view, const KTextEditor::Cursor& position) override; private: VariableCollection* m_collection; }; class KDEVPLATFORMDEBUGGER_EXPORT VariableCollection : public TreeModel { Q_OBJECT public: enum Column { NameColumn, ValueColumn, TypeColumn }; explicit VariableCollection(IDebugController* parent); - virtual ~VariableCollection(); + ~VariableCollection() override; VariablesRoot* root() const { return universe_; } Watches* watches() const { return universe_->watches(); } Locals* locals(const QString &name = i18n("Locals")) const { return universe_->locals(name); } QHash allLocals() const { return universe_->allLocals(); } public Q_SLOTS: void variableWidgetShown(); void variableWidgetHidden(); private Q_SLOTS: void updateAutoUpdate(KDevelop::IDebugSession* session = 0); void textDocumentCreated( KDevelop::IDocument*); void viewCreated(KTextEditor::Document*, KTextEditor::View*); private: VariablesRoot* universe_; QPointer activeTooltip_; bool m_widgetVisible; friend class VariableProvider; }; } #endif diff --git a/debugger/variable/variabletooltip.cpp b/debugger/variable/variabletooltip.cpp index c85426b0bf..a772f5f836 100644 --- a/debugger/variable/variabletooltip.cpp +++ b/debugger/variable/variabletooltip.cpp @@ -1,218 +1,218 @@ /* * KDevelop Debugger Support * * Copyright 2008 Vladimir Prus * Copyright 2009 Niko Sams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "variabletooltip.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "variablecollection.h" #include "../breakpoint/breakpointmodel.h" #include "../interfaces/ivariablecontroller.h" #include "../../util/activetooltip.h" #include "../../interfaces/icore.h" #include "../../interfaces/idebugcontroller.h" namespace KDevelop { class SizeGrip : public QWidget { public: SizeGrip(QWidget* parent) : QWidget(parent) { m_parent = parent; } protected: - virtual void paintEvent(QPaintEvent *) override + void paintEvent(QPaintEvent *) override { QPainter painter(this); QStyleOptionSizeGrip opt; opt.init(this); opt.corner = Qt::BottomRightCorner; style()->drawControl(QStyle::CE_SizeGrip, &opt, &painter, this); } - virtual void mousePressEvent(QMouseEvent* e) override + void mousePressEvent(QMouseEvent* e) override { if (e->button() == Qt::LeftButton) { m_pos = e->globalPos(); m_startSize = m_parent->size(); e->ignore(); } } - virtual void mouseReleaseEvent(QMouseEvent*) override + void mouseReleaseEvent(QMouseEvent*) override { m_pos = QPoint(); } - virtual void mouseMoveEvent(QMouseEvent* e) override + void mouseMoveEvent(QMouseEvent* e) override { if (!m_pos.isNull()) { m_parent->resize( m_startSize.width() + (e->globalPos().x() - m_pos.x()), m_startSize.height() + (e->globalPos().y() - m_pos.y()) ); } } private: QWidget *m_parent; QSize m_startSize; QPoint m_pos; }; VariableToolTip::VariableToolTip(QWidget* parent, QPoint position, const QString& identifier) : ActiveToolTip(parent, position) { setPalette( QApplication::palette() ); model_ = new TreeModel(QVector() << i18n("Name") << i18n("Value") << i18n("Type"), this); TooltipRoot* tr = new TooltipRoot(model_); model_->setRootItem(tr); var_ = ICore::self()->debugController()->currentSession()-> variableController()->createVariable( model_, tr, identifier); tr->init(var_); var_->attachMaybe(this, "variableCreated"); QVBoxLayout* l = new QVBoxLayout(this); l->setContentsMargins(0, 0, 0, 0); // setup proxy model proxy_ = new QSortFilterProxyModel; view_ = new AsyncTreeView(model_, proxy_, this); proxy_->setSourceModel(model_); view_->setModel(proxy_); view_->header()->resizeSection(0, 150); view_->header()->resizeSection(1, 90); view_->setSelectionBehavior(QAbstractItemView::SelectRows); view_->setSelectionMode(QAbstractItemView::SingleSelection); view_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); view_->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); l->addWidget(view_); itemHeight_ = view_->indexRowSizeHint(model_->indexForItem(var_, 0)); connect(view_->verticalScrollBar(), &QScrollBar::rangeChanged, this, &VariableToolTip::slotRangeChanged); selection_ = view_->selectionModel(); selection_->select(model_->indexForItem(var_, 0), QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect); QHBoxLayout* buttonBox = new QHBoxLayout(); buttonBox->setContentsMargins(11, 0, 11, 6); QPushButton* watchThisButton = new QPushButton(i18n("Watch this")); buttonBox->addWidget(watchThisButton); QPushButton* stopOnChangeButton = new QPushButton(i18n("Stop on Change")); buttonBox->addWidget(stopOnChangeButton); QSignalMapper* mapper = new QSignalMapper(this); connect(watchThisButton, &QPushButton::clicked, mapper, static_cast(&QSignalMapper::map)); mapper->setMapping(watchThisButton, "add_watch"); connect(stopOnChangeButton, &QPushButton::clicked, mapper, static_cast(&QSignalMapper::map)); mapper->setMapping(stopOnChangeButton, "add_watchpoint"); connect(mapper, static_cast(&QSignalMapper::mapped), this, &VariableToolTip::slotLinkActivated); QHBoxLayout* inner = new QHBoxLayout(); l->addLayout(inner); inner->setContentsMargins(0, 0, 0, 0); inner->addLayout(buttonBox); inner->addStretch(); SizeGrip* g = new SizeGrip(this); g->setFixedSize(16, 16); inner->addWidget(g, 0, (Qt::Alignment)(Qt::AlignRight | Qt::AlignBottom)); move(position); } void VariableToolTip::variableCreated(bool hasValue) { view_->resizeColumns(); if (hasValue) { ActiveToolTip::showToolTip(this, 0.0); } else { close(); } } void VariableToolTip::slotLinkActivated(const QString& link) { Variable* v = var_; QItemSelection s = selection_->selection(); if (!s.empty()) { QModelIndex index = s.front().topLeft(); TreeItem *item = model_->itemForIndex(index); if (item) { Variable* v2 = dynamic_cast(item); if (v2) v = v2; } } IDebugSession *session = ICore::self()->debugController()->currentSession(); if (session && session->state() != IDebugSession::NotStartedState && session->state() != IDebugSession::EndedState) { if (link == "add_watch") { session->variableController()->addWatch(v); } else if (link == "add_watchpoint") { session->variableController()->addWatchpoint(v); } } close(); } void VariableToolTip::slotRangeChanged(int min, int max) { Q_ASSERT(min == 0); Q_UNUSED(min); QRect rect = QApplication::desktop()->screenGeometry(this); if (pos().y() + height() + max*itemHeight_ < rect.bottom()) resize(width(), height() + max*itemHeight_); else { // Oh, well, I'm sorry, but here's the scrollbar you was // longing to see view_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); } } } diff --git a/debugger/variable/variablewidget.h b/debugger/variable/variablewidget.h index 3758ae7d0f..16ce290d2b 100644 --- a/debugger/variable/variablewidget.h +++ b/debugger/variable/variablewidget.h @@ -1,119 +1,119 @@ /*************************************************************************** begin : Sun Aug 8 1999 copyright : (C) 1999 by John Birch email : jbb@kdevelop.org ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_VARIABLEWIDGET_H #define KDEVPLATFORM_VARIABLEWIDGET_H #include #include #include #include #include "../util/treeview.h" #include "variablecollection.h" class KHistoryComboBox; class QSortFilterProxyModel; namespace KDevelop { class IDebugController; class TreeModel; class VariableTree; class AbstractVariableItem; class KDEVPLATFORMDEBUGGER_EXPORT VariableWidget : public QWidget { Q_OBJECT public: explicit VariableWidget( IDebugController *controller, QWidget *parent=0 ); Q_SIGNALS: void requestRaise(); void addWatchVariable(const QString& indent); void evaluateExpression(const QString& indent); public Q_SLOTS: void slotAddWatch(const QString &ident); protected: - virtual void showEvent(QShowEvent* e) override; - virtual void hideEvent(QHideEvent* e) override; + void showEvent(QShowEvent* e) override; + void hideEvent(QHideEvent* e) override; private: VariableTree *varTree_; KHistoryComboBox *watchVarEditor_; VariablesRoot *variablesRoot_; QSortFilterProxyModel *m_proxy; }; /***************************************************************************/ /***************************************************************************/ /***************************************************************************/ class VariableTree : public KDevelop::AsyncTreeView { Q_OBJECT public: VariableTree(IDebugController *controller, VariableWidget *parent, QSortFilterProxyModel *proxy); - virtual ~VariableTree(); + ~VariableTree() override; VariableCollection* collection() const; private: void setupActions(); - virtual void contextMenuEvent(QContextMenuEvent* event) override; + void contextMenuEvent(QContextMenuEvent* event) override; Variable *selectedVariable() const; private slots: void changeVariableFormat(int); void watchDelete(); void copyVariableValue(); void stopOnChange(); #if 0 Q_SIGNALS: void toggleWatchpoint(const QString &varName); protected: virtual void contextMenuEvent(QContextMenuEvent* event); virtual void keyPressEvent(QKeyEvent* e); virtual void showEvent(QShowEvent* event); private: // helper functions void handleAddressComputed(const GDBMI::ResultRecord& r); void updateCurrentFrame(); void copyToClipboard(AbstractVariableItem* item); QMenu* activePopup_; QAction* toggleWatch_; #endif private: QAction *m_contextMenuTitle; QMenu *m_formatMenu; QAction *m_watchDelete; QAction *m_copyVariableValue; QAction *m_stopOnChange; QSignalMapper *m_signalMapper; QSortFilterProxyModel *m_proxy; TreeModel *m_model; }; } #endif diff --git a/documentation/documentationview.h b/documentation/documentationview.h index 8605c6a552..5f7f6d8bb1 100644 --- a/documentation/documentationview.h +++ b/documentation/documentationview.h @@ -1,100 +1,100 @@ /* Copyright 2009 Aleix Pol Gonzalez Copyright 2010 Benjamin Port 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. */ #ifndef KDEVPLATFORM_DOCUMENTATIONVIEW_H #define KDEVPLATFORM_DOCUMENTATIONVIEW_H #include #include #include #include #include "documentationexport.h" namespace KDevelop { class IPlugin; class DocumentationFindWidget; } class QModelIndex; class QLineEdit; class ProvidersModel; class QComboBox; class KDEVPLATFORMDOCUMENTATION_EXPORT DocumentationView : public QWidget { Q_OBJECT public: DocumentationView(QWidget* parent, ProvidersModel* m); void showDocumentation(const KDevelop::IDocumentation::Ptr& doc); public slots: void initialize(); void addHistory(const KDevelop::IDocumentation::Ptr& doc); void emptyHistory(); void browseForward(); void browseBack(); void changedSelection(); void changedProvider(int); void changeProvider(const QModelIndex &); void showHome(); private: void updateView(); KToolBar* mActions; QAction* mForward; QAction* mBack; QAction* mFind; QLineEdit* mIdentifiers; QList< KDevelop::IDocumentation::Ptr > mHistory; QList< KDevelop::IDocumentation::Ptr >::iterator mCurrent; QComboBox* mProviders; ProvidersModel* mProvidersModel; KDevelop::DocumentationFindWidget* mFindDoc; }; class KDEVPLATFORMDOCUMENTATION_EXPORT ProvidersModel : public QAbstractListModel { Q_OBJECT public: explicit ProvidersModel(QObject* parent = 0); - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - virtual int rowCount(const QModelIndex& idx = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + int rowCount(const QModelIndex& idx = QModelIndex()) const override; QList providers(); KDevelop::IDocumentationProvider* provider(int pos) const; int rowForProvider(KDevelop::IDocumentationProvider* provider); public slots: void unloaded(KDevelop::IPlugin* p); void loaded(KDevelop::IPlugin* p); void reloadProviders(); private: void removeProviders(const QList &provider); QList mProviders; signals: void providersChanged(); }; #endif // KDEVPLATFORM_DOCUMENTATIONVIEW_H diff --git a/interfaces/configpage.h b/interfaces/configpage.h index d641ab11ae..1cd5fd39f2 100644 --- a/interfaces/configpage.h +++ b/interfaces/configpage.h @@ -1,110 +1,110 @@ /* * This file is part of KDevelop * Copyright 2014 Alex Richardson * * 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 KDEVELOP_CONFIGPAGE_H #define KDEVELOP_CONFIGPAGE_H #include #include #include #include #include "interfacesexport.h" namespace KDevelop { class IPlugin; struct ConfigPagePrivate; class KDEVPLATFORMINTERFACES_EXPORT ConfigPage : public KTextEditor::ConfigPage { Q_OBJECT public: /** * Create a new config page * @param plugin the plugin that created this config page * @param config the config skeleton that is used to store the preferences. If you don't use * a K(Core)ConfigSkeleton to save the settings you can also pass null here. * However this means that you will have to manually implement the apply(), defaults() and reset() slots */ explicit ConfigPage(IPlugin* plugin, KCoreConfigSkeleton* config = nullptr, QWidget* parent = nullptr); - virtual ~ConfigPage(); + ~ConfigPage() override; /** * Get the number of subpages of this page * @return The number of child pages or an integer < 1 if there are none. * The default implementation returns zero. */ virtual int childPages() const; /** * @return the child config page for index @p number or @c nullptr if there is none. * The default implementation returns @c nullptr. */ virtual ConfigPage* childPage(int number); enum ConfigPageType { DefaultConfigPage, LanguageConfigPage ///< A config page that contains language specific settings. This page is appended as a child page to the "Language support" config page. }; /** * @return The type of this config page. Default implementaion returns DefaultConfigPageType */ virtual ConfigPageType configPageType() const; /** * @return the plugin that this config page was created by or nullptr if it was not created by a plugin. */ IPlugin* plugin() const; /** * Initializes the KConfigDialogManager. * Must be called explicitly since not all child widgets are available at the end of the constructor. * This is handled automatically by KDevelop::ConfigDialog, subclasses don't need to call this. */ void initConfigManager(); /** * @return the KCoreConfigSkeleton used to store the settings for this page or @c nullptr * if settings are managed differently */ KCoreConfigSkeleton* configSkeleton() const; /** * Sets the config skeleton to @p skel and will create a KConfigDialogManager if needed. * This can be used if the KCoreConfigSkeleton* doesn't exist yet when calling the base class constructor. */ void setConfigSkeleton(KCoreConfigSkeleton* skel); public Q_SLOTS: - virtual void apply() override; - virtual void defaults() override; - virtual void reset() override; + void apply() override; + void defaults() override; + void reset() override; private: QScopedPointer d; }; } #endif // KDEVELOP_CONFIGPAGE_H diff --git a/interfaces/iassistant.h b/interfaces/iassistant.h index 3999bb4bf8..3f93d525d9 100644 --- a/interfaces/iassistant.h +++ b/interfaces/iassistant.h @@ -1,151 +1,151 @@ /* Copyright 2009 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. */ #ifndef KDEVPLATFORM_IASSISTANT_H #define KDEVPLATFORM_IASSISTANT_H #include #include #include #include "interfacesexport.h" #include class QAction; namespace KDevelop { ///Represents a single assistant action. ///Subclass it to create your own actions. class KDEVPLATFORMINTERFACES_EXPORT IAssistantAction : public QObject, public KSharedObject { Q_OBJECT public: IAssistantAction(); typedef QExplicitlySharedDataPointer Ptr; - virtual ~IAssistantAction(); + ~IAssistantAction() override; ///Creates a QAction that represents this exact assistant action. ///The caller owns the action, and is responsible for deleting it. virtual QAction* toKAction() const; ///Should return a short description of the action. ///It may contain simple HTML formatting. ///Must be very short, so it nicely fits into the assistant popups. virtual QString description() const = 0; ///May return additional tooltip hover information. ///The default implementation returns an empty string. virtual QString toolTip() const; ///May return an icon for this action. ///The default implementation returns an invalid icon, which means that no icon is shown. virtual QIcon icon() const; public Q_SLOTS: /** * Execute this action. * * NOTE: Implementations should properly emit executed(this) after being executed. */ virtual void execute() = 0; Q_SIGNALS: /** * Gets emitted when this action was executed. */ void executed(IAssistantAction* action); }; /** * A fake action that only shows a label. */ class KDEVPLATFORMINTERFACES_EXPORT AssistantLabelAction : public IAssistantAction { Q_OBJECT public: /** * @p description The label to show. */ explicit AssistantLabelAction(const QString& description); /** * @return the label contents. */ - virtual QString description() const override; + QString description() const override; /** * The label cannot be executed. */ - virtual void execute() override; + void execute() override; /** * No action is returned. */ - virtual QAction* toKAction() const override; + QAction* toKAction() const override; private: QString m_description; }; ///Represents a single assistant popup. ///Subclass it to create your own assistants. class KDEVPLATFORMINTERFACES_EXPORT IAssistant : public QObject, public KSharedObject { Q_OBJECT public: IAssistant(); - virtual ~IAssistant(); + ~IAssistant() override; typedef QExplicitlySharedDataPointer Ptr; ///Returns the stored list of actions QList actions() const; ///Implement this and have it create the actions for your assistant. ///It will only be called if the assistant is displayed, which saves ///memory compared to creating the actions right away. ///Default implementation does nothing. virtual void createActions(); ///Adds the given action to the list of actions. ///Does not emit actionsChanged(), you have to do that when you're ready. virtual void addAction(const IAssistantAction::Ptr& action); ///Clears the stored list of actions. ///Does not emit actionsChanged(), you have to do that when you're ready. virtual void clearActions(); ///May return an icon for this assistant virtual QIcon icon() const; ///May return the title of this assistant ///The text may be html formatted. If it can be confused with HTML, ///use Qt::escape(..). virtual QString title() const; public Q_SLOTS: ///Emits hide(), which causes this assistant to be hidden virtual void doHide(); Q_SIGNALS: ///Can be emitted by the assistant when it should be hidden void hide(); ///Can be emitted by the assistant when its actions have changed and should be re-read void actionsChanged(); private: QList m_actions; }; } #endif // KDEVPLATFORM_IASSISTANT_H diff --git a/interfaces/icompletionsettings.h b/interfaces/icompletionsettings.h index 4b95c5184c..8066360b42 100644 --- a/interfaces/icompletionsettings.h +++ b/interfaces/icompletionsettings.h @@ -1,65 +1,65 @@ /*************************************************************************** * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_ICOMPLETIONSETTINGS_H #define KDEVPLATFORM_ICOMPLETIONSETTINGS_H #include #include "interfacesexport.h" namespace KDevelop { class KDEVPLATFORMINTERFACES_EXPORT ICompletionSettings : public QObject { Q_OBJECT public: - virtual ~ICompletionSettings(); + ~ICompletionSettings() override; enum CompletionLevel { Minimal, MinimalWhenAutomatic, AlwaysFull, LAST_LEVEL }; Q_SCRIPTABLE virtual int minFilesForSimplifiedParsing() const = 0; Q_SCRIPTABLE virtual CompletionLevel completionLevel() const = 0; Q_SCRIPTABLE virtual bool automaticCompletionEnabled() const = 0; Q_SCRIPTABLE virtual int localColorizationLevel() const = 0; Q_SCRIPTABLE virtual int globalColorizationLevel() const = 0; Q_SCRIPTABLE virtual bool highlightSemanticProblems() const = 0; Q_SCRIPTABLE virtual bool highlightProblematicLines() const = 0; Q_SCRIPTABLE virtual bool boldDeclarations() const = 0; Q_SCRIPTABLE virtual bool showMultiLineSelectionInformation() const = 0; Q_SCRIPTABLE virtual QStringList todoMarkerWords() const = 0; Q_SIGNALS: void settingsChanged(ICompletionSettings*); }; } #endif diff --git a/interfaces/icore.h b/interfaces/icore.h index cd6ccb3afc..f7fa836e3a 100644 --- a/interfaces/icore.h +++ b/interfaces/icore.h @@ -1,154 +1,154 @@ /* This file is part of KDevelop Copyright 2007 Alexander Dymo Copyright 2007 Kris Wong 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 KDEVPLATFORM_ICORE_H #define KDEVPLATFORM_ICORE_H #include #include "interfacesexport.h" #include "isessionlock.h" class KAboutData; namespace KParts { class PartManager; } /** * The KDevelop namespace contains all classes provided by the KDevelop * platform libraries. */ namespace KDevelop { class IUiController; class IPluginController; class IProjectController; class ILanguageController; class IDocumentController; class ISessionController; class IRunController; class ISourceFormatterController; class ISession; class ISelectionController; class IDocumentationController; class IDebugController; class IPartController; class IDashboardController; class ITestController; /** * ICore is the container class for all the various objects in use by * KDevelop. If access is needed to a particular controller, then this class * should be used. * * ICore can provide the user with instances of the following things: * - the main window(s) * - the document controller(s) * - the plugin controller * - the project controller * - the language controller * - the KPart manager * * When an object is provided to ICore so it can be used later, ICore * will take ownership of the object and upon application shutdown will take * responsibility for deleting the objects stored by ICore. */ class KDEVPLATFORMINTERFACES_EXPORT ICore: public QObject { Q_OBJECT public: - virtual ~ICore(); + ~ICore() override; /** @return the static ICore instance */ static ICore *self(); /** @return ui controller */ Q_SCRIPTABLE virtual KDevelop::IUiController *uiController() = 0; /** @return plugin controller */ Q_SCRIPTABLE virtual KDevelop::IPluginController *pluginController() = 0; /** @return project controller */ Q_SCRIPTABLE virtual KDevelop::IProjectController *projectController() = 0; /** @return language controller */ Q_SCRIPTABLE virtual KDevelop::ILanguageController *languageController() = 0; /** @return part manager */ Q_SCRIPTABLE virtual KDevelop::IPartController *partController() = 0; /** @return document controller */ Q_SCRIPTABLE virtual KDevelop::IDocumentController *documentController() = 0; /** @return run controller */ Q_SCRIPTABLE virtual KDevelop::IRunController *runController() = 0; /** @return the active session */ Q_SCRIPTABLE virtual KDevelop::ISession *activeSession() = 0; /** @return the session lock for the active session */ Q_SCRIPTABLE virtual KDevelop::ISessionLock::Ptr activeSessionLock() = 0; /** @return the sourceformatter controller */ Q_SCRIPTABLE virtual KDevelop::ISourceFormatterController *sourceFormatterController() = 0; /** @return the selection controller */ Q_SCRIPTABLE virtual KDevelop::ISelectionController* selectionController() = 0; /** @return the documentation controller */ Q_SCRIPTABLE virtual KDevelop::IDocumentationController* documentationController() = 0; /** @return the debug controller */ Q_SCRIPTABLE virtual KDevelop::IDebugController* debugController() = 0; /** @return the test controller */ Q_SCRIPTABLE virtual KDevelop::ITestController* testController() = 0; /** @return the about data of the framework, different from the main about data which is created by the application */ virtual KAboutData aboutData() const = 0; /** @return true if the application is currently being shut down */ virtual bool shuttingDown() const = 0; Q_SIGNALS: /** Emitted when the initialization of the core components has been completed */ void initializationCompleted(); /** * Emitted immediately before tearing down the session and UI. Useful when performing any last minute * preparations such as saving settings. */ void aboutToShutdown(); /** * Emitted when the teardown of the core components has been completed. */ void shutdownCompleted(); protected: ICore(QObject *parent = 0); static ICore *m_self; }; } #endif diff --git a/interfaces/idebugcontroller.h b/interfaces/idebugcontroller.h index 0bf3711d65..c18bd54bd8 100644 --- a/interfaces/idebugcontroller.h +++ b/interfaces/idebugcontroller.h @@ -1,65 +1,65 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2009 Niko Sams * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_IDEBUGCONTROLLER_H #define KDEVPLATFORM_IDEBUGCONTROLLER_H #include #include "interfacesexport.h" namespace KDevelop { class VariableCollection; class BreakpointModel; class FrameStackModel; class IDebugSession; /** Top level debugger object. Exists as long as KDevelop exists and holds some global debugger state, like breakpoints. Also holds the IDebugSession for the specific application that is being debugged. */ class KDEVPLATFORMINTERFACES_EXPORT IDebugController : public QObject { Q_OBJECT public: explicit IDebugController(QObject *parent = 0); - virtual ~IDebugController(); + ~IDebugController() override; /** Each plugin using the debugger actions needs to call this function to setup the gui */ virtual void initializeUi() = 0; virtual void addSession(IDebugSession* session) = 0; /** Return the current debug session. At present, only one session may be active at a time. */ virtual IDebugSession *currentSession() = 0; virtual BreakpointModel *breakpointModel() = 0; virtual VariableCollection *variableCollection() = 0; Q_SIGNALS: void currentSessionChanged(KDevelop::IDebugSession* session); }; } #endif diff --git a/interfaces/idocumentationcontroller.h b/interfaces/idocumentationcontroller.h index 7e47962860..1d0e777291 100644 --- a/interfaces/idocumentationcontroller.h +++ b/interfaces/idocumentationcontroller.h @@ -1,62 +1,62 @@ /* Copyright 2009 Aleix Pol Gonzalez Copyright 2010 Benjamin Port 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. */ #ifndef KDEVPLATFORM_IDOCUMENTATIONCONTROLLER_H #define KDEVPLATFORM_IDOCUMENTATIONCONTROLLER_H #include #include namespace KDevelop { class IDocumentationProvider; class Declaration; /** * Allows to access the documentation. * * @author Aleix Pol */ class KDEVPLATFORMINTERFACES_EXPORT IDocumentationController: public QObject { Q_OBJECT public: IDocumentationController(); - virtual ~IDocumentationController(); + ~IDocumentationController() override; /** Return the documentation provider plugin instances. */ virtual QList documentationProviders() const = 0; /** Return the corresponding documentation instance for a determinate declaration. */ virtual IDocumentation::Ptr documentationForDeclaration(Declaration* declaration) = 0; /** Show the documentation specified by @p doc. */ virtual void showDocumentation(const IDocumentation::Ptr& doc) = 0; public Q_SLOTS: /** Emit signal when the documentation providers list changed. */ virtual void changedDocumentationProviders() = 0; Q_SIGNALS: /** Emitted when providers list changed */ void providersChanged(); }; } #endif diff --git a/interfaces/iplugin.h b/interfaces/iplugin.h index 0c0dcea726..f67cb5d8bd 100644 --- a/interfaces/iplugin.h +++ b/interfaces/iplugin.h @@ -1,279 +1,279 @@ /* This file is part of the KDE project Copyright 1999-2001 Bernd Gehrmann Copyright 2004,2007 Alexander Dymo Copyright 2006 Adam Treat Copyright 2007 Andreas Pakulat 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 KDEVPLATFORM_IPLUGIN_H #define KDEVPLATFORM_IPLUGIN_H #include #include #include #include "interfacesexport.h" namespace Sublime { class MainWindow; } /** * This macro adds an extension interface to register with the extension manager * Call this macro for all interfaces your plugin implements in its constructor */ #define KDEV_USE_EXTENSION_INTERFACE(Extension) \ addExtension(QByteArray::fromRawData(qobject_interface_iid(), \ static_cast(strlen(qobject_interface_iid())))); namespace KDevelop { class ICore; class ConfigPage; class Context; class ContextMenuExtension; struct ProjectConfigOptions; /** * The base class for all KDevelop plugins. * * Plugin is a component which is loaded into KDevelop shell at startup or by * request. Each plugin should have corresponding .desktop file with a * description. The .desktop file template looks like: * @code * [Desktop Entry] * Type=Service * Exec=blubb * Name= * GenericName= * Comment= * Icon= * ServiceTypes=KDevelop/Plugin * X-KDE-Library= * X-KDE-PluginInfo-Name= * X-KDE-PluginInfo-Author= * X-KDE-PluginInfo-Version= * X-KDE-PluginInfo-License= * X-KDE-PluginInfo-Category= * X-KDevelop-Version= * X-KDevelop-Category= * X-KDevelop-Mode=GUI * X-KDevelop-LoadMode= * X-KDevelop-Language= * X-KDevelop-SupportedMimeTypes= * X-KDevelop-Interfaces= * X-KDevelop-IOptional= * X-KDevelop-IRequired= * @endcode * Description of parameters in .desktop file: * - Name is a translatable name of a plugin, it is used in the plugin * selection list (required); * - GenericName is a translatable generic name of a plugin, it should * describe in general what the plugin can do (required); * - Comment is a short description about the plugin (optional); * - Icon is a plugin icon (preferred); * X-KDE-librarythis is the name of the .so file to load for this plugin (required); * - X-KDE-PluginInfo-Name is a non-translatable user-readable plugin * identifier used in KTrader queries (required); * - X-KDE-PluginInfo-Author is a non-translateable name of the plugin * author (optional); * - X-KDE-PluginInfo-Version is version number of the plugin (optional); * - X-KDE-PluginInfo-License is a license (optional). can be: GPL, * LGPL, BSD, Artistic, QPL or Custom. If this property is not set, license is * considered as unknown; * - X-KDE-PluginInfo-Category is used to categorize plugins (optional). can be: * Core, Project Management, Version Control, Utilities, Documentation, * Language Support, Debugging, Other * If this property is not set, "Other" is assumed * - X-KDevelop-Version is the KDevPlatform API version this plugin * works with (required); * - X-KDevelop-Interfaces is a list of extension interfaces that this * plugin implements (optional); * - X-KDevelop-IRequired is a list of extension interfaces that this * plugin depends on (optional); A list entry can also be of the form @c interface@pluginname, * in which case a plugin of the given name is required which implements the interface. * - X-KDevelop-IOptional is a list of extension interfaces that this * plugin will use if they are available (optional); * - X-KDevelop-Language is the name of the language the plugin provides * support for (optional); * - X-KDevelop-SupportedMimeTypes is a list of mimetypes that the * language-parser in this plugin supports (optional); * - X-KDevelop-Mode is either GUI or NoGUI to indicate whether a plugin can run * with the GUI components loaded or not (required); * - X-KDevelop-Category is a scope of a plugin (see below for * explanation) (required); * - X-KDevelop-LoadMode can be set to AlwaysOn in which case the plugin will * never be unloaded even if requested via the API. (optional); * * Plugin scope can be either: * - Global * - Project * . * Global plugins are plugins which require only the shell to be loaded and do not operate on * the Project interface and/or do not use project wide information.\n * Core plugins are global plugins which offer some important "core" functionality and thus * are not selectable by user in plugin configuration pages.\n * Project plugins require a project to be loaded and are usually loaded/unloaded along with * the project. * If your plugin uses the Project interface and/or operates on project-related * information then this is a project plugin. * * * @sa Core class documentation for information about features available to * plugins from shell applications. */ class KDEVPLATFORMINTERFACES_EXPORT IPlugin: public QObject, public KXMLGUIClient { Q_OBJECT public: /**Constructs a plugin. * @param componentName The component name for this plugin. * @param parent The parent object for the plugin. */ IPlugin(const QString &componentName, QObject *parent); /**Destructs a plugin.*/ - virtual ~IPlugin(); + ~IPlugin() override; /** * Signal the plugin that it should cleanup since it will be unloaded soon. */ Q_SCRIPTABLE virtual void unload(); /** * Provides access to the ICore implementation */ Q_SCRIPTABLE ICore *core() const; Q_SCRIPTABLE QVector extensions() const; template Extension* extension() { const auto extensionIID = QByteArray::fromRawData(qobject_interface_iid(), static_cast(strlen(qobject_interface_iid()))); if (extensions().contains(extensionIID)) { return qobject_cast(this); } return nullptr; } /** * Ask the plugin for a ContextActionContainer, which contains actions * that will be merged into the context menu. * @param context the context describing where the context menu was requested * @returns a container describing which actions to merge into which context menu part */ virtual ContextMenuExtension contextMenuExtension( KDevelop::Context* context ); /** * Can create a new KXMLGUIClient, and set it up correctly with all the plugins per-window GUI actions. * * The caller owns the created object, including all contained actions. The object is destroyed as soon as * the mainwindow is closed. * * The default implementation calls the convenience function @ref createActionsForMainWindow and uses it to fill a custom KXMLGUIClient. * * Only override this version if you need more specific features of KXMLGUIClient, or other special per-window handling. * * @param window The main window the actions are created for */ virtual KXMLGUIClient* createGUIForMainWindow( Sublime::MainWindow* window ); /** * This function allows allows setting up plugin actions conveniently. Unless createGUIForMainWindow was overridden, * this is called for each new mainwindow, and the plugin should add its actions to @p actions, and write its KXMLGui xml file * into @p xmlFile. * * @param window The main window the actions are created for * @param xmlFile Change this to the xml file that needed for merging the actions into the GUI * @param actions Add your actions here. A new set of actions has to be created for each mainwindow. */ virtual void createActionsForMainWindow( Sublime::MainWindow* window, QString& xmlFile, KActionCollection& actions ); /** * 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. */ virtual bool hasError() const; /** * Description of the last encountered error, of an empty string if none. */ virtual QString errorDescription() const; /** * Get the global config page with the \p number, config pages from 0 to * configPages()-1 are available if configPages() > 0. * * @param number index of config page * @param options The options used to initialize the ProjectConfigPage * @param parent parent widget for config page * @return newly created config page or NULL, if the number is out of bounds, default implementation returns NULL. * This config page should inherit from ProjectConfigPage, but it is not a strict requirement. * The default implementation returns @c nullptr. * @see perProjectConfigPages(), ProjectConfigPage */ virtual ConfigPage* configPage(int number, QWidget *parent); /** * Get the number of available config pages for global settings. * @return number of global config pages. The default implementation returns zero. * @see configPage() */ virtual int configPages() const; /** * Get the number of available config pages for per project settings. * @return number of per project config pages. The default implementation returns zero. * @see perProjectConfigPage() */ virtual int perProjectConfigPages() const; /** * Get the per project config page with the \p number, config pages from 0 to * perProjectConfigPages()-1 are available if perProjectConfigPages() > 0. * * @param number index of config page * @param options The options used to initialize the ProjectConfigPage * @param parent parent widget for config page * @return newly created config page or NULL, if the number is out of bounds, default implementation returns NULL. * This config page should inherit from ProjectConfigPage, but it is not a strict requirement. * The default implementation returns @c nullptr. * @see perProjectConfigPages(), ProjectConfigPage */ virtual ConfigPage* perProjectConfigPage(int number, const KDevelop::ProjectConfigOptions& options, QWidget* parent); protected: void addExtension( const QByteArray& ); /** * Initialize the XML GUI State. */ virtual void initializeGuiState(); private: friend class IPluginPrivate; class IPluginPrivate* const d; }; } #endif diff --git a/interfaces/iplugincontroller.h b/interfaces/iplugincontroller.h index ff7a54873a..bf3883a1b6 100644 --- a/interfaces/iplugincontroller.h +++ b/interfaces/iplugincontroller.h @@ -1,199 +1,199 @@ /* This file is part of the KDE project Copyright 2004, 2007 Alexander Dymo Copyright 2006 Matt Rogers Copyright 2007 Andreas Pakulat Based on code from Kopete Copyright 2002-2003 Martijn Klingens 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 KDEVPLATFORM_IPLUGINCONTROLLER_H #define KDEVPLATFORM_IPLUGINCONTROLLER_H #include #include #include #include "iplugin.h" #include "interfacesexport.h" class QExtensionManager; namespace KDevelop { class ProfileEngine; /** * The KDevelop plugin controller. * The Plugin controller is responsible for querying, loading and unloading * available plugins. * * Most of the time if you want to get at a plugin you should be using * extensionForPlugin with the extension interface name. If you need to get at * the actual \c IPlugin* pointer to connect signals/slots you should use * \c pluginForExtension() and then the IPlugin's extension member function to get * at the extension interface if necessary. * * If you have the need to load a specific plugin for a given extension both * functions have an optional second parameter that allows to specify the name * of the plugin as declared in the \c .desktop file under the * \c X-KDE-PluginInfo-Name property. This should be used only very seldomly in * real code and is mostly meant for testing and for implementation in the * shell as it makes the code dependent on the plugin name which may change and * also the actual plugin implementation so users cannot exchange one plugin * with another also implementing the same interface. * */ class KDEVPLATFORMINTERFACES_EXPORT IPluginController : public QObject { Q_OBJECT public: /** * \brief Indicates the plugin type * This is used to determine how the plugin is loaded */ enum PluginType { Global = 0, ///< Indicates that the plugin is loaded at startup Project ///< Indicates that the plugin is loaded with the first opened project }; explicit IPluginController( QObject* parent = 0 ); - virtual ~IPluginController(); + ~IPluginController() override; /** * Get the plugin info for a loaded plugin */ virtual KPluginMetaData pluginInfo(const IPlugin*) const = 0; /** * Find the KPluginMetaData structure for the given @p pluginId. */ virtual KPluginMetaData infoForPluginId(const QString &pluginId) const = 0; /** * Get a list of currently loaded plugins */ Q_SCRIPTABLE virtual QList loadedPlugins() const = 0; /** * @brief Unloads the plugin specified by @p plugin * * @param plugin The name of the plugin as specified by the * X-KDE-PluginInfo-Name key of the .desktop file for the plugin */ Q_SCRIPTABLE virtual bool unloadPlugin( const QString & plugin ) = 0; /** * @brief Loads the plugin specified by @p pluginName * * @param pluginName the name of the plugin, as given in the X-KDE-PluginInfo-Name property * @returns a pointer to the plugin instance or 0 */ Q_SCRIPTABLE virtual IPlugin* loadPlugin( const QString & pluginName ) = 0; /** * Retrieve a plugin which supports the given extension interface. * * All already loaded plugins will be queried and the first one to support the extension interface * will be returned. Any plugin can be an extension, only the "ServiceTypes=..." entry is * required in .desktop file for that plugin. * * If no already-loaded plugin was found, we try to load a plugin for the given extension. * * If no plugin was found, a nullptr will be returned. * * @param extension The extension interface. Can be empty if you want to find a plugin by name or other constraint. * @param pluginName The name of the plugin to load if multiple plugins for the extension exist, corresponds to the X-KDE-PluginInfo-Name * @param constraints A map of constraints on other plugin info properties. * @return A KDevelop extension plugin for given service type or 0 if no plugin supports it */ Q_SCRIPTABLE virtual IPlugin *pluginForExtension(const QString &extension, const QString& pluginName = {}, const QVariantMap& constraints = QVariantMap()) = 0; /** * Retrieve a list of plugins which supports the given extension interface. * All already loaded plugins will be queried and the first one to support the extension interface * will be returned. Any plugin can be an extension, only the "ServiceTypes=..." entry is * required in .desktop file for that plugin. * @param extension The extension interface * @param constraints A map of constraints on other plugin info properties. * @return A KDevelop extension plugin for given service type or 0 if no plugin supports it */ virtual QList allPluginsForExtension(const QString &extension, const QVariantMap& constraints = QVariantMap()) = 0; /** * Retrieve the plugin which supports given extension interface and * returns a pointer to the extension interface. * * All already loaded plugins will be queried and the first one to support the extension interface * will be returned. Any plugin can be an extension, only "ServiceTypes=..." entry is * required in .desktop file for that plugin. * @param extension The extension interface * @param pluginName The name of the plugin to load if multiple plugins for the extension exist, corresponds to the X-KDE-PluginInfo-Name * @return Pointer to the extension interface or 0 if no plugin supports it */ template Extension* extensionForPlugin( const QString &extension = {}, const QString &pluginName = {}) { QString ext; if( extension.isEmpty() ) { ext = qobject_interface_iid(); } else { ext = extension; } IPlugin *plugin = pluginForExtension(ext, pluginName); if (plugin) { return plugin->extension(); } return 0L; } /** * Query for plugin information on KDevelop plugins implementing the given extension. * * The service version is checked for automatically and the only serviceType * searched for is "KDevelop/Plugin" * * @param extension The extension that should be implemented by the plugin, i.e. listed in X-KDevelop-Interfaces. * @param constraints A map of constraints on other plugin info properties. * @return The list of plugin offers. */ virtual QVector queryExtensionPlugins(const QString &extension, const QVariantMap& constraints = QVariantMap()) const = 0; virtual QList queryPluginsForContextMenuExtensions( KDevelop::Context* context ) const = 0; Q_SIGNALS: void loadingPlugin( const QString& ); void pluginLoaded( KDevelop::IPlugin* ); void unloadingPlugin( KDevelop::IPlugin* ); /** * This signal is emitted whenever a plugin is unloaded. * @note: that you shouldn't use the pointer anymore * except for comparing it against against other pointers. The plugin instance can already have been completely * deleted when this signal is emitted. */ void pluginUnloaded( KDevelop::IPlugin* ); private: friend class IPlugin; }; } #endif diff --git a/interfaces/iproject.h b/interfaces/iproject.h index 6010b8b4b0..54d9fbeae5 100644 --- a/interfaces/iproject.h +++ b/interfaces/iproject.h @@ -1,180 +1,180 @@ /* This file is part of the KDE project Copyright 2001 Matthias Hoelzer-Kluepfel Copyright 2001-2002 Bernd Gehrmann Copyright 2002-2003 Roberto Raggi Copyright 2002 Simon Hausmann Copyright 2003 Jens Dagerbo Copyright 2003 Mario Scalas Copyright 2003-2004 Alexander Dymo Copyright 2006 Matt Rogers Copyright 2007 Andreas Pakulat 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 KDEVPLATFORM_IPROJECT_H #define KDEVPLATFORM_IPROJECT_H #include #include #include #include "interfacesexport.h" class KJob; template class QList; template class QSet; namespace KDevelop { class IPlugin; class IProjectFileManager; class IBuildSystemManager; class Path; class ProjectBaseItem; class ProjectFileItem; class ProjectFolderItem; class IndexedString; /** * \brief Object which represents a KDevelop project * * Provide better descriptions */ class KDEVPLATFORMINTERFACES_EXPORT IProject : public QObject { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kdevelop.Project") Q_PROPERTY(QString projectName READ name CONSTANT) public: /** * Constructs a project. * * @param parent The parent object for the plugin. */ explicit IProject(QObject *parent = 0); /// Destructor. - virtual ~IProject(); + ~IProject() override; /** * Get the file manager for the project * * @return the file manager for the project, if one exists; otherwise null */ Q_SCRIPTABLE virtual IProjectFileManager* projectFileManager() const = 0; /** * Get the build system manager for the project * * @return the build system manager for the project, if one exists; otherwise null */ Q_SCRIPTABLE virtual IBuildSystemManager* buildSystemManager() const = 0; /** * Get the plugin that manages the project * This can be used to get other interfaces like IBuildSystemManager */ Q_SCRIPTABLE virtual IPlugin* managerPlugin() const = 0; /** * Get the version control plugin for this project * This may return 0 if the project is not under version control * or version control has been disabled for this project */ Q_SCRIPTABLE virtual IPlugin* versionControlPlugin() const = 0; /** * With this the top-level project item can be retrieved */ Q_SCRIPTABLE virtual ProjectFolderItem* projectItem() const = 0; /** * @return all items with the corresponding @p path */ Q_SCRIPTABLE virtual QList itemsForPath( const IndexedString& path ) const = 0; /** * @return all file items with the corresponding @p file path */ Q_SCRIPTABLE virtual QList filesForPath( const IndexedString& file ) const = 0; /** * @return all folder items with the corresponding @p folder path */ Q_SCRIPTABLE virtual QList foldersForPath( const IndexedString& folder ) const = 0; /** * @return the path to the project file */ virtual Path projectFile() const = 0; /** Get the url of the project file.*/ virtual KSharedConfigPtr projectConfiguration() const = 0; virtual void addToFileSet( ProjectFileItem* item ) = 0; virtual void removeFromFileSet( ProjectFileItem* item ) = 0; virtual QSet fileSet() const = 0; /** Returns whether the project is ready to be used or not. A project won't be ready for use when it's being reloaded or still loading */ virtual bool isReady() const=0; /** * @brief Get the project path * @return The canonical absolute directory of the project. */ virtual Path path() const = 0; /** Returns the name of the project. */ virtual Q_SCRIPTABLE QString name() const = 0; /** * @brief Check if the project contains an item with the given @p path. * * @param path the path to check * * @return true if the path @a path is a part of the project. */ virtual Q_SCRIPTABLE bool inProject(const IndexedString &path) const = 0; /** * @brief Tells the project what job is reloading it * * It's useful so that we can tell whether the project manager is busy or not. */ virtual void setReloadJob(KJob* job) = 0; Q_SIGNALS: /** * Gets emitted whenever a file was added to the project. */ void fileAddedToSet( KDevelop::ProjectFileItem* item ); /** * Gets emitted whenever a file was removed from the project. */ void fileRemovedFromSet( KDevelop::ProjectFileItem* item ); public Q_SLOTS: /** Make the model to reload */ virtual void reloadModel() = 0; }; } #endif diff --git a/interfaces/iprojectcontroller.h b/interfaces/iprojectcontroller.h index 0e232db852..ab2ac2db1f 100644 --- a/interfaces/iprojectcontroller.h +++ b/interfaces/iprojectcontroller.h @@ -1,199 +1,199 @@ /* This file is part of KDevelop Copyright 2006 Adam Treat Copyright 2007 Andreas Pakulat 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 KDEVPLATFORM_IPROJECTCONTROLLER_H #define KDEVPLATFORM_IPROJECTCONTROLLER_H #include #include #include #include "interfacesexport.h" class QItemSelectionModel; namespace KDevelop { class IProject; class ProjectBuildSetModel; class ProjectModel; class ProjectBaseItem; class ProjectChangesModel; /** * @class IProjectController */ class KDEVPLATFORMINTERFACES_EXPORT IProjectController : public QObject { Q_OBJECT public: explicit IProjectController( QObject *parent = 0 ); - virtual ~IProjectController(); + ~IProjectController() override; Q_SCRIPTABLE virtual KDevelop::IProject* projectAt( int ) const = 0; Q_SCRIPTABLE virtual int projectCount() const = 0; Q_SCRIPTABLE virtual QList projects() const = 0; /** * Provides access to the model representing the open projects * @returns the model containing the projects and their items */ Q_SCRIPTABLE virtual ProjectModel* projectModel() = 0; /** * @returns an instance to the model that keeps track of the state * of the files per project. */ Q_SCRIPTABLE virtual ProjectChangesModel* changesModel() = 0; Q_SCRIPTABLE virtual ProjectBuildSetModel* buildSetModel() = 0; /** * Find an open project using the name of the project * @param name the name of the project to be found * @returns the project or null if no project with that name is open */ Q_SCRIPTABLE virtual KDevelop::IProject* findProjectByName( const QString& name ) = 0; /** * Finding an open project for a given file or folder in the project * @param url the url of a file/folder belonging to an open project * @returns the first open project containing the url or null if no such * project can be found */ Q_SCRIPTABLE virtual IProject* findProjectForUrl( const QUrl& url ) const = 0; /** * Checks whether the given project name is used already or not. The project * controller supports only 1 project with a given name to be open at any time * @param name the name of the project to be opened or created * @returns whether the name is already used for an open project */ Q_SCRIPTABLE virtual bool isProjectNameUsed( const QString& name ) const = 0; virtual QUrl projectsBaseDirectory() const = 0; enum FormattingOptions { FormatHtml, FormatPlain }; /** * Returns a pretty short representation of the base path of the url, considering the currently loaded projects: * When the file is part of a currently loaded project, that projects name is shown as prefix instead of the * the full file path. * The returned path always has a training slash. * @param format formatting used for the string */ Q_SCRIPTABLE virtual QString prettyFilePath(const QUrl& url, FormattingOptions format = FormatHtml) const = 0; /** * Returns a pretty short representation of the given url, considering the currently loaded projects: * When the file is part of a currently loaded project, that projects name is shown as prefix instead of the * the full file path. * @param format formatting used for the string */ Q_SCRIPTABLE virtual QString prettyFileName(const QUrl& url, FormattingOptions format = FormatHtml) const = 0; /** * @returns whether project files should be parsed or not */ static bool parseAllProjectSources(); public Q_SLOTS: /** * Tries finding a project-file for the given source-url and opens it. * If no .kdev4 project file is found, the user is asked to import a project. */ virtual void openProjectForUrl( const QUrl &sourceUrl ) = 0; /** * open the project from the given kdev4 project file. This only reads * the file and starts creating the project model from it. The opening process * is finished once @ref projectOpened signal is emitted. * @param url a kdev4 project file top open * @returns true if the given project could be opened, false otherwise */ virtual void openProject( const QUrl & url = QUrl() ) = 0; /** * close the given project. Closing the project is done in steps and * the @ref projectClosing and @ref projectClosed signals are emitted. Only when * the latter signal is emitted it is guaranteed that the project has been closed. * The @ref IProject object will be deleted after the closing has finished. * @returns true if the project could be closed, false otherwise */ virtual void closeProject( IProject* ) = 0; virtual void configureProject( IProject* ) = 0; /// Schedules all files of the @p project for reparsing by @see BackgroundParser virtual void reparseProject( IProject* project, bool ForceUpdate = false ) = 0; // virtual void changeCurrentProject( KDevelop::ProjectBaseItem* ) = 0; Q_SIGNALS: /** * Emitted right before a project is started to be loaded. * * At this point all sanity checks have been done, so the project * is really going to be loaded. Will be followed by @ref projectOpened signal * when loading completes or by @ref projectOpeningAborted if there are errors during loading * or it is aborted. * * @param project the project that is about to be opened. */ void projectAboutToBeOpened( KDevelop::IProject* project ); /** * emitted after a project is completely opened and the project model * has been populated. * @param project the project that has been opened. */ void projectOpened( KDevelop::IProject* project ); /** * emitted when starting to close a project that has been completely loaded before * (the @ref projectOpened signal has been emitted). * @param project the project that is going to be closed. */ void projectClosing( KDevelop::IProject* project ); /** * emitted when a project has been closed completely. * The project object is still valid, the deletion will be done * delayed during the next run of the event loop. * @param project the project that has been closed. */ void projectClosed( KDevelop::IProject* project ); /** * emitted when a project could not be loaded correctly or loading was aborted. * @ref project contents may not be initialized properly. * @param project the project which loading has been aborted. */ void projectOpeningAborted( KDevelop::IProject* project ); /** * emitted whenever the project configuration dialog accepted * changes * @param project the project whose configuration has changed */ void projectConfigurationChanged( KDevelop::IProject* project ); }; } #endif diff --git a/interfaces/iselectioncontroller.h b/interfaces/iselectioncontroller.h index 0c50b11cd2..a6035c2d9f 100644 --- a/interfaces/iselectioncontroller.h +++ b/interfaces/iselectioncontroller.h @@ -1,83 +1,83 @@ /* This file is part of KDevelop Copyright 2009 Andreas Pakulat 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 KDEVPLATFORM_ISELECTIONCONTROLLER_H #define KDEVPLATFORM_ISELECTIONCONTROLLER_H #include #include "interfacesexport.h" namespace KDevelop { class Context; /** * The main controller for selection updates in the GUI. * * This controller can be used by selection consumers and selection providers. * * A selection provider (for example a treeview for the projects) should * call updateSelection() with an appropriate context filled with the details * of the selection * * A selection consumer who is interested in notifications when the selection has * been changed, should connect to the selectionChanged signal. The consumer should * retrieve all necessary information that it might need to do something with the * selection and store those. Storing the whole Context* might be dangerous as it * will be deleted on the next selection change. * */ class KDEVPLATFORMINTERFACES_EXPORT ISelectionController : public QObject { Q_OBJECT public: ///Constructor. explicit ISelectionController(QObject *parent); - ~ISelectionController(); + ~ISelectionController() override; /** * Provides the current selection, note that this might be 0 */ virtual Context* currentSelection() = 0; public Q_SLOTS: /** * updates the current selection. * The SelectionController takes ownership of the given context and * deletes it when the selection is updated the next time. * @param context the new selection */ virtual void updateSelection( Context* context ) = 0; Q_SIGNALS: /** * Notify that the current selection changed. * @note The context might be deleted behind the back (when a new selection * is set) of the receivers of this signal, so make sure to copy all the * needed information. */ void selectionChanged( KDevelop::Context* ); }; } #endif // KDEVPLATFORM_ISELECTIONCONTROLLER_H diff --git a/interfaces/isession.h b/interfaces/isession.h index 035cfb7c49..3192a9d22d 100644 --- a/interfaces/isession.h +++ b/interfaces/isession.h @@ -1,77 +1,77 @@ /* This file is part of KDevelop Copyright 2008 Andreas Pakulat 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 KDEVPLATFORM_ISESSION_H #define KDEVPLATFORM_ISESSION_H #include "interfacesexport.h" #include #include #include class QUuid; class QString; namespace KDevelop { class IPlugin; /** * @class ISession */ class KDEVPLATFORMINTERFACES_EXPORT ISession : public QObject { Q_OBJECT public: explicit ISession( QObject* parent = 0 ); - virtual ~ISession(); + ~ISession() override; /** * A short string nicely identifying the session, including contained projects * * The string is empty if the session is empty and has no name. */ virtual QString description() const = 0; virtual QString name() const = 0; virtual QList containedProjects() const = 0; virtual void setContainedProjects( const QList& projects ) = 0; virtual QUrl pluginDataArea( const IPlugin* ) = 0; virtual KSharedConfigPtr config() = 0; virtual QUuid id() const = 0; /** * Mark session as temporary. It will then be deleted on close. * * This is mainly useful for unit tests etc. */ virtual void setTemporary(bool temp) = 0; virtual bool isTemporary() const = 0; Q_SIGNALS: void sessionUpdated( KDevelop::ISession* session ); }; } Q_DECLARE_METATYPE( KDevelop::ISession* ) #endif diff --git a/interfaces/isourceformatter.h b/interfaces/isourceformatter.h index 21d5d4aaaa..bfbc6d1c79 100644 --- a/interfaces/isourceformatter.h +++ b/interfaces/isourceformatter.h @@ -1,231 +1,231 @@ /* This file is part of KDevelop Copyright (C) 2008 Cédric Pasteur 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 KDEVPLATFORM_ISOURCEFORMATTER_H #define KDEVPLATFORM_ISOURCEFORMATTER_H #include #include #include #include "interfacesexport.h" class QUrl; namespace KDevelop { class KDEVPLATFORMINTERFACES_EXPORT SourceFormatterStyle { public: struct MimeHighlightPair { QString mimeType; QString highlightMode; }; typedef QVector MimeList; SourceFormatterStyle(); explicit SourceFormatterStyle( const QString& name ); void setContent( const QString& content ); void setCaption( const QString& caption ); QString content() const; QString caption() const; QString name() const; QString description() const; void setDescription( const QString& desc ); bool usePreview() const; void setUsePreview(bool use); void setMimeTypes( const MimeList& types ); void setMimeTypes( const QStringList& types ); /// Provides the possibility to the item to return a better-suited /// code sample. If empty, the default is used. QString overrideSample() const; void setOverrideSample( const QString& sample ); MimeList mimeTypes() const; /// mime types as a QVariantList, type and mode separated by | in strings QVariant mimeTypesVariant() const; bool supportsLanguage(const QString& language) const; /// get the language / highlight mode for a given @p mime QString modeForMimetype(const QMimeType& mime) const; /// Copy content, mime types and code sample from @p other. void copyDataFrom(SourceFormatterStyle *other); private: bool m_usePreview; QString m_name; QString m_caption; QString m_content; QString m_description; QString m_overrideSample; MimeList m_mimeTypes; }; /** * @brief An object describing a style associated with a plugin * which can deal with this style. */ struct SourceFormatterStyleItem { QString engine; SourceFormatterStyle style; }; typedef QVector SourceFormatterItemList; /** * @short A widget to edit a style * A plugin should inherit this widget to create a widget to * edit a style. * @author Cédric Pasteur */ class KDEVPLATFORMINTERFACES_EXPORT SettingsWidget : public QWidget { Q_OBJECT public: explicit SettingsWidget(QWidget *parent = 0); - virtual ~SettingsWidget(); + ~SettingsWidget() override; /** This function is called after the creation of the dialog. * it should initialise the widgets with the values corresponding to * the predefined style \arg name if it's not empty, or * to the string \arg content. */ virtual void load(const SourceFormatterStyle&) = 0; /** \return A string representing the state of the config. */ virtual QString save() = 0; Q_SIGNALS: /** Emits this signal when a setting was changed and the preview * needs to be updated. \arg text is the text that will be shown in the * editor. One might want to show different text * according to the different pages shown in the widget. * Text should already be formatted. */ void previewTextChanged(const QString &text); }; /** * @short An interface for a source beautifier * An example of a plugin using an external executable to do * the formatting can be found in kdevelop/plugins/formatters/indent_plugin.cpp. * @author Cédric Pasteur */ class KDEVPLATFORMINTERFACES_EXPORT ISourceFormatter { public: virtual ~ISourceFormatter(); /** \return The name of the plugin. This should contain only * ASCII chars and no spaces. This will be used internally to identify * the plugin. */ virtual QString name() = 0; /** \return A caption describing the plugin. */ virtual QString caption() = 0; /** \return A more complete description of the plugin. * The string should be written in Rich text. It can eg contain * a link to the project homepage. */ virtual QString description() = 0; /** Formats using the current style. * @param text The text to format * @param url The URL to which the text belongs (its contents must not be changed). * @param leftContext The context at the left side of the text. If it is in another line, it must end with a newline. * @param rightContext The context at the right side of the text. If it is in the next line, it must start with a newline. * * If the source-formatter cannot work correctly with the context, it will just return the input text. */ virtual QString formatSource(const QString &text, const QUrl& url, const QMimeType &mime, const QString& leftContext = QString(), const QString& rightContext = QString()) = 0; /** * Format with the given style, this is mostly for the kcm to format the preview text * Its a bit of a hassle that this needs to be public API, but I can't find a better way * to do this. */ virtual QString formatSourceWithStyle( SourceFormatterStyle, const QString& text, const QUrl& url, const QMimeType &mime, const QString& leftContext = QString(), const QString& rightContext = QString() ) = 0; /** \return A map of predefined styles (a key and a caption for each type) */ virtual QList predefinedStyles() = 0; /** \return The widget to edit a style. */ virtual SettingsWidget* editStyleWidget(const QMimeType &mime) = 0; /** \return The text used in the config dialog to preview the current style. */ virtual QString previewText(const SourceFormatterStyle& style, const QMimeType &mime) = 0; struct Indentation { Indentation() : indentationTabWidth(0), indentWidth(0) { } // If this indentation is really valid bool isValid() const { return indentationTabWidth != 0 || indentWidth != 0; } // The length of one tab used for indentation. // Zero if unknown, -1 if tabs should not be used for indentation int indentationTabWidth; // The number of columns that equal one indentation level. // If this is zero, the default should be used. int indentWidth; }; /** \return The indentation of the style applicable for the given url. */ virtual Indentation indentation(const QUrl& url) = 0; /** \return A string representing the map. Values are written in the form * key=value and separated with ','. */ static QString optionMapToString(const QMap &map); /** \return A map corresponding to the string, that was created with * \ref optionMapToString. */ static QMap stringToOptionMap(const QString &option); /** \return A message to display when an executable needed by a * plugin is missing. This should be returned as description * if a needed executable is not found. */ static QString missingExecutableMessage(const QString &name); }; } Q_DECLARE_INTERFACE(KDevelop::ISourceFormatter, "org.kdevelop.ISourceFormatter") Q_DECLARE_TYPEINFO(KDevelop::SourceFormatterStyle::MimeHighlightPair, Q_MOVABLE_TYPE); #endif // KDEVPLATFORM_ISOURCEFORMATTER_H // kate: indent-mode cstyle; space-indent off; tab-width 4; diff --git a/interfaces/isourceformattercontroller.h b/interfaces/isourceformattercontroller.h index 8fcc51102e..2e2b3eb65b 100644 --- a/interfaces/isourceformattercontroller.h +++ b/interfaces/isourceformattercontroller.h @@ -1,71 +1,71 @@ /* This file is part of KDevelop Copyright 2009 Andreas Pakulat Copyright (C) 2008 Cédric Pasteur 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 KDEVPLATFORM_ISOURCEFORMATTERCONTROLLER_H #define KDEVPLATFORM_ISOURCEFORMATTERCONTROLLER_H #include #include #include "interfacesexport.h" class QUrl; namespace KDevelop { class ISourceFormatter; class SourceFormatterStyle; /** \short An interface to the controller managing all source formatter plugins */ class KDEVPLATFORMINTERFACES_EXPORT ISourceFormatterController : public QObject { Q_OBJECT public: explicit ISourceFormatterController(QObject *parent = 0); - virtual ~ISourceFormatterController(); + ~ISourceFormatterController() override; /** \return The formatter corresponding to the language * of the document corresponding to the \arg url. */ virtual ISourceFormatter* formatterForUrl(const QUrl &url) = 0; /** Loads and returns a source formatter for this mime type. * The language is then activated and the style is loaded. * The source formatter is then ready to use on a file. */ virtual ISourceFormatter* formatterForMimeType(const QMimeType &mime) = 0; /** \return Whether this mime type is supported by any plugin. */ virtual bool isMimeTypeSupported(const QMimeType &mime) = 0; virtual KDevelop::SourceFormatterStyle styleForMimeType( const QMimeType& mime ) = 0; ///Set whether or not source formatting is disabled with \arg disable virtual void disableSourceFormatting(bool disable) = 0; ///\return Whether or not source formatting is enabled virtual bool sourceFormattingEnabled() = 0; }; } #endif // KDEVPLATFORM_ISOURCEFORMATTERCONTROLLER_H // kate: indent-mode cstyle; space-indent off; tab-width 4 = 0; diff --git a/interfaces/itestcontroller.h b/interfaces/itestcontroller.h index 022e7942f7..71d6a34afc 100644 --- a/interfaces/itestcontroller.h +++ b/interfaces/itestcontroller.h @@ -1,141 +1,141 @@ /* This file is part of KDevelop Copyright 2012 Miha Čančula 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 KDEVPLATFORM_ITESTCONTROLLER_H #define KDEVPLATFORM_ITESTCONTROLLER_H #include "interfacesexport.h" #include #include #include #include class KJob; namespace KDevelop { struct TestResult; class IProject; class ITestSuite; /** * The result of a single unit test run **/ struct KDEVPLATFORMINTERFACES_EXPORT TestResult { /** * Enumeration of possible test case results **/ enum TestCaseResult { NotRun, ///< The test case was not selected for running. Skipped, ///< The test case was skipped. Passed, ///< The test case was run and passed. Failed, ///< The test case was run and failed. ExpectedFail, ///< The test case was expected to fail, and did. UnexpectedPass, ///< The test case was expected to fail, but passed. Error, ///< There was an error while trying to run the test case. }; /** * The individual results of all test cases. **/ QHash testCaseResults; /** * The total result of the entire suite. * * This is usually the worst outcome of the individual test cases, * but can be different especially when dealing with errors. */ TestCaseResult suiteResult; }; class KDEVPLATFORMINTERFACES_EXPORT ITestController : public QObject { Q_OBJECT public: explicit ITestController(QObject* parent = 0); - virtual ~ITestController(); + ~ITestController() override; /** * Add a new test suite. * * No ownership is taken, the caller stays responsible for the suite. * * If a suite with the same project and same name exists, the old one will be removed and deleted. */ virtual void addTestSuite(ITestSuite* suite) = 0; /** * Remove a test suite from the controller. * * This does not delete the test suite. */ virtual void removeTestSuite(ITestSuite* suite) = 0; /** * Returns the list of all known test suites. */ virtual QList testSuites() const = 0; /** * Find a test suite in @p project with @p name. */ virtual ITestSuite* findTestSuite(IProject* project, const QString& name) const = 0; /** * Return the list of all test suites in @p project. */ virtual QList testSuitesForProject(IProject* project) const = 0; /** * Notify the controller that a test run for @p suite was finished with result @p result */ virtual void notifyTestRunFinished(ITestSuite* suite, const KDevelop::TestResult& result) = 0; /** * Notify the controller that a test run for @p suite was started */ virtual void notifyTestRunStarted(KDevelop::ITestSuite* suite, const QStringList& test_cases) = 0; Q_SIGNALS: /** * Emitted whenever a new test suite gets added. */ void testSuiteAdded(KDevelop::ITestSuite* suite) const; /** * Emitted whenever a test suite gets removed. */ void testSuiteRemoved(KDevelop::ITestSuite* suite) const; /** * Emitted after a test suite was run. */ void testRunFinished(KDevelop::ITestSuite* suite, const KDevelop::TestResult& result) const; /** * Emitted when a test suite starts. */ void testRunStarted(KDevelop::ITestSuite* suite, const QStringList& test_cases) const; }; } Q_DECLARE_INTERFACE( KDevelop::ITestController, "org.kdevelop.ITestController") #endif // KDEVPLATFORM_ITESTCONTROLLER_H diff --git a/interfaces/launchconfigurationtype.h b/interfaces/launchconfigurationtype.h index d4cc92b75e..dff392e556 100644 --- a/interfaces/launchconfigurationtype.h +++ b/interfaces/launchconfigurationtype.h @@ -1,152 +1,152 @@ /* This file is part of KDevelop Copyright 2009 Andreas Pakulat 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 KDEVPLATFORM_LAUNCHCONFIGURATIONTYPE_H #define KDEVPLATFORM_LAUNCHCONFIGURATIONTYPE_H #include "interfacesexport.h" #include #include class QMenu; class QIcon; class QUrl; class KConfigGroup; namespace KDevelop { class IProject; class ILaunchConfiguration; class ProjectBaseItem; class ILauncher; class LaunchConfigurationPageFactory; /** * Launch configuration types are used to be able to create * new launch configurations. Each launch configuration has a * specific type, which specifies which launchers can be used * for the configuration as well as which config pages are needed * to setup the launch configuration */ class KDEVPLATFORMINTERFACES_EXPORT LaunchConfigurationType : public QObject { Q_OBJECT public: LaunchConfigurationType(); - virtual ~LaunchConfigurationType(); + ~LaunchConfigurationType() override; /** * Provide a unique identifier for the type * among other things this will be used to create a config group in launch * configurations for the pages of this config type * @returns a unique identifier for this launch configuration type */ virtual QString id() const = 0; /** * Provide a user visible name for the type * @returns a translatable string for the type */ virtual QString name() const = 0; /** * Add @p starter to this configuration type * @param starter the launcher that can start configurations of this type */ void addLauncher( ILauncher* starter ); /** * remove @p starter from this configuration type * @param starter the launcher that should not start configurations of this type */ void removeLauncher( ILauncher* starter ); /** * Access all launchers that are usable with this type * @returns a list of launchers that can be used with configurations of this type */ QList launchers() const; /** * Convenience method to access a launcher given its @p id * @param id the id of the launcher to be found * @returns the launcher with the given id or 0 if there's no such launcher in this configuration type */ ILauncher* launcherForId( const QString& id ); /** * Provide a list of widgets to configure a launch configuration for this type * @returns a list of factories to create config pages from. */ virtual QList configPages() const = 0; /** * Provide an icon for this launch configuration type * @returns an icon to be used for representing launch configurations of this type */ virtual QIcon icon() const = 0; /** * Check whether this launch configuration type can launch the given project item * @param item the project tree item to test * @returns true if this configuration type can launch the given item, false otherwise */ virtual bool canLaunch( KDevelop::ProjectBaseItem* item ) const = 0; /** * Configure the given launch configuration to execute the selected item * @param config the configuration to setup * @param item the item to launch */ virtual void configureLaunchFromItem( KConfigGroup config, KDevelop::ProjectBaseItem* item ) const = 0; /** * Configure the given launch configuration to execute the selected item * @param config the configuration to setup * @param item the item to launch */ virtual void configureLaunchFromCmdLineArguments( KConfigGroup config, const QStringList &args ) const = 0; /** * Check whether this launch configuration type can launch the given file * @param file the file to test launchability * @returns true if this configuration type can launch the given file, false otherwise */ virtual bool canLaunch( const QUrl& file ) const = 0; /** * Returns a menu that will be added to the UI where the interface will be * able to add any suggestion it needs, like default targets. */ virtual QMenu* launcherSuggestions() { return 0; } signals: void signalAddLaunchConfiguration(KDevelop::ILaunchConfiguration* launch); private: class LaunchConfigurationTypePrivate* const d; }; } #endif diff --git a/language/assistant/renameaction.h b/language/assistant/renameaction.h index 510c2f1e51..b1196b543a 100644 --- a/language/assistant/renameaction.h +++ b/language/assistant/renameaction.h @@ -1,75 +1,75 @@ /* Copyright 2012 Olivier de Gaalon Copyright 2014 Kevin Funk 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. */ #ifndef KDEVPLATFORM_RENAMEACTION_H #define KDEVPLATFORM_RENAMEACTION_H #include #include #include #include namespace KDevelop { class Identifier; /** * A HACK to circumvent the bad RangeInRevision API without rewriting everything. * * The RangeInRevision is actually just blindly assuming that it belongs to * the revision the file was parsed in the last time. But if the file is * reparsed in between (due to changes) the ranges might be wrong. Due to that * we must store the ranges and their actual revision... Stupid! * * See also: https://bugs.kde.org/show_bug.cgi?id=295707 */ struct KDEVPLATFORMLANGUAGE_EXPORT RevisionedFileRanges { KDevelop::IndexedString file; KDevelop::RevisionReference revision; QList ranges; static QVector convert(const QMap >& uses); }; class KDEVPLATFORMLANGUAGE_EXPORT RenameAction : public KDevelop::IAssistantAction { Q_OBJECT public: RenameAction(const KDevelop::Identifier& oldDeclarationName, const QString& newDeclarationName, const QVector& oldDeclarationUses); - virtual ~RenameAction(); + ~RenameAction() override; - virtual QString description() const override; - virtual void execute() override; + QString description() const override; + void execute() override; QString newDeclarationName() const; QString oldDeclarationName() const; private: struct Private; QScopedPointer const d; }; } Q_DECLARE_TYPEINFO(KDevelop::RevisionedFileRanges, Q_MOVABLE_TYPE); #endif diff --git a/language/assistant/renameassistant.h b/language/assistant/renameassistant.h index 7cba6dde3c..2f1df3b28e 100644 --- a/language/assistant/renameassistant.h +++ b/language/assistant/renameassistant.h @@ -1,56 +1,56 @@ /* Copyright 2010 Olivier de Gaalon Copyright 2014 Kevin Funk 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. */ #ifndef KDEVPLATFORM_RENAMEEASSISTANT_H #define KDEVPLATFORM_RENAMEEASSISTANT_H #include #include #include #include #include "renameaction.h" namespace KTextEditor { class View; } namespace KDevelop { class ParseJob; class KDEVPLATFORMLANGUAGE_EXPORT RenameAssistant : public StaticAssistant { Q_OBJECT public: explicit RenameAssistant(ILanguageSupport* supportedLanguage); - virtual ~RenameAssistant(); + ~RenameAssistant() override; - virtual void textChanged(KTextEditor::View* view, const KTextEditor::Range& invocationRange, const QString& removedText = QString()) override; - virtual bool isUseful() const override; + void textChanged(KTextEditor::View* view, const KTextEditor::Range& invocationRange, const QString& removedText = QString()) override; + bool isUseful() const override; - virtual QString title() const override; + QString title() const override; private: struct Private; QScopedPointer const d; }; } #endif // KDEVPLATFORM_RENAMEEASSISTANT_H diff --git a/language/assistant/renamefileaction.h b/language/assistant/renamefileaction.h index 23efb20c25..87799cb70d 100644 --- a/language/assistant/renamefileaction.h +++ b/language/assistant/renamefileaction.h @@ -1,48 +1,48 @@ /* Copyright 2012 Milian Wolff Copyright 2014 Kevin Funk 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. */ #ifndef KDEVPLATFORM_RENAMEFILEACTION_H #define KDEVPLATFORM_RENAMEFILEACTION_H #include #include namespace KDevelop { class BasicRefactoring; } class RenameFileAction : public KDevelop::IAssistantAction { Q_OBJECT public: RenameFileAction(KDevelop::BasicRefactoring* refactoring, const QUrl& file, const QString& newName); - virtual ~RenameFileAction(); + ~RenameFileAction() override; - virtual QString description() const override; - virtual void execute() override; + QString description() const override; + void execute() override; private: struct Private; QScopedPointer const d; }; #endif // KDEVPLATFORM_RENAMEFILEACTION_H diff --git a/language/assistant/staticassistant.h b/language/assistant/staticassistant.h index ad2180901a..9846604b6b 100644 --- a/language/assistant/staticassistant.h +++ b/language/assistant/staticassistant.h @@ -1,94 +1,94 @@ /* * Copyright 2014 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 KDEVPLATFORM_STATICASSISTANT_H #define KDEVPLATFORM_STATICASSISTANT_H #include #include namespace KTextEditor { class Document; class View; class Range; } namespace KDevelop { class ILanguageSupport; /** * @brief This class serves as a base for long-living assistants * * Normally, an assistant only lives for a short time, and is indirectly owned by a KDevelop::Problem. * Static assistants are owned by the language support plugins and exist as long as the language plugin is loaded. * They are not created by KDevelop::Problem instances, instead, they check for problematic code for themselves, * by tracking document changes via the textChanged() method. * * Note that static assistants are not bound to a single document/view. * Instead the current document/view we're looking at is passed via the textChanged() method. * * Register instances of this class view StaticAssistantsManager::registerAssistant * * @sa textChanged() * @sa StaticAssistantsManager::registerAssistant */ class KDEVPLATFORMLANGUAGE_EXPORT StaticAssistant : public IAssistant { Q_OBJECT public: using Ptr = QExplicitlySharedDataPointer; explicit StaticAssistant(ILanguageSupport* supportedLanguage); - virtual ~StaticAssistant(); + ~StaticAssistant() override; /** * Language this static assistant supports * * textChanged() will only be called for documents with language equal to this assistant's language * @sa textChanged(0) */ ILanguageSupport* supportedLanguage() const; /** * Invoked whenever text inside a view was changed by the user * * Reimplement in subclass */ virtual void textChanged(KTextEditor::View* view, const KTextEditor::Range& invocationRange, const QString& removedText = QString()) = 0; /** * Whether it's worth showing this assistant to the user * * Reimplement in subclass */ virtual bool isUseful() const = 0; private: struct Private; QScopedPointer const d; }; } #endif // KDEVPLATFORM_STATICASSISTANT_H diff --git a/language/assistant/staticassistantsmanager.h b/language/assistant/staticassistantsmanager.h index 1cfd3fb3d3..ccd2536687 100644 --- a/language/assistant/staticassistantsmanager.h +++ b/language/assistant/staticassistantsmanager.h @@ -1,77 +1,77 @@ /* Copyright 2009 David Nolden Copyright 2014 Kevin Funk 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. */ #ifndef KDEVPLATFORM_STATICASSISTANTSMANAGER_H #define KDEVPLATFORM_STATICASSISTANTSMANAGER_H #include #include #include "staticassistant.h" #include #include #include #include class QTimer; typedef QPointer SafeDocumentPointer; namespace KDevelop { class IDocument; class ParseJob; class DUContext; class TopDUContext; /** * @brief Class managing instances of StaticAssistant * * Invokes the appropriate methods on registered StaticAssistant instances, such as StaticAssistant::textChanged * * @sa StaticAssistant::textChanged */ class KDEVPLATFORMLANGUAGE_EXPORT StaticAssistantsManager : public QObject { Q_OBJECT public: explicit StaticAssistantsManager(QObject* parent = 0); - virtual ~StaticAssistantsManager(); + ~StaticAssistantsManager() override; QExplicitlySharedDataPointer activeAssistant(); void registerAssistant(const StaticAssistant::Ptr assistant); void unregisterAssistant(const StaticAssistant::Ptr assistant); QList registeredAssistants() const; public slots: void hideAssistant(); private: struct Private; QScopedPointer const d; Q_PRIVATE_SLOT(d, void eventuallyStartAssistant()) }; } #endif // KDEVPLATFORM_STATICASSISTANTSMANAGER_H diff --git a/language/backgroundparser/backgroundparser.h b/language/backgroundparser/backgroundparser.h index 5623a56c3d..62a5fddfa8 100644 --- a/language/backgroundparser/backgroundparser.h +++ b/language/backgroundparser/backgroundparser.h @@ -1,227 +1,227 @@ /* * This file is part of KDevelop * * Copyright 2006 Adam Treat * Copyright 2007 Kris Wong * Copyright 2007-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. */ #ifndef KDEVPLATFORM_BACKGROUNDPARSER_H #define KDEVPLATFORM_BACKGROUNDPARSER_H #include #include #include #include #include #include #include #include "parsejob.h" class QMutex; namespace ThreadWeaver { class Job; class QObjectDecorator; class Weaver; } namespace KDevelop { class DocumentChangeTracker; class IDocument; class IProject; class ILanguageController; class ParseJob; class ParserDependencyPolicy; /** * This class handles the creation of parse jobs for given file URLs. * * For performance reasons you must always use clean, canonical URLs. If you do not do that, * issues might arise (and the debug build will assert). */ class KDEVPLATFORMLANGUAGE_EXPORT BackgroundParser : public QObject, public IStatus { Q_OBJECT Q_INTERFACES( KDevelop::IStatus ) public: explicit BackgroundParser(ILanguageController *languageController); - ~BackgroundParser(); + ~BackgroundParser() override; - virtual QString statusName() const override; + QString statusName() const override; enum { BestPriority = -10000, ///Best possible job-priority. No jobs should actually have this. NormalPriority = 0, ///Standard job-priority. This priority is used for parse-jobs caused by document-editing/opening. ///There is an additional parsing-thread reserved for jobs with this and better priority, to improve responsiveness. InitialParsePriority = 10000, ///Priority used when adding file on project loading WorstPriority = 100000 ///Worst possible job-priority. }; /** * Queries the background parser as to whether there is currently * a parse job for @p document, and if so, returns it. * * This may not contain all of the parse jobs that are intended * unless you call in from your job's ThreadWeaver::Job::aboutToBeQueued() * function. */ Q_SCRIPTABLE ParseJob* parseJobForDocument(const IndexedString& document) const; /** * Set how many ThreadWeaver threads the background parser should set up and use. */ Q_SCRIPTABLE void setThreadCount(int threadCount); /** * Return how many ThreadWeaver threads the background parser should set up and use. */ Q_SCRIPTABLE int threadCount() const; /** * Set the delay in miliseconds before the background parser starts parsing. */ Q_SCRIPTABLE void setDelay(int miliseconds); /** * Returns all documents that were added through addManagedTopRange. This is typically the currently * open documents. */ Q_SCRIPTABLE QList managedDocuments(); /** * Returns the tracker for the given url if the document is being tracked, else returns zero. * This function is thread-safe, but the returned object also isn't, so you must not use it * when you're in a background thread without the foreground lock acquired. * */ DocumentChangeTracker* trackerForUrl(const IndexedString& url) const; Q_SIGNALS: /** * Emitted whenever a document parse-job has finished. * The job contains the du-chain(if one was created) etc. * * The job is deleted after this signal has been emitted. Receivers should not hold * references to it. */ void parseJobFinished(KDevelop::ParseJob* job); // Implementations of IStatus signals void clearMessage( KDevelop::IStatus* ) override; void showMessage( KDevelop::IStatus*, const QString & message, int timeout = 0) override; void hideProgress( KDevelop::IStatus* ) override; void showProgress( KDevelop::IStatus*, int minimum, int maximum, int value) override; void showErrorMessage( const QString&, int ) override; public Q_SLOTS: /** * Suspends execution of the background parser */ void suspend(); /** * Resumes execution of the background parser */ void resume(); ///Reverts all requests that were made for the given notification-target. ///priorities and requested features will be reverted as well. ///When @p notifyWhenReady is set to a nullptr, all requests will be reverted. void revertAllRequests(QObject* notifyWhenReady); /** * Queues up the @p url to be parsed. * @p features The minimum features that should be computed for this top-context * @p priority A value that manages the order of parsing. Documents with lowest priority are parsed first. * @param notifyReady An optional pointer to a QObject that should contain a slot * "void updateReady(KDevelop::IndexedString url, KDevelop::ReferencedTopDUContext topContext)". * The notification is guaranteed to be called once for each call to addDocument. The given top-context * may be invalid if the update failed. */ void addDocument(const IndexedString& url, TopDUContext::Features features = TopDUContext::VisibleDeclarationsAndContexts, int priority = 0, QObject* notifyWhenReady = 0, ParseJob::SequentialProcessingFlags flags = ParseJob::IgnoresSequentialProcessing); /** * Removes the @p url that is registered for the given notification from the url. * * @param notifyWhenReady Notifier the document was added with. */ void removeDocument(const IndexedString& url, QObject* notifyWhenReady = 0); /** * Forces the current queue to be parsed. */ void parseDocuments(); void updateProgressBar(); ///Disables processing for all jobs that have a worse priority than @param priority ///This can be used to temporarily limit the processing to only the most important jobs. ///To only enable processing for important jobs, call setNeededPriority(0). ///This should only be used to temporarily alter the processing. A progress-bar ///will still be shown for the not yet processed jobs. void setNeededPriority(int priority); ///Disables all processing of new jobs, equivalent to setNeededPriority(BestPriority) void disableProcessing(); ///Enables all processing of new jobs, equivalent to setNeededPriority(WorstPriority) void enableProcessing(); ///Returns true if the given url is queued for parsing bool isQueued(const IndexedString& url) const; ///Retrieve the current priority for the given URL. ///You need to check whether @param url is queued before calling this function. int priorityForDocument(const IndexedString& url) const; ///Returns the number of queued jobs (not yet running nor submitted to ThreadWeaver) int queuedCount() const; ///Returns true if there are no jobs running nor queued anywhere bool isIdle() const; void documentClosed(KDevelop::IDocument*); void documentLoaded(KDevelop::IDocument*); void documentUrlChanged(KDevelop::IDocument*); void loadSettings(); protected Q_SLOTS: void parseComplete(const ThreadWeaver::JobPointer& job); void parseProgress(KDevelop::ParseJob*, float value, QString text); void startTimer(); void aboutToQuit(); private: friend class BackgroundParserPrivate; class BackgroundParserPrivate *d; private Q_SLOTS: /// Tracking of projects in state of loading. void projectAboutToBeOpened(KDevelop::IProject* project); void projectOpened(KDevelop::IProject* project); void projectOpeningAborted(KDevelop::IProject* project); }; } #endif diff --git a/language/backgroundparser/documentchangetracker.h b/language/backgroundparser/documentchangetracker.h index 04a411cb07..079feabdbd 100644 --- a/language/backgroundparser/documentchangetracker.h +++ b/language/backgroundparser/documentchangetracker.h @@ -1,258 +1,258 @@ /* * This file is part of KDevelop * * Copyright 2010 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. */ #ifndef KDEVPLATFORM_DOCUMENTCHANGETRACKER_H #define KDEVPLATFORM_DOCUMENTCHANGETRACKER_H #include #include #include #include #include #include #include #include namespace KTextEditor { class Document; class MovingRange; class MovingInterface; } namespace KDevelop { class DocumentChangeTracker; /** * These objects belongs to the foreground, and thus can only be accessed from background threads if the foreground lock is held. * */ class RevisionLockerAndClearerPrivate; /** * Helper class that locks a revision, and clears it on its destruction within the foreground thread. * Just delete it using deleteLater(). * */ class KDEVPLATFORMLANGUAGE_EXPORT RevisionLockerAndClearer : public QSharedData { public: typedef QExplicitlySharedDataPointer Ptr; ~RevisionLockerAndClearer(); /** * Returns the revision number * */ qint64 revision() const; /** * Whether the revision is still being held. It may have been lost due to document-reloads, * in which case the revision must not be used. * */ bool valid() const; /** * Transform a range from this document revision to the given @p to. * */ RangeInRevision transformToRevision(const RangeInRevision& range, const Ptr& to) const; /** * Transform a cursor from this document revision to the given @p to. * If a zero target revision is given, the transformation is done to the current document revision. * */ CursorInRevision transformToRevision(const CursorInRevision& cursor, const Ptr& to, KTextEditor::MovingCursor::InsertBehavior behavior = KTextEditor::MovingCursor::StayOnInsert) const; /** * Transforms the given range from this revision into the current revision. */ KTextEditor::Range transformToCurrentRevision(const RangeInRevision& range) const; /** * Transforms the given cursor from this revision into the current revision. */ KTextEditor::Cursor transformToCurrentRevision(const CursorInRevision& cursor, KTextEditor::MovingCursor::InsertBehavior behavior = KTextEditor::MovingCursor::StayOnInsert) const; /** * Transform ranges from the given document revision @p from to the this one. * If a zero @p from revision is given, the transformation is done from the current document revision. * */ RangeInRevision transformFromRevision(const RangeInRevision& range, const Ptr& from = Ptr()) const; /** * Transform ranges from the given document revision @p from to the this one. * If a zero @p from revision is given, the transformation is done from the current document revision. * */ CursorInRevision transformFromRevision(const CursorInRevision& cursor, const Ptr& from = Ptr(), KTextEditor::MovingCursor::InsertBehavior behavior = KTextEditor::MovingCursor::StayOnInsert) const; /** * Transforms the given range from the current revision into this revision. */ RangeInRevision transformFromCurrentRevision(const KTextEditor::Range& range) const; /** * Transforms the given cursor from the current revision into this revision. */ CursorInRevision transformFromCurrentRevision(const KTextEditor::Cursor& cursor, KTextEditor::MovingCursor::InsertBehavior behavior = KTextEditor::MovingCursor::StayOnInsert) const; private: friend class DocumentChangeTracker; RevisionLockerAndClearerPrivate* m_p; }; typedef RevisionLockerAndClearer::Ptr RevisionReference; /** * Internal helper class for RevisionLockerAndClearer * */ class KDEVPLATFORMLANGUAGE_EXPORT RevisionLockerAndClearerPrivate : public QObject { Q_OBJECT public: RevisionLockerAndClearerPrivate(DocumentChangeTracker* tracker, qint64 revision); - ~RevisionLockerAndClearerPrivate(); + ~RevisionLockerAndClearerPrivate() override; inline qint64 revision() const { return m_revision; } private: friend class RevisionLockerAndClearer; QPointer m_tracker; qint64 m_revision; }; class KDEVPLATFORMLANGUAGE_EXPORT DocumentChangeTracker : public QObject { Q_OBJECT public: explicit DocumentChangeTracker( KTextEditor::Document* document ); - virtual ~DocumentChangeTracker(); + ~DocumentChangeTracker() override; /** * Completions of the users current edits that are supposed to complete * not-yet-finished statements, like for example for-loops for parsing. * */ virtual QList > completions() const; /** * Resets the tracking to the current revision. * */ virtual void reset(); /** * Returns the document revision at which reset() was called last. * * The revision is being locked by the tracker in MovingInterface, * it will be unlocked as soon as reset() is called, so if you want to use * the revision afterwards, you have to lock it before calling reset. * * zero is returned if the revisions were invalidated after the last call. * */ RevisionReference revisionAtLastReset() const; /** * Returns the current revision (which is not locked by the tracker) * */ RevisionReference currentRevision(); /** * Whether the changes that happened since the last reset are significant enough to require an update * */ virtual bool needUpdate() const; /** * Returns the tracked document **/ KTextEditor::Document* document() const; KTextEditor::MovingInterface* documentMovingInterface() const; /** * Returns the revision object which locks the revision representing the on-disk state. * Returns a zero object if the file is not on disk. * */ RevisionReference diskRevision() const; /** * Returns whether the given revision is being current held, so that it can be used * for transformations in MovingInterface * */ bool holdingRevision(qint64 revision) const; /** * Use this function to acquire a revision. As long as the returned object is stored somewhere, * the revision can be used for transformations in MovingInterface, and especially for * DocumentChangeTracker::transformBetweenRevisions. * * Returns a zero revision object if the revision could not be acquired (it wasn't held). * */ RevisionReference acquireRevision(qint64 revision); /** * Safely maps the given range between the two given revisions. * The mapping is only done if both the from- and to- revision are held, * else the original range is returned. * * @warning: Make sure that you actually hold the referenced revisions, else no transformation will be done. * @note It is much less error-prone to use RevisionReference->transformToRevision() and RevisionReference->transformFromRevision() directly. * */ RangeInRevision transformBetweenRevisions(RangeInRevision range, qint64 fromRevision, qint64 toRevision) const; CursorInRevision transformBetweenRevisions(CursorInRevision cursor, qint64 fromRevision, qint64 toRevision, KTextEditor::MovingCursor::InsertBehavior behavior = KTextEditor::MovingCursor::StayOnInsert) const; KTextEditor::Range transformToCurrentRevision(RangeInRevision range, qint64 fromRevision) const; KTextEditor::Cursor transformToCurrentRevision(CursorInRevision cursor, qint64 fromRevision, KTextEditor::MovingCursor::InsertBehavior behavior = KTextEditor::MovingCursor::StayOnInsert) const; /// Transform the range from the current revision into the given one RangeInRevision transformToRevision(KTextEditor::Range range, qint64 toRevision) const; /// Transform the cursor from the current revision into the given one CursorInRevision transformToRevision(KTextEditor::Cursor cursor, qint64 toRevision, KTextEditor::MovingCursor::InsertBehavior behavior = KTextEditor::MovingCursor::StayOnInsert) const; protected: RevisionReference m_revisionAtLastReset; bool m_needUpdate; QString m_currentCleanedInsertion; KTextEditor::Cursor m_lastInsertionPosition; KTextEditor::MovingRange* m_changedRange; KTextEditor::Document* m_document; KTextEditor::MovingInterface* m_moving; KDevelop::IndexedString m_url; void updateChangedRange(); public slots: virtual void textInserted( KTextEditor::Document* document, const KTextEditor::Cursor& position, const QString& inserted ); virtual void textRemoved( KTextEditor::Document* document, const KTextEditor::Range& range, const QString& oldText ); void documentDestroyed( QObject* ); void aboutToInvalidateMovingInterfaceContent ( KTextEditor::Document* document ); void documentSavedOrUploaded(KTextEditor::Document*,bool); private: bool checkMergeTokens(const KTextEditor::Range& range); friend class RevisionLockerAndClearerPrivate; void lockRevision(qint64 revision); void unlockRevision(qint64 revision); QMap m_revisionLocks; ILanguageSupport::WhitespaceSensitivity m_whitespaceSensitivity; }; } #endif diff --git a/language/backgroundparser/parsejob.cpp b/language/backgroundparser/parsejob.cpp index 040b9e6879..55b13163d5 100644 --- a/language/backgroundparser/parsejob.cpp +++ b/language/backgroundparser/parsejob.cpp @@ -1,529 +1,529 @@ /* * This file is part of KDevelop * * Copyright 2006 Adam Treat * Copyright 2006-2008 Hamish Rodda * * 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 "parsejob.h" #include #include #include #include #include #include #include #include #include #include #include "backgroundparser.h" #include "util/debug.h" #include "duchain/topducontext.h" #include "duchain/duchainlock.h" #include "duchain/duchain.h" #include "duchain/parsingenvironment.h" #include #include #include #include #include #include #include #include using namespace KTextEditor; static QMutex minimumFeaturesMutex; static QHash > staticMinimumFeatures; namespace KDevelop { class ParseJobPrivate { public: ParseJobPrivate(const IndexedString& url_, ILanguageSupport* languageSupport_) : url( url_ ) , languageSupport( languageSupport_ ) , abortRequested( 0 ) , hasReadContents( false ) , aborted( false ) , features( TopDUContext::VisibleDeclarationsAndContexts ) , parsePriority( 0 ) , sequentialProcessingFlags( ParseJob::IgnoresSequentialProcessing ) { } ~ParseJobPrivate() { } ReferencedTopDUContext duContext; IndexedString url; ILanguageSupport* languageSupport; ParseJob::Contents contents; QAtomicInt abortRequested; bool hasReadContents : 1; bool aborted : 1; TopDUContext::Features features; QList > notify; QPointer tracker; RevisionReference revision; RevisionReference previousRevision; int parsePriority; ParseJob::SequentialProcessingFlags sequentialProcessingFlags; ThreadWeaver::QObjectDecorator* decorator; }; ParseJob::ParseJob( const IndexedString& url, KDevelop::ILanguageSupport* languageSupport ) : ThreadWeaver::Sequence(), d(new ParseJobPrivate(url, languageSupport)) { d->decorator = new ThreadWeaver::QObjectDecorator(this); } ParseJob::~ParseJob() { typedef QPointer QObjectPointer; foreach(const QObjectPointer &p, d->notify) { if(p) { QMetaObject::invokeMethod(p.data(), "updateReady", Qt::QueuedConnection, Q_ARG(KDevelop::IndexedString, d->url), Q_ARG(KDevelop::ReferencedTopDUContext, d->duContext)); } } delete d; } ILanguageSupport* ParseJob::languageSupport() const { return d->languageSupport; } void ParseJob::setParsePriority(int priority) { d->parsePriority = priority; } int ParseJob::parsePriority() const { return d->parsePriority; } bool ParseJob::requiresSequentialProcessing() const { return d->sequentialProcessingFlags & RequiresSequentialProcessing; } bool ParseJob::respectsSequentialProcessing() const { return d->sequentialProcessingFlags & RespectsSequentialProcessing; } void ParseJob::setSequentialProcessingFlags(SequentialProcessingFlags flags) { d->sequentialProcessingFlags = flags; } IndexedString ParseJob::document() const { return d->url; } bool ParseJob::success() const { return !d->aborted; } void ParseJob::setMinimumFeatures(TopDUContext::Features features) { d->features = features; } bool ParseJob::hasStaticMinimumFeatures() { QMutexLocker lock(&minimumFeaturesMutex); return ::staticMinimumFeatures.size(); } TopDUContext::Features ParseJob::staticMinimumFeatures(const IndexedString& url) { QMutexLocker lock(&minimumFeaturesMutex); TopDUContext::Features features = (TopDUContext::Features)0; if(::staticMinimumFeatures.contains(url)) foreach(const TopDUContext::Features &f, ::staticMinimumFeatures[url]) features = (TopDUContext::Features)(features | f); return features; } TopDUContext::Features ParseJob::minimumFeatures() const { return (TopDUContext::Features)(d->features | staticMinimumFeatures(d->url)); } void ParseJob::setDuChain(ReferencedTopDUContext duChain) { d->duContext = duChain; } ReferencedTopDUContext ParseJob::duChain() const { return d->duContext; } bool ParseJob::abortRequested() const { return d->abortRequested.load(); } void ParseJob::requestAbort() { d->abortRequested = 1; } void ParseJob::abortJob() { d->aborted = true; setStatus(Status_Aborted); } void ParseJob::setNotifyWhenReady(const QList >& notify ) { d->notify = notify; } void ParseJob::setStaticMinimumFeatures(const IndexedString& url, TopDUContext::Features features) { QMutexLocker lock(&minimumFeaturesMutex); ::staticMinimumFeatures[url].append(features); } void ParseJob::unsetStaticMinimumFeatures(const IndexedString& url, TopDUContext::Features features) { QMutexLocker lock(&minimumFeaturesMutex); ::staticMinimumFeatures[url].removeOne(features); if(::staticMinimumFeatures[url].isEmpty()) ::staticMinimumFeatures.remove(url); } KDevelop::ProblemPointer ParseJob::readContents() { Q_ASSERT(!d->hasReadContents); d->hasReadContents = true; QString localFile(document().toUrl().toLocalFile()); QFileInfo fileInfo( localFile ); QDateTime lastModified = fileInfo.lastModified(); d->tracker = ICore::self()->languageController()->backgroundParser()->trackerForUrl(document()); //Try using an artificial code-representation, which overrides everything else if(artificialCodeRepresentationExists(document())) { CodeRepresentation::Ptr repr = createCodeRepresentation(document()); d->contents.contents = repr->text().toUtf8(); qCDebug(LANGUAGE) << "took contents for " << document().str() << " from artificial code-representation"; return KDevelop::ProblemPointer(); } bool hadTracker = false; if(d->tracker) { ForegroundLock lock; if(DocumentChangeTracker* t = d->tracker.data()) { // The file is open in an editor d->previousRevision = t->revisionAtLastReset(); t->reset(); // Reset the tracker to the current revision Q_ASSERT(t->revisionAtLastReset()); d->contents.contents = t->document()->text().toUtf8(); d->contents.modification = KDevelop::ModificationRevision( lastModified, t->revisionAtLastReset()->revision() ); d->revision = t->acquireRevision(d->contents.modification.revision); hadTracker = true; } } if (!hadTracker) { // We have to load the file from disk static const int maximumFileSize = 5 * 1024 * 1024; // 5 MB if (fileInfo.size() > maximumFileSize) { KFormat f; KDevelop::ProblemPointer p(new Problem()); p->setSource(IProblem::Disk); p->setDescription(i18nc("%1: filename", "Skipped file that is too large: '%1'", localFile )); p->setExplanation(i18nc("%1: file size, %2: limit file size", "The file is %1 and exceeds the limit of %2.", f.formatByteSize(fileInfo.size()), f.formatByteSize(maximumFileSize))); p->setFinalLocation(DocumentRange(document(), KTextEditor::Range::invalid())); qCWarning(LANGUAGE) << p->description() << p->explanation(); return p; } QFile file( localFile ); if ( !file.open( QIODevice::ReadOnly ) ) { KDevelop::ProblemPointer p(new Problem()); p->setSource(IProblem::Disk); p->setDescription(i18n( "Could not open file '%1'", localFile )); switch (file.error()) { case QFile::ReadError: p->setExplanation(i18n("File could not be read from disk.")); break; case QFile::OpenError: p->setExplanation(i18n("File could not be opened.")); break; case QFile::PermissionsError: p->setExplanation(i18n("File could not be read from disk due to permissions.")); break; default: break; } p->setFinalLocation(DocumentRange(document(), KTextEditor::Range::invalid())); qCWarning(LANGUAGE) << "Could not open file" << document().str() << "(path" << localFile << ")" ; return p; } d->contents.contents = file.readAll(); ///@todo Convert from local encoding to utf-8 if they don't match d->contents.modification = KDevelop::ModificationRevision(lastModified); file.close(); } return KDevelop::ProblemPointer(); } const KDevelop::ParseJob::Contents& ParseJob::contents() const { Q_ASSERT(d->hasReadContents); return d->contents; } struct MovingRangeTranslator : public DUChainVisitor { MovingRangeTranslator(qint64 _source, qint64 _target, MovingInterface* _moving) : source(_source), target(_target), moving(_moving) { } - virtual void visit(DUContext* context) override { + void visit(DUContext* context) override { translateRange(context); ///@todo Also map import-positions // Translate uses uint usesCount = context->usesCount(); for(uint u = 0; u < usesCount; ++u) { RangeInRevision r = context->uses()[u].m_range; translateRange(r); context->changeUseRange(u, r); } } - virtual void visit(Declaration* declaration) override { + void visit(Declaration* declaration) override { translateRange(declaration); } void translateRange(DUChainBase* object) { RangeInRevision r = object->range(); translateRange(r); object->setRange(r); } void translateRange(RangeInRevision& r) { // PHP and python use top contexts that start at (0, 0) end at INT_MAX, so make sure that doesn't overflow // or translate the start of the top context away from (0, 0) if ( r.start.line != 0 || r.start.column != 0 ) { moving->transformCursor(r.start.line, r.start.column, MovingCursor::MoveOnInsert, source, target); } if ( r.end.line != std::numeric_limits::max() || r.end.column != std::numeric_limits::max() ) { moving->transformCursor(r.end.line, r.end.column, MovingCursor::StayOnInsert, source, target); } } KTextEditor::Range range; qint64 source; qint64 target; MovingInterface* moving; }; void ParseJob::translateDUChainToRevision(TopDUContext* context) { qint64 targetRevision = d->contents.modification.revision; if(targetRevision == -1) { qCDebug(LANGUAGE) << "invalid target revision" << targetRevision; return; } qint64 sourceRevision; { DUChainReadLocker duChainLock; Q_ASSERT(context->parsingEnvironmentFile()); // Cannot map if there is no source revision sourceRevision = context->parsingEnvironmentFile()->modificationRevision().revision; if(sourceRevision == -1) { qCDebug(LANGUAGE) << "invalid source revision" << sourceRevision; return; } } if(sourceRevision > targetRevision) { qCDebug(LANGUAGE) << "for document" << document().str() << ": source revision is higher than target revision:" << sourceRevision << " > " << targetRevision; return; } ForegroundLock lock; if(DocumentChangeTracker* t = d->tracker.data()) { if(!d->previousRevision) { qCDebug(LANGUAGE) << "not translating because there is no valid predecessor-revision"; return; } if(sourceRevision != d->previousRevision->revision() || !d->previousRevision->valid()) { qCDebug(LANGUAGE) << "not translating because the document revision does not match the tracker start revision (maybe the document was cleared)"; return; } if(!t->holdingRevision(sourceRevision) || !t->holdingRevision(targetRevision)) { qCDebug(LANGUAGE) << "lost one of the translation revisions, not doing the map"; return; } // Perform translation MovingInterface* moving = t->documentMovingInterface(); DUChainWriteLocker wLock; MovingRangeTranslator translator(sourceRevision, targetRevision, moving); context->visit(translator); QList< ProblemPointer > problems = context->problems(); for(QList< ProblemPointer >::iterator problem = problems.begin(); problem != problems.end(); ++problem) { RangeInRevision r = (*problem)->range(); translator.translateRange(r); (*problem)->setRange(r); } // Update the modification revision in the meta-data ModificationRevision modRev = context->parsingEnvironmentFile()->modificationRevision(); modRev.revision = targetRevision; context->parsingEnvironmentFile()->setModificationRevision(modRev); } } bool ParseJob::isUpdateRequired(const IndexedString& languageString) { if (abortRequested()) { return false; } if (minimumFeatures() & TopDUContext::ForceUpdate) { return true; } DUChainReadLocker lock; if (abortRequested()) { return false; } foreach(const ParsingEnvironmentFilePointer &file, DUChain::self()->allEnvironmentFiles(document())) { if (file->language() != languageString) { continue; } if (!file->needsUpdate(environment()) && file->featuresSatisfied(minimumFeatures())) { qCDebug(LANGUAGE) << "Already up to date" << document().str(); setDuChain(file->topContext()); lock.unlock(); highlightDUChain(); return false; } break; } return !abortRequested(); } const ParsingEnvironment* ParseJob::environment() const { return nullptr; } void ParseJob::highlightDUChain() { ENSURE_CHAIN_NOT_LOCKED if (!d->languageSupport->codeHighlighting() || !duChain() || abortRequested()) { // language doesn't support highlighting return; } if (!d->hasReadContents && !d->tracker) { d->tracker = ICore::self()->languageController()->backgroundParser()->trackerForUrl(document()); } if (d->tracker) { d->languageSupport->codeHighlighting()->highlightDUChain(duChain()); } } ControlFlowGraph* ParseJob::controlFlowGraph() { return nullptr; } DataAccessRepository* ParseJob::dataAccessInformation() { return nullptr; } bool ParseJob::hasTracker() const { return d->tracker; } ThreadWeaver::QObjectDecorator* ParseJob::decorator() const { return d->decorator; } } diff --git a/language/backgroundparser/parsejob.h b/language/backgroundparser/parsejob.h index 69c1d92c5b..f79b41c22e 100644 --- a/language/backgroundparser/parsejob.h +++ b/language/backgroundparser/parsejob.h @@ -1,243 +1,243 @@ /* * This file is part of KDevelop * * Copyright 2006 Adam Treat * Copyright 2006-2008 Hamish Rodda * * 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. */ #ifndef KDEVPLATFORM_PARSEJOB_H #define KDEVPLATFORM_PARSEJOB_H #include #include #include #include #include namespace ThreadWeaver { class QObjectDecorator; } namespace KDevelop { class ParsingEnvironment; class ControlFlowGraph; class DataAccessRepository; class BackgroundParser; class TopDUContext; class ReferencedTopDUContext; /** * The base class for background parser jobs. * * In your language plugin, don't forget to use acquire an UrlParseLock before starting to the actual parsing. */ class KDEVPLATFORMLANGUAGE_EXPORT ParseJob : public QObject, public ThreadWeaver::Sequence { Q_OBJECT public: explicit ParseJob( const IndexedString &url, ILanguageSupport* languageSupport ); /** * _No_ mutexes/locks are allowed to be locked when this object is destroyed (except for optionally the foreground lock) * */ - virtual ~ParseJob(); + ~ParseJob() override; /** * @return the language support that created this parse job. */ ILanguageSupport* languageSupport() const; struct Contents { // Modification-time of the read content ModificationRevision modification; // The contents in utf-8 format QByteArray contents; }; enum SequentialProcessingFlag { IgnoresSequentialProcessing = 0, RequiresSequentialProcessing = 1, RespectsSequentialProcessing = 2, FullSequentialProcessing = 3 }; Q_DECLARE_FLAGS(SequentialProcessingFlags, SequentialProcessingFlag) ///Sets the priority of this parse job. This is just for the purpose of ///reading it later, and does not affect the actual behaviour in any way. void setParsePriority(int priority); ///Get the priority of this parse job. ///Other than priority(), this will give you the "KDevelop-priority" of the job, ///not the QThread one (which is always zero). int parsePriority() const; /** * _No_ mutexes/locks are allowed to be locked when this is called (except for optionally the foreground lock) * * Locks the document revision so that mapping from/to the revision in the editor using MovingInterface will be possible. * * Returns an invalid pointer if the call succeeds, and a valid one if the reading fails. * */ KDevelop::ProblemPointer readContents(); /** * After reading the contents, you can call this to retrieve it. * */ const Contents& contents() const; /** * Translates the given context from its previous revision to the revision that has * been retrieved during readContents(). The top-context meta-data will be updated * with the revision. * * This can be done after reading the context before updating, so * that the correct ranges are matched onto each other during the update. * * _No_ mutexes/locks are allowed to be locked when this is called (except for optionally the foreground lock) */ void translateDUChainToRevision(TopDUContext* context); /** * Query whether this job is needed to be waited for when trying to process a job with a lower priority. **/ bool respectsSequentialProcessing() const; /** * Query whether this job requires all higher-priority jobs to finish before being processed itself. **/ bool requiresSequentialProcessing() const; void setSequentialProcessingFlags(SequentialProcessingFlags flags); /// \returns the indexed url of the document to be parsed. Q_SCRIPTABLE KDevelop::IndexedString document() const; /** * Sets a list of QObjects that should contain a slot * "void updateReady(KDevelop::IndexedString url, KDevelop::ReferencedTopDUContext topContext)". * The notification is guaranteed to be called once the parse-job finishes, from within its destructor. * The given top-context may be invalid if the update failed. */ Q_SCRIPTABLE void setNotifyWhenReady(const QList >& notify); /// Sets the du-context that was created by this parse-job Q_SCRIPTABLE virtual void setDuChain(ReferencedTopDUContext duChain); /// Returns the set du-context, or zero of none was set. Q_SCRIPTABLE virtual ReferencedTopDUContext duChain() const; /// Overridden to allow jobs to determine if they've been requested to abort - Q_SCRIPTABLE virtual void requestAbort() override; + Q_SCRIPTABLE void requestAbort() override; /// Determine if the job has been requested to abort Q_SCRIPTABLE bool abortRequested() const; /// Sets success to false, causing failed() to be emitted Q_SCRIPTABLE void abortJob(); /// Overridden to convey whether the job succeeded or not. - Q_SCRIPTABLE virtual bool success() const override; + Q_SCRIPTABLE bool success() const override; /// Set the minimum features the resulting top-context should have Q_SCRIPTABLE void setMinimumFeatures(TopDUContext::Features features); /// Minimum set of features the resulting top-context should have Q_SCRIPTABLE TopDUContext::Features minimumFeatures() const; /// Allows statically specifying an amount of features required for an url. /// These features will automatically be or'ed with the minimumFeatures() returned /// by any ParseJob with the given url. /// Since this causes some additional complixity in update-checking, minimum features should not /// be set permanently. static void setStaticMinimumFeatures(const IndexedString& url, TopDUContext::Features features); /// Must be called exactly once for each call to setStaticMinimumFeatures, with the same features. static void unsetStaticMinimumFeatures(const IndexedString& url, TopDUContext::Features features); /// Returns the statically set minimum features for the given url, or zero. static TopDUContext::Features staticMinimumFeatures(const IndexedString& url); /// Returns whether there is minimum features set up for some url static bool hasStaticMinimumFeatures(); ///Returns a structure containing information about data accesses in the parsed file. /// It's up to the caller to remove the returned instance virtual KDevelop::DataAccessRepository* dataAccessInformation(); ///Returns a control flow graph for the code in the parsed file. /// It's up to the caller to remove the returned instance virtual KDevelop::ControlFlowGraph* controlFlowGraph(); ThreadWeaver::QObjectDecorator* decorator() const; Q_SIGNALS: /**Can be used to give progress feedback to the background-parser. @param value should be between 0 and 1, where 0 = 0% and 1 = 100% * @param text may be a text that describes the current state of parsing * Do not trigger this too often, for performance reasons. */ void progress(KDevelop::ParseJob*, float value, const QString& text); protected: /** * Should return an environment for this parse job. * * This is then used to check whether existing cached data of previous parse jobs need an update. * The default implementation returns a nullptr. */ virtual const ParsingEnvironment* environment() const; /** * Checks whether there is already an up to date context available for the * current document. If so, it returns true and ensures that the document * is highlighted properly. Otherwise returns false. * * NOTE: This should be called while holding an URLParseLock for the * current document. * * @param languageString The unique string identifying your language. * This must be the same as you assign to the DUChain's environment file. * * @return True if an update is required, false if the job can return early. */ bool isUpdateRequired(const IndexedString& languageString); /** * Trigger an update to the code highlighting of the current file based * on the DUChain set in setDuChain. * * If the file for this parse job is not opened in an editor or if the language * support does not return a code highlighter, this will do nothing. * * NOTE: No DUChain lock should be held when you call this. */ void highlightDUChain(); /** * Returns whether there is a tracker for the current document. */ bool hasTracker() const; private: class ParseJobPrivate* const d; }; } Q_DECLARE_OPERATORS_FOR_FLAGS(KDevelop::ParseJob::SequentialProcessingFlags) Q_DECLARE_METATYPE(KDevelop::ParseJob*) #endif diff --git a/language/backgroundparser/parseprojectjob.h b/language/backgroundparser/parseprojectjob.h index ac8bcf3378..7604520171 100644 --- a/language/backgroundparser/parseprojectjob.h +++ b/language/backgroundparser/parseprojectjob.h @@ -1,57 +1,57 @@ /* Copyright 2009 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. */ #ifndef KDEVPLATFORM_PARSEPROJECTJOB_H #define KDEVPLATFORM_PARSEPROJECTJOB_H #include #include #include #include namespace KDevelop { class ReferencedTopDUContext; class IProject; ///A job that parses all project-files in the given project ///Deletes itself as soon as the project is deleted class KDEVPLATFORMLANGUAGE_EXPORT ParseProjectJob : public KJob { Q_OBJECT public: explicit ParseProjectJob(KDevelop::IProject* project, bool forceUpdate = false ); - virtual ~ParseProjectJob(); - virtual void start() override; - virtual bool doKill() override; + ~ParseProjectJob() override; + void start() override; + bool doKill() override; private Q_SLOTS: void deleteNow(); void updateReady(const KDevelop::IndexedString& url, KDevelop::ReferencedTopDUContext topContext); private: int m_updated; bool m_forceUpdate; KDevelop::IProject* m_project; QSet m_filesToParse; void updateProgress(); }; } #endif // KDEVPLATFORM_PARSEPROJECTJOB_H diff --git a/language/backgroundparser/tests/testlanguagesupport.h b/language/backgroundparser/tests/testlanguagesupport.h index b9263e8167..c7b98bcff5 100644 --- a/language/backgroundparser/tests/testlanguagesupport.h +++ b/language/backgroundparser/tests/testlanguagesupport.h @@ -1,43 +1,43 @@ /* * This file is part of KDevelop * * Copyright 2012 by Sven Brauch * * 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. */ #ifndef KDEVPLATFORM_TESTLANGUAGESUPPORT_H #define KDEVPLATFORM_TESTLANGUAGESUPPORT_H #include "language/interfaces/ilanguagesupport.h" #include using namespace KDevelop; class TestLanguageSupport : public QObject, public KDevelop::ILanguageSupport { Q_OBJECT Q_INTERFACES(KDevelop::ILanguageSupport) public: - virtual KDevelop::ParseJob* createParseJob(const IndexedString& url) override; - virtual QString name() const override; + KDevelop::ParseJob* createParseJob(const IndexedString& url) override; + QString name() const override; signals: void parseJobCreated(KDevelop::ParseJob* job); }; #endif diff --git a/language/backgroundparser/tests/testparsejob.h b/language/backgroundparser/tests/testparsejob.h index b836297f27..f2e75d220d 100644 --- a/language/backgroundparser/tests/testparsejob.h +++ b/language/backgroundparser/tests/testparsejob.h @@ -1,41 +1,41 @@ /* * This file is part of KDevelop * * Copyright 2012 by Sven Brauch * * 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. */ #ifndef KDEVPLATFORM_TESTPARSEJOB_H #define KDEVPLATFORM_TESTPARSEJOB_H #include "language/backgroundparser/parsejob.h" using namespace KDevelop; class TestParseJob : public KDevelop::ParseJob { Q_OBJECT public: TestParseJob(const IndexedString& url, ILanguageSupport* languageSupport); - virtual void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread* thread) override; - virtual ControlFlowGraph* controlFlowGraph() override; - virtual DataAccessRepository* dataAccessInformation() override; + void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread* thread) override; + ControlFlowGraph* controlFlowGraph() override; + DataAccessRepository* dataAccessInformation() override; int duration_ms; }; #endif diff --git a/language/classmodel/allclassesfolder.h b/language/classmodel/allclassesfolder.h index f97f9f0c3d..903770e753 100644 --- a/language/classmodel/allclassesfolder.h +++ b/language/classmodel/allclassesfolder.h @@ -1,74 +1,74 @@ /* * KDevelop Class Browser * * Copyright 2009 Lior Mualem * * 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. */ #ifndef KDEVPLATFORM_ALLCLASSESFOLDER_H #define KDEVPLATFORM_ALLCLASSESFOLDER_H #include "documentclassesfolder.h" namespace KDevelop { class IProject; } namespace ClassModelNodes { /// Special folder. /// It displays all the classes in the projects by using the IProject class AllClassesFolder : public DocumentClassesFolder { Q_OBJECT public: explicit AllClassesFolder(NodesModelInterface* a_model); public: // Node overrides - virtual void nodeCleared() override; - virtual void populateNode() override; + void nodeCleared() override; + void populateNode() override; private Q_SLOTS: // Project watching void projectOpened(KDevelop::IProject* project); void projectClosing(KDevelop::IProject* project); }; /// Contains a filter for the all classes folder. class FilteredAllClassesFolder : public AllClassesFolder { Q_OBJECT public: explicit FilteredAllClassesFolder(NodesModelInterface* a_model); public: // Operations. /// Call this to update the classes filter string. void updateFilterString(QString a_newFilterString); private: // DocumentClassesFolder overrides - virtual bool isClassFiltered(const KDevelop::QualifiedIdentifier& a_id) override; + bool isClassFiltered(const KDevelop::QualifiedIdentifier& a_id) override; private: /// We'll use this string to display only classes that match this string. QString m_filterString; }; } // namespace ClassModelNodes #endif diff --git a/language/classmodel/classmodel.h b/language/classmodel/classmodel.h index 193b7e4464..d0d64d06ed 100644 --- a/language/classmodel/classmodel.h +++ b/language/classmodel/classmodel.h @@ -1,154 +1,154 @@ /* * KDevelop Class Browser * * Copyright 2007-2008 Hamish Rodda * Copyright 2009 Lior Mualem * * 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. */ #ifndef KDEVPLATFORM_CLASSMODEL_H #define KDEVPLATFORM_CLASSMODEL_H #include #include "classmodelnode.h" #include class ClassBrowserPlugin; namespace KDevelop { class TopDUContext; class IDocument; class ParseJob; class DUContext; class IProject; class DUChainBase; class IndexedQualifiedIdentifier; } namespace ClassModelNodes { class Node; class FilteredAllClassesFolder; class FilteredProjectFolder; class FolderNode; class IdentifierNode; } /// The model interface accessible from the nodes. class NodesModelInterface { public: virtual ~NodesModelInterface(); public: enum Feature { AllProjectsClasses = 0x1, BaseAndDerivedClasses = 0x2, ClassInternals = 0x4 }; Q_DECLARE_FLAGS(Features, Feature) virtual void nodesLayoutAboutToBeChanged(ClassModelNodes::Node* a_parent) = 0; virtual void nodesLayoutChanged(ClassModelNodes::Node* a_parent) = 0; virtual void nodesRemoved(ClassModelNodes::Node* a_parent, int a_first, int a_last) = 0; virtual void nodesAboutToBeAdded(ClassModelNodes::Node* a_parent, int a_pos, int a_size) = 0; virtual void nodesAdded(ClassModelNodes::Node* a_parent) = 0; virtual Features features() const = 0; }; /** * @short A model that holds a convinient representation of the defined class in the project * * This model doesn't have much code in it, it mostly acts as a glue between the different * nodes and the tree view. * * The nodes are defined in the namespace @ref ClassModelNodes */ class KDEVPLATFORMLANGUAGE_EXPORT ClassModel : public QAbstractItemModel, public NodesModelInterface { Q_OBJECT public: ClassModel(); - virtual ~ClassModel(); + ~ClassModel() override; public: /// Retrieve the DU object related to the specified index. /// @note DUCHAINS READER LOCK MUST BE TAKEN! KDevelop::DUChainBase* duObjectForIndex(const QModelIndex& a_index); /// Call this to retrieve the index for the node associated with the specified id. QModelIndex getIndexForIdentifier(const KDevelop::IndexedQualifiedIdentifier& a_id); /// Return the model index associated with the given node. QModelIndex index(ClassModelNodes::Node* a_node) const; inline void setFeatures(NodesModelInterface::Features features); - virtual inline NodesModelInterface::Features features() const override { return m_features; } + inline NodesModelInterface::Features features() const override { return m_features; } public Q_SLOTS: /// Call this to update the filter string for the search results folder. void updateFilterString(QString a_newFilterString); /// removes the project-specific node void removeProjectNode(KDevelop::IProject* project); /// adds the project-specific node void addProjectNode(KDevelop::IProject* project); private: // NodesModelInterface overrides - virtual void nodesLayoutAboutToBeChanged(ClassModelNodes::Node* a_parent) override; - virtual void nodesLayoutChanged(ClassModelNodes::Node* a_parent) override; - virtual void nodesRemoved(ClassModelNodes::Node* a_parent, int a_first, int a_last) override; - virtual void nodesAboutToBeAdded(ClassModelNodes::Node* a_parent, int a_pos, int a_size) override; - virtual void nodesAdded(ClassModelNodes::Node* a_parent) override; + void nodesLayoutAboutToBeChanged(ClassModelNodes::Node* a_parent) override; + void nodesLayoutChanged(ClassModelNodes::Node* a_parent) override; + void nodesRemoved(ClassModelNodes::Node* a_parent, int a_first, int a_last) override; + void nodesAboutToBeAdded(ClassModelNodes::Node* a_parent, int a_pos, int a_size) override; + void nodesAdded(ClassModelNodes::Node* a_parent) override; private: /// Main level node - it's usually invisible. ClassModelNodes::Node* m_topNode; ClassModelNodes::FilteredAllClassesFolder* m_allClassesNode; QMap m_projectNodes; NodesModelInterface::Features m_features; public Q_SLOTS: /// This slot needs to be attached to collapsed signal in the tree view. void collapsed(const QModelIndex& index); /// This slot needs to be attached to expanded signal in the tree view. void expanded(const QModelIndex& index); public: // QAbstractItemModel overrides - virtual QFlags< Qt::ItemFlag > flags(const QModelIndex&) const override; - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; - virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QFlags< Qt::ItemFlag > flags(const QModelIndex&) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; - virtual bool hasChildren(const QModelIndex& parent = QModelIndex()) const override; + bool hasChildren(const QModelIndex& parent = QModelIndex()) const override; - virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; - virtual QModelIndex parent(const QModelIndex& child) const override; + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex& child) const override; }; inline void ClassModel::setFeatures(Features features) { m_features = features; } Q_DECLARE_OPERATORS_FOR_FLAGS(NodesModelInterface::Features) #endif // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/language/classmodel/classmodelnode.h b/language/classmodel/classmodelnode.h index 4220159816..bf1b1e561d 100644 --- a/language/classmodel/classmodelnode.h +++ b/language/classmodel/classmodelnode.h @@ -1,332 +1,332 @@ /* * KDevelop Class Browser * * Copyright 2007-2009 Hamish Rodda * Copyright 2009 Lior Mualem * * 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. */ #ifndef KDEVPLATFORM_CLASSMODELNODE_H #define KDEVPLATFORM_CLASSMODELNODE_H #include "classmodel.h" #include #include "../duchain/identifier.h" #include "../duchain/duchainpointer.h" #include "classmodelnodescontroller.h" class QTimer; class NodesModelInterface; namespace KDevelop { class ClassDeclaration; class ClassFunctionDeclaration; class ClassMemberDeclaration; class Declaration; } namespace ClassModelNodes { /// Base node class - provides basic functionality. class Node { public: Node(const QString& a_displayName, NodesModelInterface* a_model); virtual ~Node(); public: // Operations /// Clear all the children from the node. void clear(); /// Called by the model to collapse the node and remove sub-items if needed. virtual void collapse() {}; /// Called by the model to expand the node and populate it with sub-nodes if needed. virtual void expand() {}; /// Append a new child node to the list. void addNode(Node* a_child); /// Remove child node from the list and delete it. void removeNode(Node* a_child); /// Remove this node and delete it. void removeSelf() { m_parentNode->removeNode(this); } /// Called once the node has been populated to sort the entire tree / branch. void recursiveSort(); public: // Info retrieval /// Return the parent associated with this node. Node* getParent() const { return m_parentNode; } /// Get my index in the parent node int row(); /// Return the display name for the node. QString displayName() const { return m_displayName; } /// Returns a list of child nodes const QList& getChildren() const { return m_children; } /// Return an icon representation for the node. /// @note It calls the internal getIcon and caches the result. QIcon getCachedIcon(); public: // overridables /// Return a score when sorting the nodes. virtual int getScore() const = 0; /// Return true if the node contains sub-nodes. virtual bool hasChildren() const { return !m_children.empty(); } /// We use this string when sorting items. virtual QString getSortableString() const { return m_displayName; } protected: /// fill a_resultIcon with a display icon for the node. /// @param a_resultIcon returned icon. /// @return true if result was returned. virtual bool getIcon(QIcon& a_resultIcon) = 0; private: Node* m_parentNode; /// Called once the node has been populated to sort the entire tree / branch. void recursiveSortInternal(); protected: typedef QList< Node* > NodesList; NodesList m_children; QString m_displayName; QIcon m_cachedIcon; NodesModelInterface* m_model; }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Base class for nodes that generate and populate their child nodes dynamically class DynamicNode : public Node { public: DynamicNode(const QString& a_displayName, NodesModelInterface* a_model); /// Return true if the node was populated already. bool isPopulated() const { return m_populated; } /// Populate the node and mark the flag - called from expand or can be used internally. void performPopulateNode(bool a_forceRepopulate = false); public: // Node overrides. - virtual void collapse() override; - virtual void expand() override; - virtual bool hasChildren() const override; + void collapse() override; + void expand() override; + bool hasChildren() const override; protected: // overridables /// Called by the framework when the node is about to be expanded /// it should be populated with sub-nodes if applicable. virtual void populateNode() {} /// Called after the nodes have been removed. /// It's for derived classes to clean cached data. virtual void nodeCleared() {} private: bool m_populated; /// Clear all the child nodes and mark flag. void performNodeCleanup(); }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Base class for nodes associated with a @ref KDevelop::QualifiedIdentifier class IdentifierNode : public DynamicNode { public: IdentifierNode(KDevelop::Declaration* a_decl, NodesModelInterface* a_model, const QString& a_displayName = QString()); public: /// Returns the qualified identifier for this node by going through the tree const KDevelop::IndexedQualifiedIdentifier& getIdentifier() const { return m_identifier; } public: // Node overrides - virtual bool getIcon(QIcon& a_resultIcon) override; + bool getIcon(QIcon& a_resultIcon) override; public: // Overridables /// Return the associated declaration /// @note DU CHAIN MUST BE LOCKED FOR READ virtual KDevelop::Declaration* getDeclaration(); private: KDevelop::IndexedQualifiedIdentifier m_identifier; KDevelop::IndexedDeclaration m_indexedDeclaration; KDevelop::DeclarationPointer m_cachedDeclaration; }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// A node that represents an enum value. class EnumNode : public IdentifierNode { public: EnumNode(KDevelop::Declaration* a_decl, NodesModelInterface* a_model); public: // Node overrides - virtual int getScore() const override { return 102; } - virtual bool getIcon(QIcon& a_resultIcon) override; - virtual void populateNode() override; + int getScore() const override { return 102; } + bool getIcon(QIcon& a_resultIcon) override; + void populateNode() override; }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Provides display for a single class. class ClassNode : public IdentifierNode, public ClassModelNodeDocumentChangedInterface { public: ClassNode(KDevelop::Declaration* a_decl, NodesModelInterface* a_model); - virtual ~ClassNode(); + ~ClassNode() override; /// Lookup a contained class and return the related node. /// @return the node pointer or 0 if non was found. ClassNode* findSubClass(const KDevelop::IndexedQualifiedIdentifier& a_id); public: // Node overrides - virtual int getScore() const override { return 300; } - virtual void populateNode() override; - virtual void nodeCleared() override; - virtual bool hasChildren() const override { return true; } + int getScore() const override { return 300; } + void populateNode() override; + void nodeCleared() override; + bool hasChildren() const override { return true; } protected: // ClassModelNodeDocumentChangedInterface overrides - virtual void documentChanged(const KDevelop::IndexedString& a_file) override; + void documentChanged(const KDevelop::IndexedString& a_file) override; private: typedef QMap< uint, Node* > SubIdentifiersMap; /// Set of known sub-identifiers. It's used for updates check. SubIdentifiersMap m_subIdentifiers; /// We use this variable to know if we've registered for change notification or not. KDevelop::IndexedString m_cachedUrl; /// Updates the node to reflect changes in the declaration. /// @note DU CHAIN MUST BE LOCKED FOR READ /// @return true if something was updated. bool updateClassDeclarations(); /// Add "Base classes" and "Derived classes" folders, if needed /// @return true if one of the folders was added. bool addBaseAndDerived(); }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Provides a display for a single class function. class FunctionNode : public IdentifierNode { public: FunctionNode(KDevelop::Declaration* a_decl, NodesModelInterface* a_model); public: // Node overrides - virtual int getScore() const override { return 400; } - virtual QString getSortableString() const override { return m_sortableString; } + int getScore() const override { return 400; } + QString getSortableString() const override { return m_sortableString; } private: QString m_sortableString; }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Provides display for a single class variable. class ClassMemberNode : public IdentifierNode { public: ClassMemberNode(KDevelop::ClassMemberDeclaration* a_decl, NodesModelInterface* a_model); public: // Node overrides - virtual int getScore() const override { return 500; } - virtual bool getIcon(QIcon& a_resultIcon) override; + int getScore() const override { return 500; } + bool getIcon(QIcon& a_resultIcon) override; }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Provides a folder node with a static list of nodes. class FolderNode : public Node { public: FolderNode(const QString& a_displayName, NodesModelInterface* a_model); public: // Node overrides - virtual bool getIcon(QIcon& a_resultIcon) override; - virtual int getScore() const override { return 100; } + bool getIcon(QIcon& a_resultIcon) override; + int getScore() const override { return 100; } }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Provides a folder node with a dynamic list of nodes. class DynamicFolderNode : public DynamicNode { public: DynamicFolderNode(const QString& a_displayName, NodesModelInterface* a_model); public: // Node overrides - virtual bool getIcon(QIcon& a_resultIcon) override; - virtual int getScore() const override { return 100; } + bool getIcon(QIcon& a_resultIcon) override; + int getScore() const override { return 100; } }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Special folder - the parent is assumed to be a ClassNode. /// It then displays the base classes for the class it sits in. class BaseClassesFolderNode : public DynamicFolderNode { public: explicit BaseClassesFolderNode(NodesModelInterface* a_model); public: // Node overrides - virtual void populateNode() override; + void populateNode() override; }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Special folder - the parent is assumed to be a ClassNode. /// It then displays list of derived classes from the parent class. class DerivedClassesFolderNode : public DynamicFolderNode { public: explicit DerivedClassesFolderNode(NodesModelInterface* a_model); public: // Node overrides - virtual void populateNode() override; + void populateNode() override; }; } // namespace classModelNodes #endif // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/language/classmodel/classmodelnodescontroller.h b/language/classmodel/classmodelnodescontroller.h index a08e5e0dc8..369575372c 100644 --- a/language/classmodel/classmodelnodescontroller.h +++ b/language/classmodel/classmodelnodescontroller.h @@ -1,73 +1,73 @@ /* * KDevelop Class Browser * * Copyright 2009 Lior Mualem * * 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. */ #ifndef KDEVPLATFORM_CLASSMODELNODESCONTROLLER_H #define KDEVPLATFORM_CLASSMODELNODESCONTROLLER_H #include #include "../../serialization/indexedstring.h" #include "../duchain/ducontext.h" class QTimer; class ClassModelNodeDocumentChangedInterface { public: virtual ~ClassModelNodeDocumentChangedInterface(); /// Called when the registered document is changed. virtual void documentChanged(const KDevelop::IndexedString& a_file) = 0; }; /// This class provides notifications for updates between the different nodes /// and the various kdevelop sub-systems (such as notification when a DUChain gets /// updated). class ClassModelNodesController : public QObject { Q_OBJECT public: ClassModelNodesController(); - ~ClassModelNodesController(); + ~ClassModelNodesController() override; static ClassModelNodesController& self(); /// Register the given class node to receive notifications about its top context changes. void registerForChanges(const KDevelop::IndexedString& a_file, ClassModelNodeDocumentChangedInterface* a_node); /// Unregister the given class node from further notifications. void unregisterForChanges(const KDevelop::IndexedString& a_file, ClassModelNodeDocumentChangedInterface* a_node); private Q_SLOTS: // Files update. void updateChangedFiles(); private: // File updates related. /// List of updated files we check this list when update timer expires. QSet m_updatedFiles; /// Timer for batch updates. QTimer* m_updateTimer; typedef QMultiMap< KDevelop::IndexedString, ClassModelNodeDocumentChangedInterface* > FilesMap; /// Maps between monitored files and their class nodes. FilesMap m_filesMap; }; #endif diff --git a/language/classmodel/documentclassesfolder.cpp b/language/classmodel/documentclassesfolder.cpp index b42e0cbf4d..0d8750c032 100644 --- a/language/classmodel/documentclassesfolder.cpp +++ b/language/classmodel/documentclassesfolder.cpp @@ -1,451 +1,451 @@ /* * KDevelop Class Browser * * Copyright 2009 Lior Mualem * * 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 "documentclassesfolder.h" #include "../duchain/declaration.h" #include "../duchain/duchainlock.h" #include "../duchain/duchain.h" #include "../duchain/persistentsymboltable.h" #include "../duchain/codemodel.h" #include #include #include using namespace KDevelop; using namespace ClassModelNodes; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Contains a static list of classes within the namespace. class ClassModelNodes::StaticNamespaceFolderNode : public Node { public: StaticNamespaceFolderNode(const KDevelop::QualifiedIdentifier& a_identifier, NodesModelInterface* a_model); /// Returns the qualified identifier for this node const KDevelop::QualifiedIdentifier& qualifiedIdentifier() const { return m_identifier; } public: // Node overrides - virtual bool getIcon(QIcon& a_resultIcon) override; - virtual int getScore() const override { return 101; } + bool getIcon(QIcon& a_resultIcon) override; + int getScore() const override { return 101; } private: /// The namespace identifier. KDevelop::QualifiedIdentifier m_identifier; }; StaticNamespaceFolderNode::StaticNamespaceFolderNode(const KDevelop::QualifiedIdentifier& a_identifier, NodesModelInterface* a_model) : Node(a_identifier.last().toString(), a_model) , m_identifier(a_identifier) { } bool StaticNamespaceFolderNode::getIcon(QIcon& a_resultIcon) { static QIcon folderIcon = QIcon::fromTheme("namespace"); a_resultIcon = folderIcon; return true; } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// DocumentClassesFolder::OpenedFileClassItem::OpenedFileClassItem(const KDevelop::IndexedString& a_file, const KDevelop::IndexedQualifiedIdentifier& a_classIdentifier, ClassModelNodes::ClassNode* a_nodeItem) : file(a_file) , classIdentifier(a_classIdentifier) , nodeItem(a_nodeItem) { } DocumentClassesFolder::DocumentClassesFolder(const QString& a_displayName, NodesModelInterface* a_model) : DynamicFolderNode(a_displayName, a_model) , m_updateTimer( new QTimer(this) ) { connect( m_updateTimer, &QTimer::timeout, this, &DocumentClassesFolder::updateChangedFiles); } void DocumentClassesFolder::updateChangedFiles() { bool hadChanges = false; // re-parse changed documents. foreach( const IndexedString& file, m_updatedFiles ) { // Make sure it's one of the monitored files. if ( m_openFiles.contains(file) ) hadChanges |= updateDocument(file); } // Processed all files. m_updatedFiles.clear(); // Sort if had changes. if ( hadChanges ) recursiveSort(); } void DocumentClassesFolder::nodeCleared() { // Clear cached namespaces list (node was cleared). m_namespaces.clear(); // Clear open files and classes list m_openFiles.clear(); m_openFilesClasses.clear(); // Stop the update timer. m_updateTimer->stop(); } void DocumentClassesFolder::populateNode() { // Start updates timer - this is the required delay. m_updateTimer->start(2000); } QSet< KDevelop::IndexedString > DocumentClassesFolder::getAllOpenDocuments() { return m_openFiles; } ClassNode* DocumentClassesFolder::findClassNode(const IndexedQualifiedIdentifier& a_id) { // Make sure that the classes node is populated, otherwise // the lookup will not work. performPopulateNode(); ClassIdentifierIterator iter = m_openFilesClasses.get().find(a_id); if ( iter == m_openFilesClasses.get().end() ) return 0; // If the node is invisible - make it visible by going over the identifiers list. if ( iter->nodeItem == 0 ) { QualifiedIdentifier qualifiedIdentifier = a_id.identifier(); // Ignore zero length identifiers. if ( qualifiedIdentifier.count() == 0 ) return 0; ClassNode* closestNode = 0; int closestNodeIdLen = qualifiedIdentifier.count(); // First find the closest visible class node by reverse iteration over the id list. while ( (closestNodeIdLen > 0) && (closestNode == 0) ) { // Omit one from the end. --closestNodeIdLen; // Find the closest class. closestNode = findClassNode(qualifiedIdentifier.mid(0, closestNodeIdLen)); } if ( closestNode != 0 ) { // Start iterating forward from this node by exposing each class. // By the end of this loop, closestNode should hold the actual node. while ( closestNode && (closestNodeIdLen < qualifiedIdentifier.count()) ) { // Try the next Id. ++closestNodeIdLen; closestNode = closestNode->findSubClass(qualifiedIdentifier.mid(0, closestNodeIdLen)); } } return closestNode; } return iter->nodeItem; } void DocumentClassesFolder::closeDocument(const IndexedString& a_file) { // Get list of nodes associated with this file and remove them. std::pair< FileIterator, FileIterator > range = m_openFilesClasses.get().equal_range( a_file ); if ( range.first != m_openFilesClasses.get().end() ) { BOOST_FOREACH( const OpenedFileClassItem& item, range ) { if ( item.nodeItem ) removeClassNode(item.nodeItem); } // Clear the lists m_openFilesClasses.get().erase(range.first, range.second); } // Clear the file from the list of monitored documents. m_openFiles.remove(a_file); } bool DocumentClassesFolder::updateDocument(const KDevelop::IndexedString& a_file) { uint codeModelItemCount = 0; const CodeModelItem* codeModelItems; CodeModel::self().items(a_file, codeModelItemCount, codeModelItems); // List of declared namespaces in this file. QSet< QualifiedIdentifier > declaredNamespaces; // List of removed classes - it initially contains all the known classes, we'll eliminate them // one by one later on when we encounter them in the document. QMap< IndexedQualifiedIdentifier, FileIterator > removedClasses; { std::pair< FileIterator, FileIterator > range = m_openFilesClasses.get().equal_range( a_file ); for ( FileIterator iter = range.first; iter != range.second; ++iter ) { removedClasses.insert(iter->classIdentifier, iter); } } bool documentChanged = false; for(uint codeModelItemIndex = 0; codeModelItemIndex < codeModelItemCount; ++codeModelItemIndex) { const CodeModelItem& item = codeModelItems[codeModelItemIndex]; // Don't insert unknown or forward declarations into the class browser if ( (item.kind & CodeModelItem::Unknown) || (item.kind & CodeModelItem::ForwardDeclaration) ) continue; KDevelop::QualifiedIdentifier id = item.id.identifier(); // Don't add empty identifiers. if ( id.count() == 0 ) continue; // If it's a namespace, create it in the list. if ( item.kind & CodeModelItem::Namespace ) { // This should create the namespace folder and add it to the cache. getNamespaceFolder(id); // Add to the locally created namespaces. declaredNamespaces.insert(id); } else if ( item.kind & CodeModelItem::Class ) { // Ignore empty unnamed classes. if ( id.last().toString().isEmpty() ) continue; // See if it matches our filter? if ( isClassFiltered(id) ) continue; // Is this a new class or an existing class? if ( removedClasses.contains(id) ) { // It already exist - remove it from the known classes and continue. removedClasses.remove(id); continue; } // Where should we put this class? Node* parentNode = 0; // Check if it's namespaced and add it to the proper namespace. if ( id.count() > 1 ) { QualifiedIdentifier parentIdentifier(id.left(-1)); // Look up the namespace in the cache. // If we fail to find it we assume that the parent context is a class // and in that case, when the parent class gets expanded, it will show it. NamespacesMap::iterator iter = m_namespaces.find(parentIdentifier); if ( iter != m_namespaces.end() ) { // Add to the namespace node. parentNode = iter.value(); } else { // Reaching here means we didn't encounter any namespace declaration in the document // But a class might still be declared under a namespace. // So we'll perform a more through search to see if it's under a namespace. DUChainReadLocker readLock(DUChain::lock()); uint declsCount = 0; const IndexedDeclaration* decls; PersistentSymbolTable::self().declarations(parentIdentifier, declsCount, decls); for ( uint i = 0; i < declsCount; ++i ) { // Look for the first valid declaration. if ( decls->declaration() ) { // See if it should be namespaced. if ( decls->declaration()->kind() == Declaration::Namespace ) { // This should create the namespace folder and add it to the cache. parentNode = getNamespaceFolder(parentIdentifier); // Add to the locally created namespaces. declaredNamespaces.insert(parentIdentifier); } break; } } } } else { // Add to the main root. parentNode = this; } ClassNode* newNode = 0; if ( parentNode != 0 ) { // Create the new node and add it. IndexedDeclaration decl; uint count = 0; const IndexedDeclaration* declarations; DUChainReadLocker lock; PersistentSymbolTable::self().declarations(item.id, count, declarations); for ( uint i = 0; i < count; ++i ) { if (declarations[i].indexedTopContext().url() == a_file) { decl = declarations[i]; break; } } if (decl.isValid()) { newNode = new ClassNode(decl.declaration(), m_model); parentNode->addNode( newNode ); } } // Insert it to the map - newNode can be 0 - meaning the class is hidden. m_openFilesClasses.insert( OpenedFileClassItem( a_file, id, newNode ) ); documentChanged = true; } } // Remove empty namespaces from the list. // We need this because when a file gets unloaded, we unload the declared classes in it // and if a namespace has no class in it, it'll forever exist and no one will remove it // from the children list. foreach( const QualifiedIdentifier& id, declaredNamespaces ) removeEmptyNamespace(id); // Clear erased classes. foreach( const FileIterator& item, removedClasses ) { if ( item->nodeItem ) removeClassNode(item->nodeItem); m_openFilesClasses.get().erase(item); documentChanged = true; } return documentChanged; } void DocumentClassesFolder::parseDocument(const IndexedString& a_file) { // Add the document to the list of open files - this means we monitor it. if ( !m_openFiles.contains(a_file) ) m_openFiles.insert(a_file); updateDocument(a_file); } void DocumentClassesFolder::removeClassNode(ClassModelNodes::ClassNode* a_node) { // Get the parent namespace identifier. QualifiedIdentifier parentNamespaceIdentifier; if ( auto namespaceParent = dynamic_cast(a_node->getParent()) ) { parentNamespaceIdentifier = namespaceParent->qualifiedIdentifier(); } // Remove the node. a_node->removeSelf(); // Remove empty namespace removeEmptyNamespace(parentNamespaceIdentifier); } void DocumentClassesFolder::removeEmptyNamespace(const QualifiedIdentifier& a_identifier) { // Stop condition. if ( a_identifier.count() == 0 ) return; // Look it up in the cache. NamespacesMap::iterator iter = m_namespaces.find(a_identifier); if ( iter != m_namespaces.end() ) { if ( !(*iter)->hasChildren() ) { // Remove this node and try to remove the parent node. QualifiedIdentifier parentIdentifier = (*iter)->qualifiedIdentifier().left(-1); (*iter)->removeSelf(); m_namespaces.remove(a_identifier); removeEmptyNamespace(parentIdentifier); } } } StaticNamespaceFolderNode* DocumentClassesFolder::getNamespaceFolder(const KDevelop::QualifiedIdentifier& a_identifier) { // Stop condition. if ( a_identifier.count() == 0 ) return 0; // Look it up in the cache. NamespacesMap::iterator iter = m_namespaces.find(a_identifier); if ( iter == m_namespaces.end() ) { // It's not in the cache - create folders up to it. Node* parentNode = getNamespaceFolder(a_identifier.left(-1)); if ( parentNode == 0 ) parentNode = this; // Create the new node. StaticNamespaceFolderNode* newNode = new StaticNamespaceFolderNode(a_identifier, m_model); parentNode->addNode( newNode ); // Add it to the cache. m_namespaces.insert( a_identifier, newNode ); // Return the result. return newNode; } else return *iter; } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/language/classmodel/documentclassesfolder.h b/language/classmodel/documentclassesfolder.h index 5479329442..85902050cb 100644 --- a/language/classmodel/documentclassesfolder.h +++ b/language/classmodel/documentclassesfolder.h @@ -1,155 +1,155 @@ /* * KDevelop Class Browser * * Copyright 2009 Lior Mualem * * 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. */ #ifndef KDEVPLATFORM_DOCUMENTCLASSESFOLDER_H #define KDEVPLATFORM_DOCUMENTCLASSESFOLDER_H #include "classmodelnode.h" #include #include #include namespace ClassModelNodes { class StaticNamespaceFolderNode; /// This folder displays all the classes that relate to a list of documents. class DocumentClassesFolder : public QObject, public DynamicFolderNode { Q_OBJECT public: DocumentClassesFolder(const QString& a_displayName, NodesModelInterface* a_model); public: // Operations /// Find a class node in the lists by its id. ClassNode* findClassNode(const KDevelop::IndexedQualifiedIdentifier& a_id); protected: // Documents list handling. /// Parse a single document for classes and add them to the list. void parseDocument(const KDevelop::IndexedString& a_file); /// Re-parse the given document - remove old declarations and add new declarations. bool updateDocument(const KDevelop::IndexedString& a_file); /// Close and remove all the nodes related to the specified document. void closeDocument(const KDevelop::IndexedString& a_file); /// Returns a list of documents we have monitored. QSet< KDevelop::IndexedString > getAllOpenDocuments(); protected: // Overridables /// Override this to filter the found classes. virtual bool isClassFiltered(const KDevelop::QualifiedIdentifier&) { return false; } public: // Node overrides - virtual void nodeCleared() override; - virtual void populateNode() override; - virtual bool hasChildren() const override { return true; } + void nodeCleared() override; + void populateNode() override; + bool hasChildren() const override { return true; } private Q_SLOTS: // Files update. void updateChangedFiles(); private: // File updates related. /// List of updated files we check this list when update timer expires. QSet m_updatedFiles; /// Timer for batch updates. QTimer* m_updateTimer; private: // Opened class identifiers container definition. // An opened class item. struct OpenedFileClassItem { OpenedFileClassItem(); OpenedFileClassItem(const KDevelop::IndexedString& a_file, const KDevelop::IndexedQualifiedIdentifier& a_classIdentifier, ClassNode* a_nodeItem); /// The file this class declaration comes from. KDevelop::IndexedString file; /// The identifier for this class. KDevelop::IndexedQualifiedIdentifier classIdentifier; /// An existing node item. It maybe 0 - meaning the class node is currently hidden. ClassNode* nodeItem; }; // Index definitions. struct FileIndex {}; struct ClassIdentifierIndex {}; // Member types definitions. typedef boost::multi_index::member< OpenedFileClassItem, KDevelop::IndexedString, &OpenedFileClassItem::file> FileMember; typedef boost::multi_index::member< OpenedFileClassItem, KDevelop::IndexedQualifiedIdentifier, &OpenedFileClassItem::classIdentifier> ClassIdentifierMember; // Container definition. typedef boost::multi_index::multi_index_container< OpenedFileClassItem, boost::multi_index::indexed_by< boost::multi_index::ordered_non_unique< boost::multi_index::tag, FileMember >, boost::multi_index::ordered_unique< boost::multi_index::tag, ClassIdentifierMember > > > OpenFilesContainer; // Iterators definition. typedef OpenFilesContainer::index_iterator::type FileIterator; typedef OpenFilesContainer::index_iterator::type ClassIdentifierIterator; /// Maps all displayed classes and their referenced files. OpenFilesContainer m_openFilesClasses; /// Holds a set of open files. QSet< KDevelop::IndexedString > m_openFiles; private: typedef QMap< KDevelop::IndexedQualifiedIdentifier, StaticNamespaceFolderNode* > NamespacesMap; /// Holds a map between an identifier and a namespace folder we hold. NamespacesMap m_namespaces; /// Recursively create a namespace folder for the specified identifier if it doesn't /// exist, cache it and return it (or just return it from the cache). StaticNamespaceFolderNode* getNamespaceFolder(const KDevelop::QualifiedIdentifier& a_identifier); /// Removes the given namespace identifier recursively if it's empty. void removeEmptyNamespace(const KDevelop::QualifiedIdentifier& a_identifier); /// Remove a single class node from the lists. void removeClassNode(ClassNode* a_node); }; } // namespace ClassModelNodes #endif // KDEVPLATFORM_DOCUMENTCLASSESFOLDER_H diff --git a/language/classmodel/projectfolder.h b/language/classmodel/projectfolder.h index c9fd858754..db80680378 100644 --- a/language/classmodel/projectfolder.h +++ b/language/classmodel/projectfolder.h @@ -1,71 +1,71 @@ /* * KDevelop Class Browser * * Copyright 2009 Milian Wolff * * 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. */ #ifndef KDEVPLATFORM_PROJECTFOLDER_H #define KDEVPLATFORM_PROJECTFOLDER_H #include "documentclassesfolder.h" namespace KDevelop { class IProject; } namespace ClassModelNodes { /// Special folder /// It displays all items of a given project. class ProjectFolder : public DocumentClassesFolder { Q_OBJECT public: ProjectFolder(NodesModelInterface* a_model, KDevelop::IProject* project); explicit ProjectFolder(NodesModelInterface* a_model); - virtual void populateNode() override; + void populateNode() override; protected: KDevelop::IProject* m_project; }; /// Filter for the project folder. /// TODO: can't we share some code with FilteredAllClassesFolder somehow? class FilteredProjectFolder : public ProjectFolder { Q_OBJECT public: FilteredProjectFolder(NodesModelInterface* a_model, KDevelop::IProject* project); public: // Operations. /// Call this to update the classes filter string. void updateFilterString(QString a_newFilterString); private: // DocumentClassesFolder overrides - virtual bool isClassFiltered(const KDevelop::QualifiedIdentifier& a_id) override; + bool isClassFiltered(const KDevelop::QualifiedIdentifier& a_id) override; private: /// We'll use this string to display only classes that match this string. QString m_filterString; }; } #endif // KDEVPLATFORM_PROJECTFOLDER_H diff --git a/language/codecompletion/codecompletion.h b/language/codecompletion/codecompletion.h index 104be9c22e..ddafc9f695 100644 --- a/language/codecompletion/codecompletion.h +++ b/language/codecompletion/codecompletion.h @@ -1,79 +1,79 @@ /* * KDevelop Generic Code Completion Support * * Copyright 2006 Hamish Rodda * * 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. */ #ifndef KDEVPLATFORM_CODECOMPLETION_H #define KDEVPLATFORM_CODECOMPLETION_H #include #include namespace KParts { class Part; } namespace KTextEditor { class Document; class View; class CodeCompletionModel; } namespace KDevelop { class IDocument; class ILanguage; // TODO: cleanup this class for 5.1 class KDEVPLATFORMLANGUAGE_EXPORT CodeCompletion : public QObject { Q_OBJECT public: /** CodeCompletion will be the @p aModel parent. * If @p language is empty, the completion model will work for all files, * otherwise only for ones that contain the selected language. */ CodeCompletion(QObject* parent, KTextEditor::CodeCompletionModel* aModel, const QString& language); - virtual ~CodeCompletion(); + ~CodeCompletion() override; private Q_SLOTS: void textDocumentCreated(KDevelop::IDocument*); void viewCreated(KTextEditor::Document *document, KTextEditor::View *view); void documentUrlChanged(KDevelop::IDocument*); /** * check already opened documents, * needs to be done via delayed call to prevent infinite loop in * checkDocument() -> load lang plugin -> register CodeCompletion -> checkDocument() -> ... */ void checkDocuments(); signals: void registeredToView(KTextEditor::View* view); void unregisteredFromView(KTextEditor::View* view); private: void unregisterDocument(KTextEditor::Document*); void checkDocument(KTextEditor::Document*); KTextEditor::CodeCompletionModel* m_model; QString m_language; }; } #endif diff --git a/language/codecompletion/codecompletionitem.h b/language/codecompletion/codecompletionitem.h index ec42e07a77..1d83e438b3 100644 --- a/language/codecompletion/codecompletionitem.h +++ b/language/codecompletion/codecompletionitem.h @@ -1,152 +1,152 @@ /* * KDevelop Generic Code Completion Support * * Copyright 2007-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. */ #ifndef KDEVPLATFORM_KDEV_CODECOMPLETIONITEM_H #define KDEVPLATFORM_KDEV_CODECOMPLETIONITEM_H #include #include "../duchain/duchainpointer.h" #include "codecompletioncontext.h" namespace KTextEditor { class CodeCompletionModel; class Range; class Cursor; } class QModelIndex; namespace KDevelop { class CodeCompletionModel; struct CompletionTreeNode; class CompletionTreeItem; class IndexedType; class KDEVPLATFORMLANGUAGE_EXPORT CompletionTreeElement : public QSharedData { public: CompletionTreeElement(); virtual ~CompletionTreeElement(); CompletionTreeElement* parent() const; ///Reparenting is not supported. This is only allowed if parent() is still zero. void setParent(CompletionTreeElement*); int rowInParent() const; int columnInParent() const; ///Each element is either a node, or an item. CompletionTreeNode* asNode(); CompletionTreeItem* asItem(); template T* asItem() { return dynamic_cast(this); } template const T* asItem() const { return dynamic_cast(this); } const CompletionTreeNode* asNode() const; const CompletionTreeItem* asItem() const; private: CompletionTreeElement* m_parent; int m_rowInParent; }; struct KDEVPLATFORMLANGUAGE_EXPORT CompletionTreeNode : public CompletionTreeElement { CompletionTreeNode(); - ~CompletionTreeNode(); + ~CompletionTreeNode() override; KTextEditor::CodeCompletionModel::ExtraItemDataRoles role; QVariant roleValue; ///Will append the child, and initialize it correctly to create a working tree-structure void appendChild(QExplicitlySharedDataPointer); void appendChildren(QList >); void appendChildren(QList >); ///@warning Do not manipulate this directly, that's bad for consistency. Use appendChild instead. QList > children; }; class KDEVPLATFORMLANGUAGE_EXPORT CompletionTreeItem : public CompletionTreeElement { public: ///Execute the completion item. The default implementation does nothing. virtual void execute(KTextEditor::View* view, const KTextEditor::Range& word); ///Should return normal completion data, @see KTextEditor::CodeCompletionModel ///The default implementation returns "unimplemented", so re-implement it! ///The duchain is not locked when this is called ///Navigation-widgets should be registered to the model, then it will care about the interaction. virtual QVariant data(const QModelIndex& index, int role, const CodeCompletionModel* model) const; ///Should return the inheritance-depth. The completion-items don't need to return it through the data() function. virtual int inheritanceDepth() const; ///Should return the argument-hint depth. The completion-items don't need to return it through the data() function. virtual int argumentHintDepth() const; ///The default-implementation calls DUChainUtils::completionProperties virtual KTextEditor::CodeCompletionModel::CompletionProperties completionProperties() const; ///If this item represents a Declaration, this should return the declaration. ///The default-implementation returns zero. virtual DeclarationPointer declaration() const; ///Should return the types should be used for matching items against this one when it's an argument hint. ///The matching against all types should be done, and the best one will be used as final match result. virtual QList typeForArgumentMatching() const; ///Should return whether this completion-items data changes with input done by the user during code-completion. ///Returning true is very expensive. virtual bool dataChangedWithInput() const; }; ///A custom-group node, that can be used as-is. Just create it, and call appendChild to add group items. ///The items in the group will be shown in the completion-list with a group-header that contains the given name struct KDEVPLATFORMLANGUAGE_EXPORT CompletionCustomGroupNode : public CompletionTreeNode { ///@param inheritanceDepth @see KTextEditor::CodeCompletionModel::GroupRole CompletionCustomGroupNode(QString groupName, int inheritanceDepth = 700); int inheritanceDepth; }; typedef QExplicitlySharedDataPointer CompletionTreeItemPointer; typedef QExplicitlySharedDataPointer CompletionTreeElementPointer; } Q_DECLARE_METATYPE(KDevelop::CompletionTreeElementPointer); #endif diff --git a/language/codecompletion/codecompletionmodel.cpp b/language/codecompletion/codecompletionmodel.cpp index 5bcc8d7ac0..aa9c242c0b 100644 --- a/language/codecompletion/codecompletionmodel.cpp +++ b/language/codecompletion/codecompletionmodel.cpp @@ -1,452 +1,452 @@ /* * KDevelop Generic Code Completion Support * * Copyright 2006-2008 Hamish Rodda * Copyright 2007-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 "codecompletionmodel.h" #include #include #include #include #include #include #include #include #include #include "../duchain/declaration.h" #include "../duchain/classfunctiondeclaration.h" #include "../duchain/ducontext.h" #include "../duchain/duchain.h" #include "../duchain/namespacealiasdeclaration.h" #include "../duchain/parsingenvironment.h" #include "../duchain/duchainlock.h" #include "../duchain/duchainbase.h" #include "../duchain/topducontext.h" #include "../duchain/duchainutils.h" #include "../interfaces/quickopendataprovider.h" #include "../interfaces/icore.h" #include "../interfaces/ilanguagecontroller.h" #include "../interfaces/icompletionsettings.h" #include "util/debug.h" #include "codecompletionworker.h" #include "codecompletioncontext.h" #include #if KTEXTEDITOR_VERSION < QT_VERSION_CHECK(5, 10, 0) Q_DECLARE_METATYPE(KTextEditor::Cursor) #endif using namespace KTextEditor; //Multi-threaded completion creates some multi-threading related crashes, and sometimes shows the completions in the wrong position if the cursor was moved // #define SINGLE_THREADED_COMPLETION namespace KDevelop { class CompletionWorkerThread : public QThread { public: CompletionWorkerThread(CodeCompletionModel* model) : QThread(model), m_model(model), m_worker(m_model->createCompletionWorker()) { Q_ASSERT(m_worker->parent() == 0); // Must be null, else we cannot change the thread affinity! m_worker->moveToThread(this); Q_ASSERT(m_worker->thread() == this); } - ~CompletionWorkerThread() { + ~CompletionWorkerThread() override { delete m_worker; } - virtual void run () override { + void run () override { //We connect directly, so we can do the pre-grouping within the background thread connect(m_worker, &CodeCompletionWorker::foundDeclarationsReal, m_model, &CodeCompletionModel::foundDeclarations, Qt::QueuedConnection); connect(m_model, &CodeCompletionModel::completionsNeeded, m_worker, static_cast,const Cursor&,View*)>(&CodeCompletionWorker::computeCompletions), Qt::QueuedConnection); connect(m_model, &CodeCompletionModel::doSpecialProcessingInBackground, m_worker, &CodeCompletionWorker::doSpecialProcessing); exec(); } CodeCompletionModel* m_model; CodeCompletionWorker* m_worker; }; bool CodeCompletionModel::forceWaitForModel() { return m_forceWaitForModel; } void CodeCompletionModel::setForceWaitForModel(bool wait) { m_forceWaitForModel = wait; } CodeCompletionModel::CodeCompletionModel( QObject * parent ) : KTextEditor::CodeCompletionModel(parent) , m_forceWaitForModel(false) , m_fullCompletion(true) , m_mutex(new QMutex) , m_thread(0) { qRegisterMetaType(); } void CodeCompletionModel::initialize() { if(!m_thread) { m_thread = new CompletionWorkerThread(this); #ifdef SINGLE_THREADED_COMPLETION m_thread->m_worker = createCompletionWorker(); #endif m_thread->start(); } } CodeCompletionModel::~CodeCompletionModel() { if(m_thread->m_worker) m_thread->m_worker->abortCurrentCompletion(); m_thread->quit(); m_thread->wait(); delete m_thread; delete m_mutex; } void CodeCompletionModel::addNavigationWidget(const CompletionTreeElement* element, QWidget* widget) const { Q_ASSERT(dynamic_cast(widget)); m_navigationWidgets[element] = widget; } bool CodeCompletionModel::fullCompletion() const { return m_fullCompletion; } KDevelop::CodeCompletionWorker* CodeCompletionModel::worker() const { return m_thread->m_worker; } void CodeCompletionModel::clear() { beginResetModel(); m_completionItems.clear(); m_navigationWidgets.clear(); m_completionContext.reset(); endResetModel(); } void CodeCompletionModel::completionInvokedInternal(KTextEditor::View* view, const KTextEditor::Range& range, InvocationType invocationType, const QUrl& url) { Q_ASSERT(m_thread == worker()->thread()); Q_UNUSED(invocationType) DUChainReadLocker lock(DUChain::lock(), 400); if( !lock.locked() ) { qCDebug(LANGUAGE) << "could not lock du-chain in time"; return; } TopDUContext* top = DUChainUtils::standardContextForUrl( url ); if(!top) { return; } setCurrentTopContext(TopDUContextPointer(top)); RangeInRevision rangeInRevision = top->transformToLocalRevision(KTextEditor::Range(range)); if (top) { qCDebug(LANGUAGE) << "completion invoked for context" << (DUContext*)top; if( top->parsingEnvironmentFile() && top->parsingEnvironmentFile()->modificationRevision() != ModificationRevision::revisionForFile(IndexedString(url.toString())) ) { qCDebug(LANGUAGE) << "Found context is not current. Its revision is " /*<< top->parsingEnvironmentFile()->modificationRevision() << " while the document-revision is " << ModificationRevision::revisionForFile(IndexedString(url.toString()))*/; } DUContextPointer thisContext; { qCDebug(LANGUAGE) << "apply specialization:" << range.start(); thisContext = SpecializationStore::self().applySpecialization(top->findContextAt(rangeInRevision.start), top); if ( thisContext ) { qCDebug(LANGUAGE) << "after specialization:" << thisContext->localScopeIdentifier().toString() << thisContext->rangeInCurrentRevision(); } if(!thisContext) thisContext = top; qCDebug(LANGUAGE) << "context is set to" << thisContext.data(); if( !thisContext ) { qCDebug(LANGUAGE) << "================== NO CONTEXT FOUND ======================="; beginResetModel(); m_completionItems.clear(); m_navigationWidgets.clear(); endResetModel(); return; } } lock.unlock(); if(m_forceWaitForModel) emit waitForReset(); emit completionsNeeded(thisContext, range.start(), view); } else { qCDebug(LANGUAGE) << "Completion invoked for unknown context. Document:" << url << ", Known documents:" << DUChain::self()->documents(); } } void CodeCompletionModel::completionInvoked(KTextEditor::View* view, const KTextEditor::Range& range, InvocationType invocationType) { //If this triggers, initialize() has not been called after creation. Q_ASSERT(m_thread); KDevelop::ICompletionSettings::CompletionLevel level = KDevelop::ICore::self()->languageController()->completionSettings()->completionLevel(); if(level == KDevelop::ICompletionSettings::AlwaysFull || (invocationType != AutomaticInvocation && level == KDevelop::ICompletionSettings::MinimalWhenAutomatic)) m_fullCompletion = true; else m_fullCompletion = false; //Only use grouping in full completion mode setHasGroups(m_fullCompletion); Q_UNUSED(invocationType) if (!worker()) { qCWarning(LANGUAGE) << "Completion invoked on a completion model which has no code completion worker assigned!"; } beginResetModel(); m_navigationWidgets.clear(); m_completionItems.clear(); endResetModel(); worker()->abortCurrentCompletion(); worker()->setFullCompletion(m_fullCompletion); QUrl url = view->document()->url(); completionInvokedInternal(view, range, invocationType, url); } void CodeCompletionModel::foundDeclarations(const QList>& items, const QExplicitlySharedDataPointer& completionContext) { m_completionContext = completionContext; if(m_completionItems.isEmpty() && items.isEmpty()) { if(m_forceWaitForModel) { // TODO KF5: Check if this actually works beginResetModel(); endResetModel(); //If we need to reset the model, reset it } return; //We don't need to reset, which is bad for target model } beginResetModel(); m_completionItems = items; endResetModel(); if(m_completionContext) { qCDebug(LANGUAGE) << "got completion-context with " << m_completionContext->ungroupedElements().size() << "ungrouped elements"; } } KTextEditor::CodeCompletionModelControllerInterface::MatchReaction CodeCompletionModel::matchingItem(const QModelIndex& /*matched*/) { return None; } void CodeCompletionModel::setCompletionContext(QExplicitlySharedDataPointer completionContext) { QMutexLocker lock(m_mutex); m_completionContext = completionContext; if(m_completionContext) { qCDebug(LANGUAGE) << "got completion-context with " << m_completionContext->ungroupedElements().size() << "ungrouped elements"; } } QExplicitlySharedDataPointer CodeCompletionModel::completionContext() const { QMutexLocker lock(m_mutex); return m_completionContext; } void CodeCompletionModel::executeCompletionItem(View* view, const KTextEditor::Range& word, const QModelIndex& index) const { //We must not lock the duchain at this place, because the items might rely on that CompletionTreeElement* element = static_cast(index.internalPointer()); if( !element || !element->asItem() ) return; element->asItem()->execute(view, word); } QExplicitlySharedDataPointer< KDevelop::CompletionTreeElement > CodeCompletionModel::itemForIndex(QModelIndex index) const { CompletionTreeElement* element = static_cast(index.internalPointer()); return QExplicitlySharedDataPointer< KDevelop::CompletionTreeElement >(element); } QVariant CodeCompletionModel::data(const QModelIndex& index, int role) const { if ( role == Qt::TextAlignmentRole && index.column() == 0 ) { return Qt::AlignRight; } auto element = static_cast(index.internalPointer()); if( !element ) return QVariant(); if( role == CodeCompletionModel::GroupRole ) { if( element->asNode() ) { return QVariant(element->asNode()->role); }else { qCDebug(LANGUAGE) << "Requested group-role from leaf tree element"; return QVariant(); } }else{ if( element->asNode() ) { if( role == CodeCompletionModel::InheritanceDepth ) { auto customGroupNode = dynamic_cast(element); if(customGroupNode) return QVariant(customGroupNode->inheritanceDepth); } if( role == element->asNode()->role ) { return element->asNode()->roleValue; } else { return QVariant(); } } } if(!element->asItem()) { qCWarning(LANGUAGE) << "Error in completion model"; return QVariant(); } //Navigation widget interaction is done here, the other stuff is done within the tree-elements switch (role) { case CodeCompletionModel::InheritanceDepth: return element->asItem()->inheritanceDepth(); case CodeCompletionModel::ArgumentHintDepth: return element->asItem()->argumentHintDepth(); case CodeCompletionModel::ItemSelected: { DeclarationPointer decl = element->asItem()->declaration(); if(decl) { DUChain::self()->emitDeclarationSelected(decl); } break; } } //In minimal completion mode, hide all columns except the "name" one if(!m_fullCompletion && role == Qt::DisplayRole && index.column() != Name && (element->asItem()->argumentHintDepth() == 0 || index.column() == Prefix)) return QVariant(); //In reduced completion mode, don't show information text with the selected items if(role == ItemSelected && (!m_fullCompletion || !ICore::self()->languageController()->completionSettings()->showMultiLineSelectionInformation())) return QVariant(); return element->asItem()->data(index, role, this); } KDevelop::TopDUContextPointer CodeCompletionModel::currentTopContext() const { return m_currentTopContext; } void CodeCompletionModel::setCurrentTopContext(KDevelop::TopDUContextPointer topContext) { m_currentTopContext = topContext; } QModelIndex CodeCompletionModel::index(int row, int column, const QModelIndex& parent) const { if( parent.isValid() ) { CompletionTreeElement* element = static_cast(parent.internalPointer()); CompletionTreeNode* node = element->asNode(); if( !node ) { qCDebug(LANGUAGE) << "Requested sub-index of leaf node"; return QModelIndex(); } if (row < 0 || row >= node->children.count() || column < 0 || column >= ColumnCount) return QModelIndex(); return createIndex(row, column, node->children[row].data()); } else { if (row < 0 || row >= m_completionItems.count() || column < 0 || column >= ColumnCount) return QModelIndex(); return createIndex(row, column, const_cast(m_completionItems[row].data())); } } QModelIndex CodeCompletionModel::parent ( const QModelIndex & index ) const { if(rowCount() == 0) return QModelIndex(); if( index.isValid() ) { CompletionTreeElement* element = static_cast(index.internalPointer()); if( element->parent() ) return createIndex( element->rowInParent(), element->columnInParent(), element->parent() ); } return QModelIndex(); } int CodeCompletionModel::rowCount ( const QModelIndex & parent ) const { if( parent.isValid() ) { CompletionTreeElement* element = static_cast(parent.internalPointer()); CompletionTreeNode* node = element->asNode(); if( !node ) return 0; return node->children.count(); }else{ return m_completionItems.count(); } } QString CodeCompletionModel::filterString(KTextEditor::View* view, const KTextEditor::Range& range, const KTextEditor::Cursor& position) { m_filterString = KTextEditor::CodeCompletionModelControllerInterface::filterString(view, range, position); return m_filterString; } } #include "moc_codecompletionmodel.cpp" diff --git a/language/codecompletion/codecompletionmodel.h b/language/codecompletion/codecompletionmodel.h index 4b048f436a..d304252e67 100644 --- a/language/codecompletion/codecompletionmodel.h +++ b/language/codecompletion/codecompletionmodel.h @@ -1,151 +1,151 @@ /* * KDevelop Generic Code Completion Support * * Copyright 2006-2008 Hamish Rodda * Copyright 2007-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. */ #ifndef KDEVPLATFORM_CODECOMPLETIONMODEL_H #define KDEVPLATFORM_CODECOMPLETIONMODEL_H #include #include #include #include #include #include "../duchain/duchainpointer.h" #include #include "codecompletioncontext.h" #include "codecompletionitem.h" #include #include #include class QIcon; class QString; class QMutex; namespace KDevelop { class DUContext; class Declaration; class CodeCompletionWorker; class CompletionWorkerThread; class KDEVPLATFORMLANGUAGE_EXPORT CodeCompletionModel : public KTextEditor::CodeCompletionModel , public KTextEditor::CodeCompletionModelControllerInterface { Q_OBJECT Q_INTERFACES(KTextEditor::CodeCompletionModelControllerInterface) public: explicit CodeCompletionModel(QObject* parent); - virtual ~CodeCompletionModel(); + ~CodeCompletionModel() override; ///This MUST be called after the creation of this completion-model. ///If you use use the KDevelop::CodeCompletion helper-class, that one cares about it. virtual void initialize(); ///Entry-point for code-completion. This determines ome settings, clears the model, and then calls completionInvokedInternal for further processing. - virtual void completionInvoked(KTextEditor::View* view, const KTextEditor::Range& range, KTextEditor::CodeCompletionModel::InvocationType invocationType) override; + void completionInvoked(KTextEditor::View* view, const KTextEditor::Range& range, KTextEditor::CodeCompletionModel::InvocationType invocationType) override; - virtual QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const override; + QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const override; - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - virtual int rowCount ( const QModelIndex & parent = QModelIndex() ) const override; - virtual QModelIndex parent ( const QModelIndex & index ) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + int rowCount ( const QModelIndex & parent = QModelIndex() ) const override; + QModelIndex parent ( const QModelIndex & index ) const override; ///Use this to set whether the code-completion widget should wait for this model until it's shown ///This makes sense when the model takes some time but not too much time, to make the UI less flickering and ///annoying. ///The default is false ///@todo Remove this option, make it true by default, and make sure in CodeCompletionWorker that the whole thing cannot break void setForceWaitForModel(bool wait); bool forceWaitForModel(); ///Convenience-storage for use by the inherited completion model void setCompletionContext(QExplicitlySharedDataPointer completionContext); QExplicitlySharedDataPointer completionContext() const; ///Convenience-storage for use by the inherited completion model KDevelop::TopDUContextPointer currentTopContext() const; void setCurrentTopContext(KDevelop::TopDUContextPointer topContext); ///Tracks navigation widget so they can be interactive with through the keyboard later on void addNavigationWidget(const CompletionTreeElement* element, QWidget* widget) const; ///Whether the completion should be fully detailed. If false, it should be simplifed, so no argument-hints, ///no expanding information, no type-information, etc. bool fullCompletion() const; - virtual MatchReaction matchingItem(const QModelIndex& matched) override; + MatchReaction matchingItem(const QModelIndex& matched) override; - virtual QString filterString(KTextEditor::View* view, const KTextEditor::Range& range, const KTextEditor::Cursor& position) override; + QString filterString(KTextEditor::View* view, const KTextEditor::Range& range, const KTextEditor::Cursor& position) override; void clear(); ///Returns the tree-element that belogns to the index, or zero QExplicitlySharedDataPointer itemForIndex(QModelIndex index) const; Q_SIGNALS: ///Connection from this completion-model into the background worker thread. You should emit this from within completionInvokedInternal. void completionsNeeded(KDevelop::DUContextPointer context, const KTextEditor::Cursor& position, KTextEditor::View* view); ///Additional signal that allows directly stepping into the worker-thread, bypassing computeCompletions(..) etc. ///doSpecialProcessing(data) will be executed in the background thread. void doSpecialProcessingInBackground(uint data); protected Q_SLOTS: ///Connection from the background-thread into the model: This is called when the background-thread is ready virtual void foundDeclarations(const QList>& item, const QExplicitlySharedDataPointer& completionContext); protected: ///Eventually override this, determine the context or whatever, and then emit completionsNeeded(..) to continue processing in the background tread. ///The default-implementation does this completely, so if you don't need to do anything special, you can just leave it. virtual void completionInvokedInternal(KTextEditor::View* view, const KTextEditor::Range& range, KTextEditor::CodeCompletionModel::InvocationType invocationType, const QUrl& url); - virtual void executeCompletionItem(KTextEditor::View* view, const KTextEditor::Range& word, const QModelIndex& index) const override; + void executeCompletionItem(KTextEditor::View* view, const KTextEditor::Range& word, const QModelIndex& index) const override; QExplicitlySharedDataPointer m_completionContext; typedef QPair > DeclarationContextPair; mutable QMap > m_navigationWidgets; QList< QExplicitlySharedDataPointer > m_completionItems; /// Should create a completion-worker. The worker must have no parent object, /// because else its thread-affinity can not be changed. virtual CodeCompletionWorker* createCompletionWorker() = 0; friend class CompletionWorkerThread; CodeCompletionWorker* worker() const; private: bool m_forceWaitForModel; bool m_fullCompletion; QMutex* m_mutex; CompletionWorkerThread* m_thread; QString m_filterString; KDevelop::TopDUContextPointer m_currentTopContext; }; } #endif diff --git a/language/codecompletion/codecompletionworker.h b/language/codecompletion/codecompletionworker.h index 9f10c04bef..d0306a4e72 100644 --- a/language/codecompletion/codecompletionworker.h +++ b/language/codecompletion/codecompletionworker.h @@ -1,111 +1,111 @@ /* * KDevelop Generic Code Completion Support * * Copyright 2006-2008 Hamish Rodda * Copyright 2007-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. */ #ifndef KDEVPLATFORM_CODECOMPLETIONWORKER_H #define KDEVPLATFORM_CODECOMPLETIONWORKER_H #include #include #include #include "../duchain/duchainpointer.h" #include "../codecompletion/codecompletioncontext.h" class QMutex; namespace KTextEditor { class Range; class View; class Cursor; } namespace KDevelop { class CompletionTreeElement; class CodeCompletionModel; class KDEVPLATFORMLANGUAGE_EXPORT CodeCompletionWorker : public QObject { Q_OBJECT public: explicit CodeCompletionWorker(CodeCompletionModel* model); - virtual ~CodeCompletionWorker(); + ~CodeCompletionWorker() override; virtual void abortCurrentCompletion(); void setFullCompletion(bool); bool fullCompletion() const; KDevelop::CodeCompletionModel* model() const; ///When this is called, the result is shown in the completion-list. ///Call this from within your code void foundDeclarations(const QList>&, const CodeCompletionContext::Ptr& completionContext); Q_SIGNALS: ///Internal connections into the foreground completion model void foundDeclarationsReal(const QList>&, const QExplicitlySharedDataPointer& completionContext); protected: virtual void computeCompletions(DUContextPointer context, const KTextEditor::Cursor& position, QString followingText, const KTextEditor::Range& contextRange, const QString& contextText); ///This can be overridden to compute an own grouping in the completion-list. ///The default implementation groups items in a way that improves the efficiency of the completion-model, thus the default-implementation should be preferred. virtual QList > computeGroups(QList items, QExplicitlySharedDataPointer completionContext); ///If you don't need to reimplement computeCompletions, you can implement only this. virtual KDevelop::CodeCompletionContext* createCompletionContext(KDevelop::DUContextPointer context, const QString &contextText, const QString &followingText, const CursorInRevision &position) const; ///Override this to change the text-range which is used as context-information for the completion context ///The foreground-lock and a DUChain read lock are held when this is called virtual void updateContextRange(KTextEditor::Range& contextRange, KTextEditor::View* view, DUContextPointer context) const; ///Can be used to retrieve and set the aborting flag(Enabling it is equivalent to caling abortCompletion()) ///Is always reset from within computeCompletions bool& aborting(); ///Emits foundDeclarations() with an empty list. Always call this when you abort the process of computing completions void failed(); public Q_SLOTS: ///Connection from the foreground thread within CodeCompletionModel void computeCompletions(KDevelop::DUContextPointer context, const KTextEditor::Cursor& position, KTextEditor::View* view); ///This can be used to do special processing within the background, completely bypassing the normal computeCompletions(..) etc. system. ///It will be executed within the background when the model emits doSpecialProcessingInBackground virtual void doSpecialProcessing(uint data); private: bool m_hasFoundDeclarations; QMutex* m_mutex; bool m_abort; bool m_fullCompletion; KDevelop::CodeCompletionModel* m_model; }; } #endif // KDEVPLATFORM_CODECOMPLETIONWORKER_H diff --git a/language/codegen/applychangeswidget.h b/language/codegen/applychangeswidget.h index fefa5cef53..3bd94f419a 100644 --- a/language/codegen/applychangeswidget.h +++ b/language/codegen/applychangeswidget.h @@ -1,69 +1,69 @@ /* Copyright 2008 Aleix Pol * Copyright 2009 Ramón Zarazúa * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef KDEVPLATFORM_APPLYCHANGESWIDGET_H #define KDEVPLATFORM_APPLYCHANGESWIDGET_H #include #include namespace KTextEditor { class Document; } namespace KDevelop { class IndexedString; class ApplyChangesWidgetPrivate; class KDEVPLATFORMLANGUAGE_EXPORT ApplyChangesWidget : public QDialog { Q_OBJECT public: explicit ApplyChangesWidget(QWidget* parent=0); - ~ApplyChangesWidget(); + ~ApplyChangesWidget() override; void setInformation(const QString& info); bool hasDocuments() const; KTextEditor::Document* document() const; ///@param modified may be an artifial code representation (@ref KDevelop::InsertArtificialCodeRepresentation) void addDocuments(const IndexedString & original); ///This will save all the modified files into their originals bool applyAllChanges(); ///Update the comparison view fo @p index, in case changes have been done directly to the opened document. ///@param index the index to update, -1 for current index void updateDiffView(int index = -1); public Q_SLOTS: ///Called to signal a change to the currently viewed index void indexChanged(int); private: ApplyChangesWidgetPrivate * d; }; } #endif diff --git a/language/codegen/basicrefactoring.h b/language/codegen/basicrefactoring.h index ab9bfc61ba..9017da5c37 100644 --- a/language/codegen/basicrefactoring.h +++ b/language/codegen/basicrefactoring.h @@ -1,160 +1,160 @@ /* This file is part of KDevelop * * Copyright 2014 Miquel Sabaté * * 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. */ #ifndef BASICREFACTORING_H_ #define BASICREFACTORING_H_ #include #include #include #include #include class CppLanguageSupport; namespace KDevelop { class ContextMenuExtension; class IndexedDeclaration; class Context; class Declaration; class DUContext; /** * A widget that show the uses that it has collected for * the given declaration. */ class KDEVPLATFORMLANGUAGE_EXPORT BasicRefactoringCollector : public UsesWidget::UsesWidgetCollector { public: explicit BasicRefactoringCollector(const IndexedDeclaration &decl); QVector allUsingContexts() const; protected: /// Process the uses for the given TopDUContext. - virtual void processUses(KDevelop::ReferencedTopDUContext topContext) override; + void processUses(KDevelop::ReferencedTopDUContext topContext) override; private: QVector m_allUsingContexts; }; /// The base class for Refactoring classes from Language plugins. class KDEVPLATFORMLANGUAGE_EXPORT BasicRefactoring : public QObject { Q_OBJECT public: explicit BasicRefactoring(QObject *parent = NULL); /// Update the context menu with the "Rename" action. virtual void fillContextMenu(KDevelop::ContextMenuExtension &extension, KDevelop::Context *context); struct NameAndCollector { QString newName; QSharedPointer collector; }; /** * @return Suggestion for new filename based on the current file's name @p current and new identifer @p newName */ virtual QString newFileName(const QUrl& current, const QString& newName); /** * Add the change(s) related to renaming @p file to @p newName to @p changes and return the result. * * @param current The URL for the file you want to rename. * @param newName The new name of the file *without* the file extension. * @param changes The change set to add the rename changes to. */ virtual KDevelop::DocumentChangeSet::ChangeResult addRenameFileChanges(const QUrl& current, const QString& newName, KDevelop::DocumentChangeSet* changes); virtual bool shouldRenameUses(Declaration* declaration) const; /** * @return true if the declaration's file should be renamed if the declaration * was renamed. */ virtual bool shouldRenameFile(KDevelop::Declaration* declaration); public slots: void executeRenameAction(); protected: /** * Apply the changes to the uses that can be found inside the given * context and its children. * NOTE: the DUChain must be locked. */ virtual DocumentChangeSet::ChangeResult applyChanges(const QString &oldName, const QString &newName, DocumentChangeSet &changes, DUContext *context, int usedDeclarationIndex); /** * Apply the changes to the given declarations. * NOTE: the DUChain must be locked. */ virtual DocumentChangeSet::ChangeResult applyChangesToDeclarations(const QString &oldName, const QString &newName, DocumentChangeSet &changes, const QList &declarations); /** * Get the declaration under the current position of the cursor. * * @param allowUse Set to false if the declarations to be returned * cannot come from uses. */ virtual IndexedDeclaration declarationUnderCursor(bool allowUse = true); /** * Start the renaming of a declaration. * This function retrieves the new name for declaration @p decl and if approved renames all instances of it. */ virtual void startInteractiveRename(const KDevelop::IndexedDeclaration &decl); /** * Asks user to input a new name for @p declaration * @return new name or empty string if user changed his mind or new name contains inappropriate symbols (e.g. spaces, points, braces e.t.c) and the collector used for collecting information about @p declaration. * NOTE: unlock the DUChain before calling this. */ virtual BasicRefactoring::NameAndCollector newNameForDeclaration(const KDevelop::DeclarationPointer& declaration); /** * Renames all declarations collected by @p collector from @p oldName to @p newName * @param apply - if changes should be applied immediately * @return all changes if @p apply is false and empty set otherwise. */ DocumentChangeSet renameCollectedDeclarations(KDevelop::BasicRefactoringCollector* collector, const QString& replacementName, const QString& originalName, bool apply = true); /** * @returns true if we can show the interactive rename widget for the * given declaration. The default implementation just returns true. */ virtual bool acceptForContextMenu(const Declaration *decl); }; } // End of namespace KDevelop #endif /* BASICREFACTORING_H_ */ diff --git a/language/codegen/coderepresentation.cpp b/language/codegen/coderepresentation.cpp index 3e194a1e80..9652717914 100644 --- a/language/codegen/coderepresentation.cpp +++ b/language/codegen/coderepresentation.cpp @@ -1,377 +1,377 @@ /* 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 "coderepresentation.h" #include #include #include #include #include #include #include #include namespace KDevelop { static bool onDiskChangesForbidden = false; QString CodeRepresentation::rangeText(const KTextEditor::Range& range) const { Q_ASSERT(range.end().line() < lines()); //Easier for single line ranges which should happen most of the time if(range.onSingleLine()) return QString( line( range.start().line() ).mid( range.start().column(), range.columnWidth() ) ); //Add up al the requested lines QString rangedText = line(range.start().line()).mid(range.start().column()); for(int i = range.start().line() + 1; i <= range.end().line(); ++i) rangedText += '\n' + ((i == range.end().line()) ? line(i).left(range.end().column()) : line(i)); return rangedText; } static void grepLine(const QString& identifier, const QString& lineText, int lineNumber, QVector& ret, bool surroundedByBoundary) { if (identifier.isEmpty()) return; int pos = 0; while(true) { pos = lineText.indexOf(identifier, pos); if(pos == -1) break; int start = pos; pos += identifier.length(); int end = pos; if(!surroundedByBoundary || ( (end == lineText.length() || !lineText[end].isLetterOrNumber() || lineText[end] != '_') && (start-1 < 0 || !lineText[start-1].isLetterOrNumber() || lineText[start-1] != '_')) ) { ret << KTextEditor::Range(lineNumber, start, lineNumber, end); } } } class EditorCodeRepresentation : public DynamicCodeRepresentation { public: EditorCodeRepresentation(KTextEditor::Document* document) : m_document(document) { m_url = IndexedString(m_document->url()); } - virtual QVector< KTextEditor::Range > grep ( const QString& identifier, bool surroundedByBoundary ) const override { + QVector< KTextEditor::Range > grep ( const QString& identifier, bool surroundedByBoundary ) const override { QVector< KTextEditor::Range > ret; if (identifier.isEmpty()) return ret; for(int line = 0; line < m_document->lines(); ++line) grepLine(identifier, m_document->line(line), line, ret, surroundedByBoundary); return ret; } - virtual KDevEditingTransaction::Ptr makeEditTransaction() override { + KDevEditingTransaction::Ptr makeEditTransaction() override { return KDevEditingTransaction::Ptr(new KDevEditingTransaction(m_document)); } QString line(int line) const override { if(line < 0 || line >= m_document->lines()) return QString(); return m_document->line(line); } - virtual int lines() const override { + int lines() const override { return m_document->lines(); } QString text() const override { return m_document->text(); } bool setText(const QString& text) override { bool ret; { KDevEditingTransaction t(m_document); ret = m_document->setText(text); } ModificationRevision::clearModificationCache(m_url); return ret; } bool fileExists() override{ return QFile(m_document->url().path()).exists(); } bool replace(const KTextEditor::Range& range, const QString& oldText, const QString& newText, bool ignoreOldText) override { QString old = m_document->text(range); if(oldText != old && !ignoreOldText) { return false; } bool ret; { KDevEditingTransaction t(m_document); ret = m_document->replaceText(range, newText); } ModificationRevision::clearModificationCache(m_url); return ret; } - virtual QString rangeText(const KTextEditor::Range& range) const override { + QString rangeText(const KTextEditor::Range& range) const override { return m_document->text(range); } private: KTextEditor::Document* m_document; IndexedString m_url; }; class FileCodeRepresentation : public CodeRepresentation { public: FileCodeRepresentation(const IndexedString& document) : m_document(document) { QString localFile(document.toUrl().toLocalFile()); QFile file( localFile ); if ( file.open(QIODevice::ReadOnly) ) { data = QString::fromLocal8Bit(file.readAll()); lineData = data.split('\n'); } m_exists = file.exists(); } QString line(int line) const override { if(line < 0 || line >= lineData.size()) return QString(); return lineData.at(line); } - virtual QVector< KTextEditor::Range > grep ( const QString& identifier, bool surroundedByBoundary ) const override { + QVector< KTextEditor::Range > grep ( const QString& identifier, bool surroundedByBoundary ) const override { QVector< KTextEditor::Range > ret; if (identifier.isEmpty()) return ret; for(int line = 0; line < lineData.count(); ++line) grepLine(identifier, lineData.at(line), line, ret, surroundedByBoundary); return ret; } - virtual int lines() const override { + int lines() const override { return lineData.count(); } QString text() const override { return data; } bool setText(const QString& text) override { Q_ASSERT(!onDiskChangesForbidden); QString localFile(m_document.toUrl().toLocalFile()); QFile file( localFile ); if ( file.open(QIODevice::WriteOnly) ) { QByteArray data = text.toLocal8Bit(); if(file.write(data) == data.size()) { ModificationRevision::clearModificationCache(m_document); return true; } } return false; } bool fileExists() override{ return m_exists; } private: //We use QByteArray, because the column-numbers are measured in utf-8 IndexedString m_document; bool m_exists; QStringList lineData; QString data; }; class ArtificialStringData : public QSharedData { public: ArtificialStringData(const QString& data) { setData(data); } void setData(const QString& data) { m_data = data; m_lineData = m_data.split('\n'); } QString data() const { return m_data; } const QStringList& lines() const { return m_lineData; } private: QString m_data; QStringList m_lineData; }; class StringCodeRepresentation : public CodeRepresentation { public: StringCodeRepresentation(QExplicitlySharedDataPointer _data) : data(_data) { Q_ASSERT(data); } QString line(int line) const override { if(line < 0 || line >= data->lines().size()) return QString(); return data->lines().at(line); } - virtual int lines() const override { + int lines() const override { return data->lines().count(); } QString text() const override { return data->data(); } bool setText(const QString& text) override { data->setData(text); return true; } bool fileExists() override{ return false; } - virtual QVector< KTextEditor::Range > grep ( const QString& identifier, bool surroundedByBoundary ) const override { + QVector< KTextEditor::Range > grep ( const QString& identifier, bool surroundedByBoundary ) const override { QVector< KTextEditor::Range > ret; if (identifier.isEmpty()) return ret; for(int line = 0; line < data->lines().count(); ++line) grepLine(identifier, data->lines().at(line), line, ret, surroundedByBoundary); return ret; } private: QExplicitlySharedDataPointer data; }; static QHash > artificialStrings; //Return the representation for the given URL if it exists, or an empty pointer otherwise static QExplicitlySharedDataPointer representationForPath(const IndexedString& path) { if(artificialStrings.contains(path)) return artificialStrings[path]; else { IndexedString constructedPath(CodeRepresentation::artificialPath(path.str())); if(artificialStrings.contains(constructedPath)) return artificialStrings[constructedPath]; else return QExplicitlySharedDataPointer(); } } bool artificialCodeRepresentationExists(const IndexedString& path) { return representationForPath(path); } CodeRepresentation::Ptr createCodeRepresentation(const IndexedString& path) { if(artificialCodeRepresentationExists(path)) return CodeRepresentation::Ptr(new StringCodeRepresentation(representationForPath(path))); IDocument* document = ICore::self()->documentController()->documentForUrl(path.toUrl()); if(document && document->textDocument()) return CodeRepresentation::Ptr(new EditorCodeRepresentation(document->textDocument())); else return CodeRepresentation::Ptr(new FileCodeRepresentation(path)); } void CodeRepresentation::setDiskChangesForbidden(bool changesForbidden) { onDiskChangesForbidden = changesForbidden; } QString CodeRepresentation::artificialPath(const QString& name) { QUrl url = QUrl::fromLocalFile(name); return QString::fromLatin1("/kdev-artificial/") + url.adjusted(QUrl::NormalizePathSegments).path(); } InsertArtificialCodeRepresentation::InsertArtificialCodeRepresentation(const IndexedString& file, const QString& text) : m_file(file) { // make it simpler to use this by converting relative strings into artificial paths if(QUrl(m_file.str()).isRelative()) { m_file = IndexedString(CodeRepresentation::artificialPath(file.str())); int idx = 0; while(artificialStrings.contains(m_file)) { ++idx; m_file = IndexedString(CodeRepresentation::artificialPath(QStringLiteral("%1_%2").arg(idx).arg(file.str()))); } } Q_ASSERT(!artificialStrings.contains(m_file)); artificialStrings.insert(m_file, QExplicitlySharedDataPointer(new ArtificialStringData(text))); } IndexedString InsertArtificialCodeRepresentation::file() { return m_file; } InsertArtificialCodeRepresentation::~InsertArtificialCodeRepresentation() { Q_ASSERT(artificialStrings.contains(m_file)); artificialStrings.remove(m_file); } void InsertArtificialCodeRepresentation::setText(const QString& text) { Q_ASSERT(artificialStrings.contains(m_file)); artificialStrings[m_file]->setData(text); } QString InsertArtificialCodeRepresentation::text() { Q_ASSERT(artificialStrings.contains(m_file)); return artificialStrings[m_file]->data(); } } // kate: indent-width 4; diff --git a/language/codegen/templaterenderer.cpp b/language/codegen/templaterenderer.cpp index 3005924c7a..8a6e7ac615 100644 --- a/language/codegen/templaterenderer.cpp +++ b/language/codegen/templaterenderer.cpp @@ -1,310 +1,310 @@ /* * This file is part of KDevelop * Copyright 2012 Miha Čančula * * 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 "templaterenderer.h" #include "documentchangeset.h" #include "sourcefiletemplate.h" #include "templateengine.h" #include "templateengine_p.h" #include "archivetemplateloader.h" #include "util/debug.h" #include #include #include #include #include #include #include using namespace Grantlee; class NoEscapeStream : public OutputStream { public: NoEscapeStream(); explicit NoEscapeStream (QTextStream* stream); - virtual QString escape (const QString& input) const override; - virtual QSharedPointer< OutputStream > clone (QTextStream* stream) const override; + QString escape (const QString& input) const override; + QSharedPointer< OutputStream > clone (QTextStream* stream) const override; }; NoEscapeStream::NoEscapeStream() : OutputStream() { } NoEscapeStream::NoEscapeStream(QTextStream* stream) : OutputStream (stream) { } QString NoEscapeStream::escape(const QString& input) const { return input; } QSharedPointer NoEscapeStream::clone(QTextStream* stream) const { QSharedPointer clonedStream = QSharedPointer( new NoEscapeStream( stream ) ); return clonedStream; } using namespace KDevelop; namespace KDevelop { class TemplateRendererPrivate { public: Engine* engine; Grantlee::Context context; TemplateRenderer::EmptyLinesPolicy emptyLinesPolicy; QString errorString; }; } TemplateRenderer::TemplateRenderer() : d(new TemplateRendererPrivate) { d->engine = &TemplateEngine::self()->d->engine; d->emptyLinesPolicy = KeepEmptyLines; } TemplateRenderer::~TemplateRenderer() { delete d; } void TemplateRenderer::addVariables(const QVariantHash& variables) { QVariantHash::const_iterator it = variables.constBegin(); QVariantHash::const_iterator end = variables.constEnd(); for (; it != end; ++it) { d->context.insert(it.key(), it.value()); } } void TemplateRenderer::addVariable(const QString& name, const QVariant& value) { d->context.insert(name, value); } QVariantHash TemplateRenderer::variables() const { return d->context.stackHash(0); } QString TemplateRenderer::render(const QString& content, const QString& name) const { Template t = d->engine->newTemplate(content, name); QString output; QTextStream textStream(&output); NoEscapeStream stream(&textStream); t->render(&stream, &d->context); if (t->error() != Grantlee::NoError) { d->errorString = t->errorString(); } else { d->errorString.clear(); } if (d->emptyLinesPolicy == TrimEmptyLines && output.contains('\n')) { QStringList lines = output.split('\n', QString::KeepEmptyParts); QMutableStringListIterator it(lines); // Remove empty lines from the start of the document while (it.hasNext()) { if (it.next().trimmed().isEmpty()) { it.remove(); } else { break; } } // Remove single empty lines it.toFront(); bool prePreviousEmpty = false; bool previousEmpty = false; while (it.hasNext()) { bool currentEmpty = it.peekNext().trimmed().isEmpty(); if (!prePreviousEmpty && previousEmpty && !currentEmpty) { it.remove(); } prePreviousEmpty = previousEmpty; previousEmpty = currentEmpty; it.next(); } // Compress multiple empty lines it.toFront(); previousEmpty = false; while (it.hasNext()) { bool currentEmpty = it.next().trimmed().isEmpty(); if (currentEmpty && previousEmpty) { it.remove(); } previousEmpty = currentEmpty; } // Remove empty lines from the end it.toBack(); while (it.hasPrevious()) { if (it.previous().trimmed().isEmpty()) { it.remove(); } else { break; } } // Add a newline to the end of file it.toBack(); it.insert(QString()); output = lines.join("\n"); } else if (d->emptyLinesPolicy == RemoveEmptyLines) { QStringList lines = output.split('\n', QString::SkipEmptyParts); QMutableStringListIterator it(lines); while (it.hasNext()) { if (it.next().trimmed().isEmpty()) { it.remove(); } } it.toBack(); if (lines.size() > 1) { it.insert(QString()); } output = lines.join("\n"); } return output; } QString TemplateRenderer::renderFile(const QUrl& url, const QString& name) const { QFile file(url.toLocalFile()); file.open(QIODevice::ReadOnly); QString content(file.readAll()); qCDebug(LANGUAGE) << content; return render(content, name); } QStringList TemplateRenderer::render(const QStringList& contents) const { qCDebug(LANGUAGE) << d->context.stackHash(0); QStringList ret; foreach (const QString& content, contents) { ret << render(content); } return ret; } void TemplateRenderer::setEmptyLinesPolicy(TemplateRenderer::EmptyLinesPolicy policy) { d->emptyLinesPolicy = policy; } TemplateRenderer::EmptyLinesPolicy TemplateRenderer::emptyLinesPolicy() const { return d->emptyLinesPolicy; } DocumentChangeSet TemplateRenderer::renderFileTemplate(const SourceFileTemplate& fileTemplate, const QUrl& baseUrl, const QHash& fileUrls) { DocumentChangeSet changes; const QDir baseDir(baseUrl.path()); QRegExp nonAlphaNumeric("\\W"); for (QHash::const_iterator it = fileUrls.constBegin(); it != fileUrls.constEnd(); ++it) { QString cleanName = it.key().toLower(); cleanName.replace(nonAlphaNumeric, "_"); const QString path = it.value().toLocalFile(); addVariable("output_file_" + cleanName, baseDir.relativeFilePath(path)); addVariable("output_file_" + cleanName + "_absolute", path); } const KArchiveDirectory* directory = fileTemplate.directory(); ArchiveTemplateLocation location(directory); foreach (const SourceFileTemplate::OutputFile& outputFile, fileTemplate.outputFiles()) { const KArchiveEntry* entry = directory->entry(outputFile.fileName); if (!entry) { qCWarning(LANGUAGE) << "Entry" << outputFile.fileName << "is mentioned in group" << outputFile.identifier << "but is not present in the archive"; continue; } const KArchiveFile* file = dynamic_cast(entry); if (!file) { qCWarning(LANGUAGE) << "Entry" << entry->name() << "is not a file"; continue; } QUrl url = fileUrls[outputFile.identifier]; IndexedString document(url); KTextEditor::Range range(KTextEditor::Cursor(0, 0), 0); DocumentChange change(document, range, QString(), render(file->data(), outputFile.identifier)); changes.addChange(change); qCDebug(LANGUAGE) << "Added change for file" << document.str(); } return changes; } QString TemplateRenderer::errorString() const { return d->errorString; } diff --git a/language/codegen/templatesmodel.h b/language/codegen/templatesmodel.h index f740b6bf28..0c30036bec 100644 --- a/language/codegen/templatesmodel.h +++ b/language/codegen/templatesmodel.h @@ -1,122 +1,122 @@ /* This file is part of KDevelop Copyright 2007 Alexander Dymo Copyright 2012 Miha Čančula 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 KDEVPLATFORM_TEMPLATESMODEL_H #define KDEVPLATFORM_TEMPLATESMODEL_H #include #include namespace KDevelop { class TemplatesModelPrivate; /** * @brief A convenience class for loading templates using .kdevtemplate files * * It loads template archives, extracts and stores their description files, and * displays them as a three-level tree structure. * * The locations for loading and storing files are determined by the typePrefix. * We use QStandardPaths with the GenericData type and create a filter string as such: * \li templates: typePrefix "/templates/" * \li descriptions: typePrefix "/template_descriptions/" * \li previews: typePrefix "/template_previews/" * * @sa ITemplateProvider::templatesModel() **/ class KDEVPLATFORMLANGUAGE_EXPORT TemplatesModel : public QStandardItemModel { Q_OBJECT public: /** * Extra roles for template-specific properties * @sa Qt::ItemDataRole **/ enum TemplateRole { DescriptionFileRole = Qt::UserRole + 1, ///< Template description file name IconNameRole = Qt::UserRole + 2, ///< Template icon name CommentRole = Qt::UserRole + 3, ///< Template comment ArchiveFileRole = Qt::UserRole + 4 ///< Template archive file name }; /** * Creates a new templates model * * @param typePrefix the type prefix used to determine resource locations. * @param parent parent object, defaults to 0. **/ explicit TemplatesModel(const QString& typePrefix, QObject* parent = 0); /** * Destructor * **/ - virtual ~TemplatesModel(); + ~TemplatesModel() override; /** * Reloads all found templates **/ virtual void refresh(); /** * Loads template @p fileName and save it to the template storage directory. * * If the file is an archive, the whole archive will be copied. * If the file has a .desktop or .kdevtemplate suffix, the contents * of its containing directory will be archived and saved. **/ QString loadTemplateFile(const QString& fileName); /** * Finds the model index of the template file @p fileName. * * For convenience, this function returns the found template index, as well as all of its ancestors. * The indexes are ordered from the top-level ancestor to the actual index of the template. * This is useful for managing selection when multiple views display different level of the model. * * @param fileName the template file name **/ QModelIndexList templateIndexes(const QString& fileName) const; /** * Returns the type prefix used to find a template resource. **/ QString typePrefix() const; /** * The model will include @p path during the search for template archives * * @param path Path to a directory that contains normal user data. The template model will search for a kdevappwizard/templates (or your model name prefix) directory * inside @p path and will use them. Please note that the path has to end with a '/'. */ void addDataPath(const QString &path); private: TemplatesModelPrivate* const d; }; } #endif // KDEVPLATFORM_TEMPLATESMODEL_H diff --git a/language/duchain/duchain.cpp b/language/duchain/duchain.cpp index 6dd22005e2..17db813444 100644 --- a/language/duchain/duchain.cpp +++ b/language/duchain/duchain.cpp @@ -1,1702 +1,1702 @@ /* This is part of KDevelop Copyright 2006-2008 Hamish Rodda Copyright 2007-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 "duchain.h" #include "duchainlock.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../interfaces/ilanguagesupport.h" #include "../interfaces/icodehighlighting.h" #include "../backgroundparser/backgroundparser.h" #include "util/debug.h" #include "topducontext.h" #include "topducontextdata.h" #include "topducontextdynamicdata.h" #include "parsingenvironment.h" #include "declaration.h" #include "definitions.h" #include "duchainutils.h" #include "use.h" #include "uses.h" #include "abstractfunctiondeclaration.h" #include "duchainregister.h" #include "persistentsymboltable.h" #include "serialization/itemrepository.h" #include "waitforupdate.h" #include "importers.h" #ifdef HAVE_MALLOC_TRIM #include "malloc.h" #endif namespace { //Additional "soft" cleanup steps that are done before the actual cleanup. //During "soft" cleanup, the consistency is not guaranteed. The repository is //marked to be updating during soft cleanup, so if kdevelop crashes, it will be cleared. //The big advantage of the soft cleanup steps is, that the duchain is always only locked for //short times, which leads to no lockup in the UI. const int SOFT_CLEANUP_STEPS = 1; const uint cleanupEverySeconds = 200; ///Approximate maximum count of top-contexts that are checked during final cleanup const uint maxFinalCleanupCheckContexts = 2000; const uint minimumFinalCleanupCheckContextsPercentage = 10; //Check at least n% of all top-contexts during cleanup //Set to true as soon as the duchain is deleted } namespace KDevelop { bool DUChain::m_deleted = false; ///Must be locked through KDevelop::SpinLock before using chainsByIndex ///This lock should be locked only for very short times QMutex DUChain::chainsByIndexLock; std::vector DUChain::chainsByIndex; //This thing is not actually used, but it's needed for compiling DEFINE_LIST_MEMBER_HASH(EnvironmentInformationListItem, items, uint) //An entry for the item-repository that holds some meta-data. Behind this entry, the actual ParsingEnvironmentFileData is stored. class EnvironmentInformationItem { public: EnvironmentInformationItem(uint topContext, uint size) : m_topContext(topContext), m_size(size) { } ~EnvironmentInformationItem() { } unsigned int hash() const { return m_topContext; } unsigned int itemSize() const { return sizeof(*this) + m_size; } uint m_topContext; uint m_size;//Size of the data behind, that holds the actual item }; struct ItemRepositoryIndexHash { uint operator()(unsigned int __x) const { return 173*(__x>>2) + 11 * (__x >> 16); } }; class EnvironmentInformationRequest { public: ///This constructor should only be used for lookup EnvironmentInformationRequest(uint topContextIndex) : m_file(0), m_index(topContextIndex) { } EnvironmentInformationRequest(const ParsingEnvironmentFile* file) : m_file(file), m_index(file->indexedTopContext().index()) { } enum { AverageSize = 32 //This should be the approximate average size of an Item }; unsigned int hash() const { return m_index; } uint itemSize() const { return sizeof(EnvironmentInformationItem) + DUChainItemSystem::self().dynamicSize(*m_file->d_func()); } void createItem(EnvironmentInformationItem* item) const { new (item) EnvironmentInformationItem(m_index, DUChainItemSystem::self().dynamicSize(*m_file->d_func())); Q_ASSERT(m_file->d_func()->m_dynamic); DUChainBaseData* data = reinterpret_cast(reinterpret_cast(item) + sizeof(EnvironmentInformationItem)); DUChainItemSystem::self().copy(*m_file->d_func(), *data, true); Q_ASSERT(data->m_range == m_file->d_func()->m_range); Q_ASSERT(data->classId == m_file->d_func()->classId); Q_ASSERT(data->m_dynamic == false); } static void destroy(EnvironmentInformationItem* item, KDevelop::AbstractItemRepository&) { item->~EnvironmentInformationItem(); //We don't need to call the destructor, because that's done in DUChainBase::makeDynamic() //We just need to make sure that every environment-file is dynamic when it's deleted // DUChainItemSystem::self().callDestructor((DUChainBaseData*)(((char*)item) + sizeof(EnvironmentInformationItem))); } static bool persistent(const EnvironmentInformationItem* ) { //Cleanup done separately return true; } bool equals(const EnvironmentInformationItem* item) const { return m_index == item->m_topContext; } const ParsingEnvironmentFile* m_file; uint m_index; }; ///A list of environment-information/top-contexts mapped to a file-name class EnvironmentInformationListItem { public: EnvironmentInformationListItem() { initializeAppendedLists(true); } EnvironmentInformationListItem(const EnvironmentInformationListItem& rhs, bool dynamic = true) { initializeAppendedLists(dynamic); m_file = rhs.m_file; copyListsFrom(rhs); } ~EnvironmentInformationListItem() { freeAppendedLists(); } unsigned int hash() const { //We only compare the declaration. This allows us implementing a map, although the item-repository //originally represents a set. return m_file.hash(); } unsigned short int itemSize() const { return dynamicSize(); } IndexedString m_file; uint classSize() const { return sizeof(*this); } START_APPENDED_LISTS(EnvironmentInformationListItem); ///Contains the index of each contained environment-item APPENDED_LIST_FIRST(EnvironmentInformationListItem, uint, items); END_APPENDED_LISTS(EnvironmentInformationListItem, items); }; class EnvironmentInformationListRequest { public: ///This constructor should only be used for lookup EnvironmentInformationListRequest(const IndexedString& file) : m_file(file), m_item(0) { } ///This is used to actually construct the information in the repository EnvironmentInformationListRequest(const IndexedString& file, const EnvironmentInformationListItem& item) : m_file(file), m_item(&item) { } enum { AverageSize = 160 //This should be the approximate average size of an Item }; unsigned int hash() const { return m_file.hash(); } uint itemSize() const { return m_item->itemSize(); } void createItem(EnvironmentInformationListItem* item) const { Q_ASSERT(m_item->m_file == m_file); new (item) EnvironmentInformationListItem(*m_item, false); } static void destroy(EnvironmentInformationListItem* item, KDevelop::AbstractItemRepository&) { item->~EnvironmentInformationListItem(); } static bool persistent(const EnvironmentInformationListItem*) { //Cleanup is done separately return true; } bool equals(const EnvironmentInformationListItem* item) const { return m_file == item->m_file; } IndexedString m_file; const EnvironmentInformationListItem* m_item; }; class DUChainPrivate; static DUChainPrivate* duChainPrivateSelf = 0; class DUChainPrivate { class CleanupThread : public QThread { public: CleanupThread(DUChainPrivate* data) : m_stopRunning(false), m_data(data) { } void stopThread() { { QMutexLocker lock(&m_waitMutex); m_stopRunning = true; m_wait.wakeAll(); //Wakes the thread up, so it notices it should exit } wait(); } private: void run() override { while(1) { for(uint s = 0; s < cleanupEverySeconds; ++s) { if(m_stopRunning) break; QMutexLocker lock(&m_waitMutex); m_wait.wait(&m_waitMutex, 1000); } if(m_stopRunning) break; //Just to make sure the cache is cleared periodically ModificationRevisionSet::clearCache(); m_data->doMoreCleanup(SOFT_CLEANUP_STEPS); if(m_stopRunning) break; } } bool m_stopRunning; QWaitCondition m_wait; QMutex m_waitMutex; DUChainPrivate* m_data; }; public: DUChainPrivate() : m_chainsMutex(QMutex::Recursive), m_cleanupMutex(QMutex::Recursive), instance(0), m_cleanupDisabled(false), m_destroyed(false), m_environmentListInfo("Environment Lists"), m_environmentInfo("Environment Information") { #if defined(TEST_NO_CLEANUP) m_cleanupDisabled = true; #endif duChainPrivateSelf = this; qRegisterMetaType("KDevelop::DUChainBasePointer"); qRegisterMetaType("KDevelop::DUContextPointer"); qRegisterMetaType("KDevelop::TopDUContextPointer"); qRegisterMetaType("KDevelop::DeclarationPointer"); qRegisterMetaType("KDevelop::FunctionDeclarationPointer"); qRegisterMetaType("KDevelop::IndexedString"); qRegisterMetaType("KDevelop::IndexedTopDUContext"); qRegisterMetaType("KDevelop::ReferencedTopDUContext"); instance = new DUChain(); m_cleanup = new CleanupThread(this); m_cleanup->start(); DUChain::m_deleted = false; ///Loading of some static data: { ///@todo Solve this more duchain-like QFile f(globalItemRepositoryRegistry().path() + "/parsing_environment_data"); bool opened = f.open(QIODevice::ReadOnly); ///FIXME: ugh, so ugly ParsingEnvironmentFile::m_staticData = reinterpret_cast( new char[sizeof(StaticParsingEnvironmentData)]); if(opened) { qCDebug(LANGUAGE) << "reading parsing-environment static data"; //Read f.read((char*)ParsingEnvironmentFile::m_staticData, sizeof(StaticParsingEnvironmentData)); }else{ qCDebug(LANGUAGE) << "creating new parsing-environment static data"; //Initialize new (ParsingEnvironmentFile::m_staticData) StaticParsingEnvironmentData(); } } ///Read in the list of available top-context indices { QFile f(globalItemRepositoryRegistry().path() + "/available_top_context_indices"); bool opened = f.open(QIODevice::ReadOnly); if(opened) { Q_ASSERT( (f.size() % sizeof(uint)) == 0); - m_availableTopContextIndices.resize(f.size()/sizeof(uint)); + m_availableTopContextIndices.resize(f.size()/(int)sizeof(uint)); f.read((char*)m_availableTopContextIndices.data(), f.size()); } } } ~DUChainPrivate() { qCDebug(LANGUAGE) << "Destroying"; DUChain::m_deleted = true; m_cleanup->stopThread(); delete m_cleanup; delete instance; } void clear() { if(!m_cleanupDisabled) doMoreCleanup(); DUChainWriteLocker writeLock(DUChain::lock()); QMutexLocker l(&m_chainsMutex); foreach(TopDUContext* top, m_chainsByUrl.values()) removeDocumentChainFromMemory(top); m_indexEnvironmentInformations.clear(); m_fileEnvironmentInformations.clear(); Q_ASSERT(m_fileEnvironmentInformations.isEmpty()); Q_ASSERT(m_chainsByUrl.isEmpty()); } ///DUChain must be write-locked ///Also removes from the environment-manager if the top-context is not on disk void removeDocumentChainFromMemory(TopDUContext* context) { QMutexLocker l(&m_chainsMutex); { QMutexLocker l(&m_referenceCountsMutex); if(m_referenceCounts.contains(context)) { //This happens during shutdown, since everything is unloaded qCDebug(LANGUAGE) << "removed a top-context that was reference-counted:" << context->url().str() << context->ownIndex(); m_referenceCounts.remove(context); } } uint index = context->ownIndex(); // qCDebug(LANGUAGE) << "duchain: removing document" << context->url().str(); Q_ASSERT(hasChainForIndex(index)); Q_ASSERT(m_chainsByUrl.contains(context->url(), context)); m_chainsByUrl.remove(context->url(), context); if(!context->isOnDisk()) instance->removeFromEnvironmentManager(context); l.unlock(); //DUChain is write-locked, so we can do whatever we want on the top-context, including deleting it context->deleteSelf(); l.relock(); Q_ASSERT(hasChainForIndex(index)); QMutexLocker lock(&DUChain::chainsByIndexLock); DUChain::chainsByIndex[index] = 0; } ///Must be locked before accessing content of this class. ///Should be released during expensive disk-operations and such. QMutex m_chainsMutex; QMutex m_cleanupMutex; CleanupThread* m_cleanup; DUChain* instance; DUChainLock lock; QMultiMap m_chainsByUrl; //Must be locked before accessing m_referenceCounts QMutex m_referenceCountsMutex; QHash m_referenceCounts; Definitions m_definitions; Uses m_uses; QSet m_loading; bool m_cleanupDisabled; //List of available top-context indices, protected by m_chainsMutex QVector m_availableTopContextIndices; ///Used to keep alive the top-context that belong to documents loaded in the editor QSet m_openDocumentContexts; bool m_destroyed; ///The item must not be stored yet ///m_chainsMutex should not be locked, since this can trigger I/O void addEnvironmentInformation(ParsingEnvironmentFilePointer info) { Q_ASSERT(!findInformation(info->indexedTopContext().index())); Q_ASSERT(m_environmentInfo.findIndex(info->indexedTopContext().index()) == 0); QMutexLocker lock(&m_chainsMutex); m_fileEnvironmentInformations.insert(info->url(), info); m_indexEnvironmentInformations.insert(info->indexedTopContext().index(), info); Q_ASSERT(info->d_func()->classId); } ///The item must be managed currently ///m_chainsMutex does not need to be locked void removeEnvironmentInformation(ParsingEnvironmentFilePointer info) { info->makeDynamic(); //By doing this, we make sure the data is actually being destroyed in the destructor bool removed = false; bool removed2 = false; { QMutexLocker lock(&m_chainsMutex); removed = m_fileEnvironmentInformations.remove(info->url(), info); removed2 = m_indexEnvironmentInformations.remove(info->indexedTopContext().index()); } { //Remove it from the environment information lists if it was there QMutexLocker lock(m_environmentListInfo.mutex()); uint index = m_environmentListInfo.findIndex(info->url()); if(index) { EnvironmentInformationListItem item(*m_environmentListInfo.itemFromIndex(index)); if(item.itemsList().removeOne(info->indexedTopContext().index())) { m_environmentListInfo.deleteItem(index); if(!item.itemsList().isEmpty()) m_environmentListInfo.index(EnvironmentInformationListRequest(info->url(), item)); } } } QMutexLocker lock(m_environmentInfo.mutex()); uint index = m_environmentInfo.findIndex(info->indexedTopContext().index()); if(index) { m_environmentInfo.deleteItem(index); } Q_UNUSED(removed); Q_UNUSED(removed2); Q_ASSERT(index || (removed && removed2)); Q_ASSERT(!findInformation(info->indexedTopContext().index())); } ///m_chainsMutex should _not_ be locked, because this may trigger I/O QList getEnvironmentInformation(IndexedString url) { QList ret; uint listIndex = m_environmentListInfo.findIndex(url); if(listIndex) { KDevVarLengthArray topContextIndices; { //First store all the possible intices into the KDevVarLengthArray, so we can unlock the mutex before processing them. QMutexLocker lock(m_environmentListInfo.mutex()); //Lock the mutex to make sure the item isn't changed while it's being iterated const EnvironmentInformationListItem* item = m_environmentListInfo.itemFromIndex(listIndex); FOREACH_FUNCTION(uint topContextIndex, item->items) topContextIndices << topContextIndex; } //Process the indices in a separate step after copying them from the array, so we don't need m_environmentListInfo.mutex locked, //and can call loadInformation(..) safely, which else might lead to a deadlock. for (uint topContextIndex : topContextIndices) { QExplicitlySharedDataPointer< ParsingEnvironmentFile > p = ParsingEnvironmentFilePointer(loadInformation(topContextIndex)); if(p) { ret << p; }else{ qCDebug(LANGUAGE) << "Failed to load enviromment-information for" << TopDUContextDynamicData::loadUrl(topContextIndex).str(); } } } QMutexLocker l(&m_chainsMutex); //Add those information that have not been added to the stored lists yet foreach(ParsingEnvironmentFilePointer file, m_fileEnvironmentInformations.values(url)) if(!ret.contains(file)) ret << file; return ret; } ///Must be called _without_ the chainsByIndex spin-lock locked static inline bool hasChainForIndex(uint index) { QMutexLocker lock(&DUChain::chainsByIndexLock); return (DUChain::chainsByIndex.size() > index) && DUChain::chainsByIndex[index]; } ///Must be called _without_ the chainsByIndex spin-lock locked. Returns the top-context if it is loaded. static inline TopDUContext* readChainForIndex(uint index) { QMutexLocker lock(&DUChain::chainsByIndexLock); if(DUChain::chainsByIndex.size() > index) return DUChain::chainsByIndex[index]; else return 0; } ///Makes sure that the chain with the given index is loaded ///@warning m_chainsMutex must NOT be locked when this is called void loadChain(uint index, QSet& loaded) { QMutexLocker l(&m_chainsMutex); if(!hasChainForIndex(index)) { if(m_loading.contains(index)) { //It's probably being loaded by another thread. So wait until the load is ready while(m_loading.contains(index)) { l.unlock(); qCDebug(LANGUAGE) << "waiting for another thread to load index" << index; QThread::usleep(50000); l.relock(); } loaded.insert(index); return; } m_loading.insert(index); loaded.insert(index); l.unlock(); qCDebug(LANGUAGE) << "loading top-context" << index; TopDUContext* chain = TopDUContextDynamicData::load(index); if(chain) { chain->setParsingEnvironmentFile(loadInformation(chain->ownIndex())); if(!chain->usingImportsCache()) { //Eventually also load all the imported chains, so the import-structure is built foreach(const DUContext::Import &import, chain->DUContext::importedParentContexts()) { if(!loaded.contains(import.topContextIndex())) { loadChain(import.topContextIndex(), loaded); } } } chain->rebuildDynamicImportStructure(); chain->setInDuChain(true); instance->addDocumentChain(chain); } l.relock(); m_loading.remove(index); } } ///Stores all environment-information ///Also makes sure that all information that stays is referenced, so it stays alive. ///@param atomic If this is false, the write-lock will be released time by time void storeAllInformation(bool atomic, DUChainWriteLocker& locker) { uint cnt = 0; QList urls; { QMutexLocker lock(&m_chainsMutex); urls += m_fileEnvironmentInformations.keys(); } foreach(const IndexedString &url, urls) { QList check; { QMutexLocker lock(&m_chainsMutex); check = m_fileEnvironmentInformations.values(url); } foreach(ParsingEnvironmentFilePointer file, check) { EnvironmentInformationRequest req(file.data()); QMutexLocker lock(m_environmentInfo.mutex()); uint index = m_environmentInfo.findIndex(req); if(file->d_func()->isDynamic()) { //This item has been changed, or isn't in the repository yet //Eventually remove an old entry if(index) m_environmentInfo.deleteItem(index); //Add the new entry to the item repository index = m_environmentInfo.index(req); Q_ASSERT(index); EnvironmentInformationItem* item = const_cast(m_environmentInfo.itemFromIndex(index)); DUChainBaseData* theData = reinterpret_cast(reinterpret_cast(item) + sizeof(EnvironmentInformationItem)); Q_ASSERT(theData->m_range == file->d_func()->m_range); Q_ASSERT(theData->m_dynamic == false); Q_ASSERT(theData->classId == file->d_func()->classId); file->setData( theData ); ++cnt; }else{ m_environmentInfo.itemFromIndex(index); //Prevent unloading of the data, by accessing the item } } ///We must not release the lock while holding a reference to a ParsingEnvironmentFilePointer, else we may miss the deletion of an ///information, and will get crashes. if(!atomic && (cnt % 100 == 0)) { //Release the lock on a regular basis locker.unlock(); locker.lock(); } storeInformationList(url); //Access the data in the repository, so the bucket isn't unloaded uint index = m_environmentListInfo.findIndex(EnvironmentInformationListRequest(url)); if(index) { m_environmentListInfo.itemFromIndex(index); }else{ QMutexLocker lock(&m_chainsMutex); qCDebug(LANGUAGE) << "Did not find stored item for" << url.str() << "count:" << m_fileEnvironmentInformations.values(url); } if(!atomic) { locker.unlock(); locker.lock(); } } } QMutex& cleanupMutex() { return m_cleanupMutex; } ///@param retries When this is nonzero, then doMoreCleanup will do the specified amount of cycles ///doing the cleanup without permanently locking the du-chain. During these steps the consistency ///of the disk-storage is not guaranteed, but only few changes will be done during these steps, ///so the final step where the duchain is permanently locked is much faster. void doMoreCleanup(int retries = 0, bool needLockRepository = true) { if(m_cleanupDisabled) return; //This mutex makes sure that there's never 2 threads at he same time trying to clean up QMutexLocker lockCleanupMutex(&cleanupMutex()); if(m_destroyed || m_cleanupDisabled) return; Q_ASSERT(!instance->lock()->currentThreadHasReadLock() && !instance->lock()->currentThreadHasWriteLock()); DUChainWriteLocker writeLock(instance->lock()); PersistentSymbolTable::self().clearCache(); //This is used to stop all parsing before starting to do the cleanup. This way less happens during the //soft cleanups, and we have a good chance that during the "hard" cleanup only few data has to be written. QList lockedParseMutexes; QList locked; if(needLockRepository) { if (ICore* core = ICore::self()) if (ILanguageController* lc = core->languageController()) lockedParseMutexes = lc->loadedLanguages(); writeLock.unlock(); //Here we wait for all parsing-threads to stop their processing foreach(const auto& language, lockedParseMutexes) { language->parseLock()->lockForWrite(); locked << language->parseLock(); } writeLock.lock(); globalItemRepositoryRegistry().lockForWriting(); qCDebug(LANGUAGE) << "starting cleanup"; } QTime startTime = QTime::currentTime(); storeAllInformation(!retries, writeLock); //Puts environment-information into a repository //We don't need to increase the reference-count, since the cleanup-mutex is locked QSet workOnContexts; { QMutexLocker l(&m_chainsMutex); foreach(TopDUContext* top, m_chainsByUrl.values()) { workOnContexts << top; Q_ASSERT(hasChainForIndex(top->ownIndex())); } } foreach(TopDUContext* context, workOnContexts) { context->m_dynamicData->store(); if(retries) { //Eventually give other threads a chance to access the duchain writeLock.unlock(); //Sleep to give the other threads a realistic chance to get a read-lock in between QThread::usleep(500); writeLock.lock(); } } //Unload all top-contexts that don't have a reference-count and that are not imported by a referenced one QSet unloadedNames; bool unloadedOne = true; bool unloadAllUnreferenced = !retries; //Now unload contexts, but only ones that are not imported by any other currently loaded context //The complication: Since during the lock-break new references may be added, we must never keep //the du-chain in an invalid state. Thus we can only unload contexts that are not imported by any //currently loaded contexts. In case of loops, we have to unload everything at once. while(unloadedOne) { unloadedOne = false; int hadUnloadable = 0; unloadContexts: foreach(TopDUContext* unload, workOnContexts) { bool hasReference = false; { QMutexLocker l(&m_referenceCountsMutex); //Test if the context is imported by a referenced one foreach(TopDUContext* context, m_referenceCounts.keys()) { if(context == unload || context->imports(unload, CursorInRevision())) { workOnContexts.remove(unload); hasReference = true; } } } if(!hasReference) ++hadUnloadable; //We have found a context that is not referenced else continue; //This context is referenced bool isImportedByLoaded = !unload->loadedImporters().isEmpty(); //If we unload a context that is imported by other contexts, we create a bad loaded state if(isImportedByLoaded && !unloadAllUnreferenced) continue; unloadedNames.insert(unload->url()); //Since we've released the write-lock in between, we've got to call store() again to be sure that none of the data is dynamic //If nothing has changed, it is only a low-cost call. unload->m_dynamicData->store(); Q_ASSERT(!unload->d_func()->m_dynamic); removeDocumentChainFromMemory(unload); workOnContexts.remove(unload); unloadedOne = true; if(!unloadAllUnreferenced) { //Eventually give other threads a chance to access the duchain writeLock.unlock(); //Sleep to give the other threads a realistic chance to get a read-lock in between QThread::usleep(500); writeLock.lock(); } } if(hadUnloadable && !unloadedOne) { Q_ASSERT(!unloadAllUnreferenced); //This can happen in case of loops. We have o unload everything at one time. qCDebug(LANGUAGE) << "found" << hadUnloadable << "unloadable contexts, but could not unload separately. Unloading atomically."; unloadAllUnreferenced = true; hadUnloadable = 0; //Reset to 0, so we cannot loop forever goto unloadContexts; } } if(retries == 0) { QMutexLocker lock(&m_chainsMutex); //Do this atomically, since we must be sure that _everything_ is already saved for(QMultiMap::iterator it = m_fileEnvironmentInformations.begin(); it != m_fileEnvironmentInformations.end(); ) { ParsingEnvironmentFile* f = it->data(); Q_ASSERT(f->d_func()->classId); if(f->ref.load() == 1) { Q_ASSERT(!f->d_func()->isDynamic()); //It cannot be dynamic, since we have stored before //The ParsingEnvironmentFilePointer is only referenced once. This means that it does not belong to any //loaded top-context, so just remove it to save some memory and processing time. ///@todo use some kind of timeout before removing it = m_fileEnvironmentInformations.erase(it); }else{ ++it; } } } if(retries) writeLock.unlock(); //This must be the last step, due to the on-disk reference counting globalItemRepositoryRegistry().store(); //Stores all repositories { //Store the static parsing-environment file data ///@todo Solve this more elegantly, using a general mechanism to store static duchain-like data Q_ASSERT(ParsingEnvironmentFile::m_staticData); QFile f(globalItemRepositoryRegistry().path() + "/parsing_environment_data"); bool opened = f.open(QIODevice::WriteOnly); Q_ASSERT(opened); Q_UNUSED(opened); f.write((char*)ParsingEnvironmentFile::m_staticData, sizeof(StaticParsingEnvironmentData)); } ///Write out the list of available top-context indices { QMutexLocker lock(&m_chainsMutex); QFile f(globalItemRepositoryRegistry().path() + "/available_top_context_indices"); bool opened = f.open(QIODevice::WriteOnly); Q_ASSERT(opened); Q_UNUSED(opened); f.write((char*)m_availableTopContextIndices.data(), m_availableTopContextIndices.size() * sizeof(uint)); } if(retries) { doMoreCleanup(retries-1, false); writeLock.lock(); } if(needLockRepository) { globalItemRepositoryRegistry().unlockForWriting(); int elapsedSeconds = startTime.secsTo(QTime::currentTime()); qCDebug(LANGUAGE) << "seconds spent doing cleanup: " << elapsedSeconds << "top-contexts still open:" << m_chainsByUrl.size(); } if(!retries) { int elapesedMilliSeconds = startTime.msecsTo(QTime::currentTime()); qCDebug(LANGUAGE) << "milliseconds spent doing cleanup with locked duchain: " << elapesedMilliSeconds; } foreach(QReadWriteLock* lock, locked) lock->unlock(); #ifdef HAVE_MALLOC_TRIM // trim unused memory but keep a pad buffer of about 50 MB // this can greatly decrease the perceived memory consumption of kdevelop // see: https://sourceware.org/bugzilla/show_bug.cgi?id=14827 malloc_trim(50 * 1024 * 1024); #endif } ///Checks whether the information is already loaded. ParsingEnvironmentFile* findInformation(uint topContextIndex) { QMutexLocker lock(&m_chainsMutex); QHash::iterator it = m_indexEnvironmentInformations.find(topContextIndex); if(it != m_indexEnvironmentInformations.end()) return (*it).data(); return 0; } ///Loads/gets the environment-information for the given top-context index, or returns zero if none exists ///@warning m_chainsMutex should NOT be locked when this is called, because it triggers I/O ///@warning no other mutexes should be locked, as that may lead to a dedalock ParsingEnvironmentFile* loadInformation(uint topContextIndex) { ParsingEnvironmentFile* alreadyLoaded = findInformation(topContextIndex); if(alreadyLoaded) return alreadyLoaded; //Step two: Check if it is on disk, and if is, load it uint dataIndex = m_environmentInfo.findIndex(EnvironmentInformationRequest(topContextIndex)); if(!dataIndex) { //No environment-information stored for this top-context return 0; } const EnvironmentInformationItem& item(*m_environmentInfo.itemFromIndex(dataIndex)); QMutexLocker lock(&m_chainsMutex); //Due to multi-threading, we must do this check after locking the mutex, so we can be sure we don't create the same item twice at the same time alreadyLoaded = findInformation(topContextIndex); if(alreadyLoaded) return alreadyLoaded; ///FIXME: ugly, and remove const_cast ParsingEnvironmentFile* ret = dynamic_cast(DUChainItemSystem::self().create( const_cast(reinterpret_cast(reinterpret_cast(&item) + sizeof(EnvironmentInformationItem))) )); if(ret) { Q_ASSERT(ret->d_func()->classId); Q_ASSERT(ret->indexedTopContext().index() == topContextIndex); ParsingEnvironmentFilePointer retPtr(ret); m_fileEnvironmentInformations.insert(ret->url(), retPtr); Q_ASSERT(!m_indexEnvironmentInformations.contains(ret->indexedTopContext().index())); m_indexEnvironmentInformations.insert(ret->indexedTopContext().index(), retPtr); } return ret; } struct CleanupListVisitor { QList checkContexts; bool operator()(const EnvironmentInformationItem* item) { checkContexts << item->m_topContext; return true; } }; ///Will check a selection of all top-contexts for up-to-date ness, and remove them if out of date void cleanupTopContexts() { DUChainWriteLocker lock( DUChain::lock() ); qCDebug(LANGUAGE) << "cleaning top-contexts"; CleanupListVisitor visitor; uint startPos = 0; m_environmentInfo.visitAllItems(visitor); int checkContextsCount = maxFinalCleanupCheckContexts; int percentageOfContexts = (visitor.checkContexts.size() * 100) / minimumFinalCleanupCheckContextsPercentage; if(checkContextsCount < percentageOfContexts) checkContextsCount = percentageOfContexts; if(visitor.checkContexts.size() > (int)checkContextsCount) startPos = qrand() % (visitor.checkContexts.size() - checkContextsCount); int endPos = startPos + maxFinalCleanupCheckContexts; if(endPos > visitor.checkContexts.size()) endPos = visitor.checkContexts.size(); QSet< uint > check; for(int a = startPos; a < endPos && check.size() < checkContextsCount; ++a) if(check.size() < checkContextsCount) addContextsForRemoval(check, IndexedTopDUContext(visitor.checkContexts[a])); foreach(uint topIndex, check) { IndexedTopDUContext top(topIndex); if(top.data()) { qCDebug(LANGUAGE) << "removing top-context for" << top.data()->url().str() << "because it is out of date"; instance->removeDocumentChain(top.data()); } } qCDebug(LANGUAGE) << "check ready"; } private: void addContextsForRemoval(QSet& topContexts, IndexedTopDUContext top) { if(topContexts.contains(top.index())) return; QExplicitlySharedDataPointer info( instance->environmentFileForDocument(top) ); ///@todo Also check if the context is "useful"(Not a duplicate context, imported by a useful one, ...) if(info && info->needsUpdate()) { //This context will be removed }else{ return; } topContexts.insert(top.index()); if(info) { //Check whether importers need to be removed as well QList< QExplicitlySharedDataPointer > importers = info->importers(); QSet< QExplicitlySharedDataPointer > checkNext; //Do breadth first search, so less imports/importers have to be loaded, and a lower depth is reached for(QList< QExplicitlySharedDataPointer >::iterator it = importers.begin(); it != importers.end(); ++it) { IndexedTopDUContext c = (*it)->indexedTopContext(); if(!topContexts.contains(c.index())) { topContexts.insert(c.index()); //Prevent useless recursion checkNext.insert(*it); } } for(QSet< QExplicitlySharedDataPointer >::const_iterator it = checkNext.begin(); it != checkNext.end(); ++it) { topContexts.remove((*it)->indexedTopContext().index()); //Enable full check again addContextsForRemoval(topContexts, (*it)->indexedTopContext()); } } } ///Stores the environment-information for the given url void storeInformationList(IndexedString url) { QMutexLocker lock(m_environmentListInfo.mutex()); EnvironmentInformationListItem newItem; newItem.m_file = url; QSet newItems; { QMutexLocker lock(&m_chainsMutex); QMultiMap::iterator start = m_fileEnvironmentInformations.lowerBound(url); QMultiMap::iterator end = m_fileEnvironmentInformations.upperBound(url); for(QMultiMap::iterator it = start; it != end; ++it) { uint topContextIndex = (*it)->indexedTopContext().index(); newItems.insert(topContextIndex); newItem.itemsList().append(topContextIndex); } } uint index = m_environmentListInfo.findIndex(url); if(index) { //We only handle adding items here, since we can never be sure whether everything is loaded //Removal is handled directly in removeEnvironmentInformation const EnvironmentInformationListItem* item = m_environmentListInfo.itemFromIndex(index); QSet oldItems; FOREACH_FUNCTION(uint topContextIndex, item->items) { oldItems.insert(topContextIndex); if(!newItems.contains(topContextIndex)) { newItems.insert(topContextIndex); newItem.itemsList().append(topContextIndex); } } if(oldItems == newItems) return; ///Update/insert a new list m_environmentListInfo.deleteItem(index); //Remove the previous item } Q_ASSERT(m_environmentListInfo.findIndex(EnvironmentInformationListRequest(url)) == 0); //Insert the new item m_environmentListInfo.index(EnvironmentInformationListRequest(url, newItem)); Q_ASSERT(m_environmentListInfo.findIndex(EnvironmentInformationListRequest(url))); } //Loaded environment-informations. Protected by m_chainsMutex QMultiMap m_fileEnvironmentInformations; QHash m_indexEnvironmentInformations; ///The following repositories are thread-safe, and m_chainsMutex should not be locked when using them, because ///they may trigger I/O. Still it may be required to lock their local mutexes. ///Maps filenames to a list of top-contexts/environment-information. ItemRepository m_environmentListInfo; ///Maps top-context-indices to environment-information item. ItemRepository m_environmentInfo; }; Q_GLOBAL_STATIC(DUChainPrivate, sdDUChainPrivate) DUChain::DUChain() { Q_ASSERT(ICore::self()); connect(ICore::self()->documentController(), &IDocumentController::documentLoadedPrepare, this, &DUChain::documentLoadedPrepare); connect(ICore::self()->documentController(), &IDocumentController::documentUrlChanged, this, &DUChain::documentRenamed); connect(ICore::self()->documentController(), &IDocumentController::documentActivated, this, &DUChain::documentActivated); connect(ICore::self()->documentController(), &IDocumentController::documentClosed, this, &DUChain::documentClosed); } DUChain::~DUChain() { DUChain::m_deleted = true; } DUChain* DUChain::self() { return sdDUChainPrivate->instance; } extern void initModificationRevisionSetRepository(); extern void initDeclarationRepositories(); extern void initIdentifierRepository(); extern void initTypeRepository(); extern void initInstantiationInformationRepository(); void DUChain::initialize() { // Initialize the global item repository as first thing after loading the session Q_ASSERT(ICore::self()); Q_ASSERT(ICore::self()->activeSession()); ItemRepositoryRegistry::initialize(ICore::self()->activeSessionLock()); initReferenceCounting(); // This needs to be initialized here too as the function is not threadsafe, but can // sometimes be called from different threads. This results in the underlying QFile // being 0 and hence crashes at some point later when accessing the contents via // read. See https://bugs.kde.org/show_bug.cgi?id=250779 RecursiveImportRepository::repository(); RecursiveImportCacheRepository::repository(); // similar to above, see https://bugs.kde.org/show_bug.cgi?id=255323 initDeclarationRepositories(); initModificationRevisionSetRepository(); initIdentifierRepository(); initTypeRepository(); initInstantiationInformationRepository(); Importers::self(); globalImportIdentifier(); globalIndexedImportIdentifier(); globalAliasIdentifier(); globalIndexedAliasIdentifier(); } DUChainLock* DUChain::lock() { return &sdDUChainPrivate->lock; } QList DUChain::allChains() const { QMutexLocker l(&sdDUChainPrivate->m_chainsMutex); return sdDUChainPrivate->m_chainsByUrl.values(); } void DUChain::updateContextEnvironment( TopDUContext* context, ParsingEnvironmentFile* file ) { QMutexLocker l(&sdDUChainPrivate->m_chainsMutex); removeFromEnvironmentManager( context ); context->setParsingEnvironmentFile( file ); addToEnvironmentManager( context ); } void DUChain::removeDocumentChain( TopDUContext* context ) { ENSURE_CHAIN_WRITE_LOCKED; IndexedTopDUContext indexed(context->indexed()); Q_ASSERT(indexed.data() == context); ///This assertion fails if you call removeDocumentChain(..) on a document that has not been added to the du-chain context->m_dynamicData->deleteOnDisk(); Q_ASSERT(indexed.data() == context); sdDUChainPrivate->removeDocumentChainFromMemory(context); Q_ASSERT(!indexed.data()); Q_ASSERT(!environmentFileForDocument(indexed)); QMutexLocker lock(&sdDUChainPrivate->m_chainsMutex); sdDUChainPrivate->m_availableTopContextIndices.push_back(indexed.index()); } void DUChain::addDocumentChain( TopDUContext * chain ) { QMutexLocker l(&sdDUChainPrivate->m_chainsMutex); // qCDebug(LANGUAGE) << "duchain: adding document" << chain->url().str() << " " << chain; Q_ASSERT(chain); Q_ASSERT(!sdDUChainPrivate->hasChainForIndex(chain->ownIndex())); { QMutexLocker lock(&DUChain::chainsByIndexLock); if(DUChain::chainsByIndex.size() <= chain->ownIndex()) DUChain::chainsByIndex.resize(chain->ownIndex() + 100, 0); DUChain::chainsByIndex[chain->ownIndex()] = chain; } { Q_ASSERT(DUChain::chainsByIndex[chain->ownIndex()]); } Q_ASSERT(sdDUChainPrivate->hasChainForIndex(chain->ownIndex())); sdDUChainPrivate->m_chainsByUrl.insert(chain->url(), chain); Q_ASSERT(sdDUChainPrivate->hasChainForIndex(chain->ownIndex())); chain->setInDuChain(true); l.unlock(); addToEnvironmentManager(chain); // This function might be called during shutdown by stale parse jobs // Make sure we don't access null-pointers here if (ICore::self() && ICore::self()->languageController() && ICore::self()->languageController()->backgroundParser()->trackerForUrl(chain->url())) { //Make sure the context stays alive at least as long as the context is open ReferencedTopDUContext ctx(chain); sdDUChainPrivate->m_openDocumentContexts.insert(ctx); } } void DUChain::addToEnvironmentManager( TopDUContext * chain ) { ParsingEnvironmentFilePointer file = chain->parsingEnvironmentFile(); if( !file ) return; //We don't need to manage Q_ASSERT(file->indexedTopContext().index() == chain->ownIndex()); if(ParsingEnvironmentFile* alreadyHave = sdDUChainPrivate->findInformation(file->indexedTopContext().index())) { ///If this triggers, there has already been another environment-information registered for this top-context. ///removeFromEnvironmentManager should have been called before to remove the old environment-information. Q_ASSERT(alreadyHave == file.data()); Q_UNUSED(alreadyHave); return; } sdDUChainPrivate->addEnvironmentInformation(file); } void DUChain::removeFromEnvironmentManager( TopDUContext * chain ) { ParsingEnvironmentFilePointer file = chain->parsingEnvironmentFile(); if( !file ) return; //We don't need to manage sdDUChainPrivate->removeEnvironmentInformation(file); } TopDUContext* DUChain::chainForDocument(const QUrl& document, bool proxyContext) const { return chainForDocument(IndexedString(document), proxyContext); } bool DUChain::isInMemory(uint topContextIndex) const { return DUChainPrivate::hasChainForIndex(topContextIndex); } IndexedString DUChain::urlForIndex(uint index) const { { TopDUContext* chain = DUChainPrivate::readChainForIndex(index); if(chain) return chain->url(); } return TopDUContextDynamicData::loadUrl(index); } TopDUContext* DUChain::loadChain(uint index) { QSet loaded; sdDUChainPrivate->loadChain(index, loaded); { QMutexLocker lock(&chainsByIndexLock); if(chainsByIndex.size() > index) { TopDUContext* top = chainsByIndex[index]; if(top) return top; } } return 0; } TopDUContext* DUChain::chainForDocument(const KDevelop::IndexedString& document, bool proxyContext) const { ENSURE_CHAIN_READ_LOCKED; if(sdDUChainPrivate->m_destroyed) return 0; QList list = sdDUChainPrivate->getEnvironmentInformation(document); foreach(const ParsingEnvironmentFilePointer &file, list) if(isInMemory(file->indexedTopContext().index()) && file->isProxyContext() == proxyContext) { return file->topContext(); } foreach(const ParsingEnvironmentFilePointer &file, list) if(proxyContext == file->isProxyContext()) { return file->topContext(); } //Allow selecting a top-context even if there is no ParsingEnvironmentFile QList< TopDUContext* > ret = chainsForDocument(document); foreach(TopDUContext* ctx, ret) { if(!ctx->parsingEnvironmentFile() || (ctx->parsingEnvironmentFile()->isProxyContext() == proxyContext)) return ctx; } return 0; } QList DUChain::chainsForDocument(const QUrl& document) const { return chainsForDocument(IndexedString(document)); } QList DUChain::chainsForDocument(const IndexedString& document) const { QList chains; if(sdDUChainPrivate->m_destroyed) return chains; QMutexLocker l(&sdDUChainPrivate->m_chainsMutex); // Match all parsed versions of this document for (auto it = sdDUChainPrivate->m_chainsByUrl.lowerBound(document); it != sdDUChainPrivate->m_chainsByUrl.end(); ++it) { if (it.key() == document) chains << it.value(); else break; } return chains; } TopDUContext* DUChain::chainForDocument( const QUrl& document, const KDevelop::ParsingEnvironment* environment, bool proxyContext ) const { return chainForDocument( IndexedString(document), environment, proxyContext ); } ParsingEnvironmentFilePointer DUChain::environmentFileForDocument( const IndexedString& document, const ParsingEnvironment* environment, bool proxyContext ) const { ENSURE_CHAIN_READ_LOCKED; if(sdDUChainPrivate->m_destroyed) return ParsingEnvironmentFilePointer(); QList< ParsingEnvironmentFilePointer> list = sdDUChainPrivate->getEnvironmentInformation(document); // qCDebug(LANGUAGE) << document.str() << ": matching" << list.size() << (onlyProxyContexts ? "proxy-contexts" : (noProxyContexts ? "content-contexts" : "contexts")); auto it = list.constBegin(); while(it != list.constEnd()) { if(*it && ((*it)->isProxyContext() == proxyContext) && (*it)->matchEnvironment(environment) && // Verify that the environment-file and its top-context are "good": The top-context must exist, // and there must be a content-context associated to the proxy-context. (*it)->topContext() && (!proxyContext || DUChainUtils::contentContextFromProxyContext((*it)->topContext())) ) { return *it; } ++it; } return ParsingEnvironmentFilePointer(); } QList DUChain::allEnvironmentFiles(const IndexedString& document) { return sdDUChainPrivate->getEnvironmentInformation(document); } ParsingEnvironmentFilePointer DUChain::environmentFileForDocument(IndexedTopDUContext topContext) const { if(topContext.index() == 0) return ParsingEnvironmentFilePointer(); return ParsingEnvironmentFilePointer(sdDUChainPrivate->loadInformation(topContext.index())); } TopDUContext* DUChain::chainForDocument( const IndexedString& document, const ParsingEnvironment* environment, bool proxyContext ) const { if(sdDUChainPrivate->m_destroyed) return 0; ParsingEnvironmentFilePointer envFile = environmentFileForDocument(document, environment, proxyContext); if(envFile) { return envFile->topContext(); }else{ return 0; } } QList DUChain::documents() const { QMutexLocker l(&sdDUChainPrivate->m_chainsMutex); QList ret; foreach(TopDUContext* top, sdDUChainPrivate->m_chainsByUrl.values()) { ret << top->url().toUrl(); } return ret; } QList DUChain::indexedDocuments() const { QMutexLocker l(&sdDUChainPrivate->m_chainsMutex); QList ret; foreach(TopDUContext* top, sdDUChainPrivate->m_chainsByUrl.values()) { ret << top->url(); } return ret; } void DUChain::documentActivated(KDevelop::IDocument* doc) { if(sdDUChainPrivate->m_destroyed) return; //Check whether the document has an attached environment-manager, and whether that one thinks the document needs to be updated. //If yes, update it. DUChainReadLocker lock( DUChain::lock() ); QMutexLocker l(&sdDUChainPrivate->m_chainsMutex); TopDUContext* ctx = DUChainUtils::standardContextForUrl(doc->url(), true); if(ctx && ctx->parsingEnvironmentFile()) if(ctx->parsingEnvironmentFile()->needsUpdate()) ICore::self()->languageController()->backgroundParser()->addDocument(IndexedString(doc->url())); } void DUChain::documentClosed(IDocument* document) { if(sdDUChainPrivate->m_destroyed) return; IndexedString url(document->url()); foreach(const ReferencedTopDUContext &top, sdDUChainPrivate->m_openDocumentContexts) if(top->url() == url) sdDUChainPrivate->m_openDocumentContexts.remove(top); } void DUChain::documentLoadedPrepare(KDevelop::IDocument* doc) { if(sdDUChainPrivate->m_destroyed) return; const IndexedString url(doc->url()); DUChainWriteLocker lock( DUChain::lock() ); QMutexLocker l(&sdDUChainPrivate->m_chainsMutex); TopDUContext* standardContext = DUChainUtils::standardContextForUrl(doc->url()); QList chains = chainsForDocument(url); auto languages = ICore::self()->languageController()->languagesForUrl(doc->url()); if(standardContext) { Q_ASSERT(chains.contains(standardContext)); //We have just loaded it Q_ASSERT((standardContext->url() == url)); sdDUChainPrivate->m_openDocumentContexts.insert(standardContext); bool needsUpdate = standardContext->parsingEnvironmentFile() && standardContext->parsingEnvironmentFile()->needsUpdate(); if(!needsUpdate) { //Only apply the highlighting if we don't need to update, else we might highlight total crap //Do instant highlighting only if all imports are loaded, to make sure that we don't block the user-interface too long //Else the highlighting will be done in the background-thread //This is not exactly right, as the direct imports don't necessarily equal the real imports used by uses //but it approximates the correct behavior. bool allImportsLoaded = true; foreach(const DUContext::Import& import, standardContext->importedParentContexts()) if(!import.indexedContext().indexedTopContext().isLoaded()) allImportsLoaded = false; if(allImportsLoaded) { l.unlock(); lock.unlock(); foreach(const auto& language, languages) { if(language->codeHighlighting()) { language->codeHighlighting()->highlightDUChain(standardContext); } } qCDebug(LANGUAGE) << "highlighted" << doc->url() << "in foreground"; return; } }else{ qCDebug(LANGUAGE) << "not highlighting the duchain because the documents needs an update"; } if(needsUpdate || !(standardContext->features() & TopDUContext::AllDeclarationsContextsAndUses)) { ICore::self()->languageController()->backgroundParser()->addDocument(IndexedString(doc->url()), (TopDUContext::Features)(TopDUContext::AllDeclarationsContextsAndUses | TopDUContext::ForceUpdate)); return; } } //Add for highlighting etc. ICore::self()->languageController()->backgroundParser()->addDocument(IndexedString(doc->url()), TopDUContext::AllDeclarationsContextsAndUses); } void DUChain::documentRenamed(KDevelop::IDocument* doc) { if(sdDUChainPrivate->m_destroyed) return; if(!doc->url().isValid()) { ///Maybe this happens when a file was deleted? qCWarning(LANGUAGE) << "Strange, url of renamed document is invalid!"; }else{ ICore::self()->languageController()->backgroundParser()->addDocument(IndexedString(doc->url()), (TopDUContext::Features)(TopDUContext::AllDeclarationsContextsAndUses | TopDUContext::ForceUpdate)); } } Uses* DUChain::uses() { return &sdDUChainPrivate->m_uses; } Definitions* DUChain::definitions() { return &sdDUChainPrivate->m_definitions; } static void finalCleanup() { DUChainWriteLocker writeLock(DUChain::lock()); qCDebug(LANGUAGE) << "doing final cleanup"; int cleaned = 0; while((cleaned = globalItemRepositoryRegistry().finalCleanup())) { qCDebug(LANGUAGE) << "cleaned" << cleaned << "B"; if(cleaned < 1000) { qCDebug(LANGUAGE) << "cleaned enough"; break; } } qCDebug(LANGUAGE) << "final cleanup ready"; } void DUChain::shutdown() { // if core is not shutting down, we can end up in deadlocks or crashes // since language plugins might still try to access static duchain stuff Q_ASSERT(!ICore::self() || ICore::self()->shuttingDown()); qCDebug(LANGUAGE) << "Cleaning up and shutting down DUChain"; QMutexLocker lock(&sdDUChainPrivate->cleanupMutex()); { //Acquire write-lock of the repository, so when kdevelop crashes in that process, the repository is discarded //Crashes here may happen in an inconsistent state, thus this makes sense, to protect the user from more crashes globalItemRepositoryRegistry().lockForWriting(); sdDUChainPrivate->cleanupTopContexts(); globalItemRepositoryRegistry().unlockForWriting(); } sdDUChainPrivate->doMoreCleanup(); //Must be done _before_ finalCleanup, else we may be deleting yet needed data sdDUChainPrivate->m_openDocumentContexts.clear(); sdDUChainPrivate->m_destroyed = true; sdDUChainPrivate->clear(); { //Acquire write-lock of the repository, so when kdevelop crashes in that process, the repository is discarded //Crashes here may happen in an inconsistent state, thus this makes sense, to protect the user from more crashes globalItemRepositoryRegistry().lockForWriting(); finalCleanup(); globalItemRepositoryRegistry().unlockForWriting(); } globalItemRepositoryRegistry().shutdown(); } uint DUChain::newTopContextIndex() { { QMutexLocker lock(&sdDUChainPrivate->m_chainsMutex); if(!sdDUChainPrivate->m_availableTopContextIndices.isEmpty()) { uint ret = sdDUChainPrivate->m_availableTopContextIndices.back(); sdDUChainPrivate->m_availableTopContextIndices.pop_back(); if(TopDUContextDynamicData::fileExists(ret)) { qCWarning(LANGUAGE) << "Problem in the management of availalbe top-context indices"; return newTopContextIndex(); } return ret; } } static QAtomicInt& currentId( globalItemRepositoryRegistry().getCustomCounter("Top-Context Counter", 1) ); return currentId.fetchAndAddRelaxed(1); } void DUChain::refCountUp(TopDUContext* top) { QMutexLocker l(&sdDUChainPrivate->m_referenceCountsMutex); if(!sdDUChainPrivate->m_referenceCounts.contains(top)) sdDUChainPrivate->m_referenceCounts.insert(top, 1); else ++sdDUChainPrivate->m_referenceCounts[top]; } bool DUChain::deleted() { return m_deleted; } void DUChain::refCountDown(TopDUContext* top) { QMutexLocker l(&sdDUChainPrivate->m_referenceCountsMutex); if(!sdDUChainPrivate->m_referenceCounts.contains(top)) { //qCWarning(LANGUAGE) << "tried to decrease reference-count for" << top->url().str() << "but this top-context is not referenced"; return; } --sdDUChainPrivate->m_referenceCounts[top]; if(!sdDUChainPrivate->m_referenceCounts[top]) sdDUChainPrivate->m_referenceCounts.remove(top); } void DUChain::emitDeclarationSelected(const DeclarationPointer& decl) { emit declarationSelected(decl); } KDevelop::ReferencedTopDUContext DUChain::waitForUpdate(const KDevelop::IndexedString& document, KDevelop::TopDUContext::Features minFeatures, bool proxyContext) { Q_ASSERT(!lock()->currentThreadHasReadLock() && !lock()->currentThreadHasWriteLock()); WaitForUpdate waiter; updateContextForUrl(document, minFeatures, &waiter); // waiter.m_waitMutex.lock(); // waiter.m_dataMutex.unlock(); while(!waiter.m_ready) { // we might have been shut down in the meanwhile if (!ICore::self()) { return 0; } QMetaObject::invokeMethod(ICore::self()->languageController()->backgroundParser(), "parseDocuments"); QApplication::processEvents(); QThread::usleep(1000); } if(!proxyContext) { DUChainReadLocker readLock(DUChain::lock()); return DUChainUtils::contentContextFromProxyContext(waiter.m_topContext); } return waiter.m_topContext; } void DUChain::updateContextForUrl(const IndexedString& document, TopDUContext::Features minFeatures, QObject* notifyReady, int priority) const { DUChainReadLocker lock( DUChain::lock() ); TopDUContext* standardContext = DUChainUtils::standardContextForUrl(document.toUrl()); if(standardContext && standardContext->parsingEnvironmentFile() && !standardContext->parsingEnvironmentFile()->needsUpdate() && standardContext->parsingEnvironmentFile()->featuresSatisfied(minFeatures)) { lock.unlock(); if(notifyReady) QMetaObject::invokeMethod(notifyReady, "updateReady", Qt::DirectConnection, Q_ARG(KDevelop::IndexedString, document), Q_ARG(KDevelop::ReferencedTopDUContext, ReferencedTopDUContext(standardContext))); }else{ ///Start a parse-job for the given document ICore::self()->languageController()->backgroundParser()->addDocument(document, minFeatures, priority, notifyReady); } } void DUChain::disablePersistentStorage(bool disable) { sdDUChainPrivate->m_cleanupDisabled = disable; } void DUChain::storeToDisk() { bool wasDisabled = sdDUChainPrivate->m_cleanupDisabled; sdDUChainPrivate->m_cleanupDisabled = false; sdDUChainPrivate->doMoreCleanup(); sdDUChainPrivate->m_cleanupDisabled = wasDisabled; } bool DUChain::compareToDisk() { DUChainWriteLocker writeLock(DUChain::lock()); ///Step 1: Compare the repositories return true; } } diff --git a/language/duchain/duchain.h b/language/duchain/duchain.h index 5c38f243f1..908bd1d1ad 100644 --- a/language/duchain/duchain.h +++ b/language/duchain/duchain.h @@ -1,301 +1,301 @@ /* This file is part of KDevelop Copyright 2006-2008 Hamish Rodda Copyright 2007-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. */ #ifndef KDEVPLATFORM_DUCHAIN_H #define KDEVPLATFORM_DUCHAIN_H #include #include "topducontext.h" #include "parsingenvironment.h" class QUrl; namespace KDevelop { class IDocument; class TopDUContext; class DUChainLock; class ParsingEnvironmentManager; class ParsingEnvironment; class ParsingEnvironmentFile; typedef QExplicitlySharedDataPointer ParsingEnvironmentFilePointer; class Definitions; class Uses; /** * \short Holds references to all top level source file contexts. * * The DUChain is a global static class which manages the definition-use * chains. It performs the following functions: * \li registers chains with addDocumentChain() and deregisters with removeDocumentChain() * \li allows querying for existing chains * \li watches text editors, registering and deregistering them with the BackgroundParser when files * are opened and closed. */ class KDEVPLATFORMLANGUAGE_EXPORT DUChain : public QObject { Q_OBJECT public: /** * Initializes common static item repositories. * Must be called once for multi threaded applications to work reliably. */ static void initialize(); /** * Return a list of all chains available */ Q_SCRIPTABLE QList allChains() const; /** * Makes sure the standard-context for the given url is up-to-date. * This may trigger a parsing in background, so a QObject can be given that will be notified * asyonchronously once the update is ready. * If the context is already up to date, the given QObject is notified directly. * * @param document Document to update * @param features The requested features. If you want to force a full update of the context, give TopDUContext::ForceUpdate. * If you want to force an update including all imports, use TopDUContext::ForceUpdateRecursive. * @param notifyReady An optional pointer to a QObject that should contain a slot * "void updateReady(KDevelop::IndexedString url, KDevelop::ReferencedTopDUContext topContext)". * The notification is guaranteed to be called once for each call to updateContextForUrl. The given top-context * may be invalid if the update failed. A queued connection is used if a re-parse has to be done. The duchain * will _not_ be locked when updateReady is called. * @param priority An optional priority for the job. The lower the value, the higher it's priority. * @note The duchain must _not_ be locked when this is called! */ Q_SCRIPTABLE void updateContextForUrl(const IndexedString& document, TopDUContext::Features minFeatures, QObject* notifyReady = 0, int priority = 1) const; /** * Convenience-function similar to updateContextForUrl that blocks this thread until the update of the given document is ready, * and returns the top-context. * @param document The document to update * @param features The requested features. If you want to force a full update of the context, give TopDUContext::ForceUpdate. * If you want to force an update including all imports, use TopDUContext::ForceUpdateRecursive. * @return The up-to-date top-context, or zero if the update failed * * @note The duchain must _not_ be locked when this is called! * */ KDevelop::ReferencedTopDUContext waitForUpdate(const KDevelop::IndexedString& document, KDevelop::TopDUContext::Features minFeatures, bool proxyContext = false); /** * Return any chain for the given document * If available, the version accepting IndexedString should be used instead of this, for performance reasons. * When no fitting chain is in memory, one may be loaded from disk. * * @note The duchain must be at least read-locked locked when this is called! * */ Q_SCRIPTABLE TopDUContext* chainForDocument(const QUrl& document, bool proxyContext = false) const; Q_SCRIPTABLE TopDUContext* chainForDocument(const IndexedString& document, bool proxyContext = false) const; /** * Return all chains for the given document that are currently in memory. * This does not load any chains from disk. * */ Q_SCRIPTABLE QList chainsForDocument(const QUrl& document) const; /** * Return all chains for the given document that are currently in memory. * This does not load any chains from disk. * Should be preferred over the QUrl version. * */ Q_SCRIPTABLE QList chainsForDocument(const IndexedString& document) const; /** * Find a chain that fits into the given environment. If no fitting chain is found, 0 is returned. * When no fitting chain is in memory, one may be loaded from disk. * @param proxyContext If this is true, only contexts are found that have an ParsingEnvironmentFile that has the proxy-flag set. Else, only content-contexts will be returned. * * @note The duchain must be at least read-locked locked when this is called! * */ Q_SCRIPTABLE TopDUContext* chainForDocument(const QUrl& document, const ParsingEnvironment* environment, bool proxyContext = false) const; /** * Find a chain that fits into the given environment. If no fitting chain is found, 0 is returned. * When no fitting chain is in memory, one may be loaded from disk. * @param proxyContext If this is true, only contexts are found that have an ParsingEnvironmentFile that has the proxy-flag set. Else, only content-contexts will be returned. * * Prefer this over the QUrl version. * * @note The duchain must be at least read-locked locked when this is called! * */ Q_SCRIPTABLE TopDUContext* chainForDocument(const IndexedString& document, const ParsingEnvironment* environment, bool proxyContext = false) const; /** * Find the environment-file of a chain that fits into the given environment. If no fitting chain is found, 0 is returned. * When no fitting chain is in memory, one may be loaded from disk. * * This should be preferred over chainForDocument when only the environment-info is needed, because the TopDUContext is not loaded in this function. * ** @param proxyContext If this is true, only contexts are found that have an ParsingEnvironmentFile that has the proxy-flag set. Else, only content-contexts will be returned. * * Prefer this over the QUrl version. * * @note The duchain must be at least read-locked locked when this is called! * */ Q_SCRIPTABLE ParsingEnvironmentFilePointer environmentFileForDocument(const IndexedString& document, const ParsingEnvironment* environment, bool proxyContext = false) const; Q_SCRIPTABLE ParsingEnvironmentFilePointer environmentFileForDocument(IndexedTopDUContext topContext) const; /** * Returns the list of the environment-infos of all versions of the given document. */ Q_SCRIPTABLE QList allEnvironmentFiles(const IndexedString& document); ///Returns the top-context that has the given index assigned, or zero if it doesn't exist. @see TopDUContext::ownIndex ///The duchain must be read-locked when this is called ///This function is inlined because it is called in a very high frequency Q_SCRIPTABLE inline TopDUContext* chainForIndex(uint index) { if(m_deleted) return 0; { QMutexLocker lock(&chainsByIndexLock); if(chainsByIndex.size() > index) { TopDUContext* top = chainsByIndex[index]; if(top) return top; } } //Load the top-context return loadChain(index); } ///Returns the url for the given top-context index if available. This does have some cost, so avoid it when possible. Q_SCRIPTABLE IndexedString urlForIndex(uint index) const; /// Only used for debugging at the moment Q_SCRIPTABLE QList documents() const; /// Only used for debugging at the moment /// Prefer that over the QUrl version for performance reasons Q_SCRIPTABLE QList indexedDocuments() const; /** * Registers a new definition-use \a chain for the given \a document. */ Q_SCRIPTABLE void addDocumentChain(TopDUContext* chain); /// Returns true if the global duchain instance has already been deleted Q_SCRIPTABLE static bool deleted(); /// Returns the global static instance. Q_SCRIPTABLE static DUChain* self(); /// Returns the structure that manages mapping between definitions and declarations Q_SCRIPTABLE static Definitions* definitions(); /// Returns the structure that manages mapping between declarations, and which top level contexts contain uses of them. static Uses* uses(); /** * Retrieve the read write lock for the entire definition-use chain. * To call non-const methods, you must be holding a write lock. * * Evaluations made prior to holding a lock (including which objects * exist) must be verified once the lock is held, as they may have changed * or been deleted. * * \threadsafe */ Q_SCRIPTABLE static DUChainLock* lock(); /// Returns whether the top-context with the given index is currently loaded in memory Q_SCRIPTABLE bool isInMemory(uint topContextIndex) const; /** * Changes the environment attached to the given top-level context, and updates the management-structures to reflect that * */ Q_SCRIPTABLE void updateContextEnvironment( TopDUContext* context, ParsingEnvironmentFile* file ); ///Allocates a new identity for a new top-context, no lock needed. The returned value is never zero static uint newTopContextIndex(); ///If you call this, the persistent disk-storage structure will stay unaffected, and no duchain cleanup will be done. ///Call this from within tests. void disablePersistentStorage(bool disable = true); ///Stores the whole duchain and all its repositories in the current state to disk ///The duchain must not be locked in any way void storeToDisk(); ///Compares the whole duchain and all its repositories in the current state to disk ///When the comparison fails, debug-output will show why ///The duchain must not be locked when calling this ///@return true If the current memory state equals the disk state, else false bool compareToDisk(); Q_SIGNALS: ///Is emitted when the declaration has been selected somewhere in the user-interface, for example in the completion-list void declarationSelected(const KDevelop::DeclarationPointer& decl); public Q_SLOTS: ///Removes the given top-context from the duchain, and deletes it. void removeDocumentChain(KDevelop::TopDUContext* document); ///Emits the declarationSelected signal, so other parties can notice it. void emitDeclarationSelected(const KDevelop::DeclarationPointer& decl); /** * Shutdown and cleanup the DUChain. */ void shutdown(); private Q_SLOTS: void documentActivated(KDevelop::IDocument* doc); void documentLoadedPrepare(KDevelop::IDocument* document); void documentRenamed(KDevelop::IDocument* document); void documentClosed(KDevelop::IDocument*); private: TopDUContext* loadChain(uint index); //These two are exported here so that the extremely frequently called chainForIndex(..) can be inlined static bool m_deleted; static std::vector chainsByIndex; static QMutex chainsByIndexLock; /// Increases the reference-count for the given top-context. The result: It will not be unloaded. /// Do this to prevent KDevelop from unloading a top-context that you plan to use. Don't forget calling unReferenceToContext again, /// else the top-context will stay in memory for ever. void refCountUp(TopDUContext* top); /// Decreases the reference-count for the given top-context. When it reaches zero, KDevelop is free to unload it at any time, /// also invalidating all the contained declarations and contexts. void refCountDown(TopDUContext* top); void addToEnvironmentManager( TopDUContext * chain ); void removeFromEnvironmentManager( TopDUContext * chain ); DUChain(); - ~DUChain(); + ~DUChain() override; friend class DUChainPrivate; friend class ReferencedTopDUContext; }; } #endif // KDEVPLATFORM_DUCHAIN_H diff --git a/language/duchain/duchainutils.cpp b/language/duchain/duchainutils.cpp index 2511684d4d..82d267a687 100644 --- a/language/duchain/duchainutils.cpp +++ b/language/duchain/duchainutils.cpp @@ -1,619 +1,629 @@ /* * DUChain Utilities * * Copyright 2007 Hamish Rodda * Copyright 2007-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 "duchainutils.h" #include #include #include "../interfaces/ilanguagesupport.h" #include "util/debug.h" #include "declaration.h" #include "classfunctiondeclaration.h" #include "ducontext.h" #include "duchain.h" #include "use.h" #include "duchainlock.h" #include "classmemberdeclaration.h" #include "functiondefinition.h" #include "specializationstore.h" #include "persistentsymboltable.h" #include "classdeclaration.h" #include "parsingenvironment.h" using namespace KDevelop; using namespace KTextEditor; CodeCompletionModel::CompletionProperties DUChainUtils::completionProperties(const Declaration* dec) { CodeCompletionModel::CompletionProperties p; if(dec->context()->type() == DUContext::Class) { if (const ClassMemberDeclaration* member = dynamic_cast(dec)) { switch (member->accessPolicy()) { case Declaration::Public: p |= CodeCompletionModel::Public; break; case Declaration::Protected: p |= CodeCompletionModel::Protected; break; case Declaration::Private: p |= CodeCompletionModel::Private; break; default: break; } if (member->isStatic()) p |= CodeCompletionModel::Static; if (member->isAuto()) {}//TODO if (member->isFriend()) p |= CodeCompletionModel::Friend; if (member->isRegister()) {}//TODO if (member->isExtern()) {}//TODO if (member->isMutable()) {}//TODO } } if (const AbstractFunctionDeclaration* function = dynamic_cast(dec)) { p |= CodeCompletionModel::Function; if (function->isVirtual()) p |= CodeCompletionModel::Virtual; if (function->isInline()) p |= CodeCompletionModel::Inline; if (function->isExplicit()) {}//TODO } if( dec->isTypeAlias() ) p |= CodeCompletionModel::TypeAlias; if (dec->abstractType()) { switch (dec->abstractType()->whichType()) { case AbstractType::TypeIntegral: p |= CodeCompletionModel::Variable; break; case AbstractType::TypePointer: p |= CodeCompletionModel::Variable; break; case AbstractType::TypeReference: p |= CodeCompletionModel::Variable; break; case AbstractType::TypeFunction: p |= CodeCompletionModel::Function; break; case AbstractType::TypeStructure: p |= CodeCompletionModel::Class; break; case AbstractType::TypeArray: p |= CodeCompletionModel::Variable; break; case AbstractType::TypeEnumeration: p |= CodeCompletionModel::Enum; break; case AbstractType::TypeEnumerator: p |= CodeCompletionModel::Variable; break; case AbstractType::TypeAbstract: case AbstractType::TypeDelayed: case AbstractType::TypeUnsure: case AbstractType::TypeAlias: // TODO break; } if( dec->abstractType()->modifiers() & AbstractType::ConstModifier ) p |= CodeCompletionModel::Const; if( dec->kind() == Declaration::Instance && !dec->isFunctionDeclaration() ) p |= CodeCompletionModel::Variable; } if (dec->context()) { if( dec->context()->type() == DUContext::Global ) p |= CodeCompletionModel::GlobalScope; else if( dec->context()->type() == DUContext::Namespace ) p |= CodeCompletionModel::NamespaceScope; else if( dec->context()->type() != DUContext::Class && dec->context()->type() != DUContext::Enum ) p |= CodeCompletionModel::LocalScope; } return p; } /**We have to construct the item from the pixmap, else the icon will be marked as "load on demand", * and for some reason will be loaded every time it's used(this function returns a QIcon marked "load on demand" * each time this is called). And the loading is very slow. Seems like a bug somewhere, it cannot be ment to be that slow. */ #define RETURN_CACHED_ICON(name) {static QIcon icon(QIcon::fromTheme(name).pixmap(QSize(16, 16))); return icon;} QIcon DUChainUtils::iconForProperties(KTextEditor::CodeCompletionModel::CompletionProperties p) { if( (p & CodeCompletionModel::Variable) ) if( (p & CodeCompletionModel::Protected) ) RETURN_CACHED_ICON("CVprotected_var") else if( p & CodeCompletionModel::Private ) RETURN_CACHED_ICON("CVprivate_var") else RETURN_CACHED_ICON("CVpublic_var") else if( (p & CodeCompletionModel::Union) && (p & CodeCompletionModel::Protected) ) RETURN_CACHED_ICON("protected_union") else if( p & CodeCompletionModel::Enum ) if( p & CodeCompletionModel::Protected ) RETURN_CACHED_ICON("protected_enum") else if( p & CodeCompletionModel::Private ) RETURN_CACHED_ICON("private_enum") else RETURN_CACHED_ICON("enum") else if( p & CodeCompletionModel::Struct ) if( p & CodeCompletionModel::Private ) RETURN_CACHED_ICON("private_struct") else RETURN_CACHED_ICON("struct") else if( p & CodeCompletionModel::Slot ) if( p & CodeCompletionModel::Protected ) RETURN_CACHED_ICON("CVprotected_slot") else if( p & CodeCompletionModel::Private ) RETURN_CACHED_ICON("CVprivate_slot") else if(p & CodeCompletionModel::Public ) RETURN_CACHED_ICON("CVpublic_slot") else RETURN_CACHED_ICON("slot") else if( p & CodeCompletionModel::Signal ) if( p & CodeCompletionModel::Protected ) RETURN_CACHED_ICON("CVprotected_signal") else RETURN_CACHED_ICON("signal") else if( p & CodeCompletionModel::Class ) if( (p & CodeCompletionModel::Class) && (p & CodeCompletionModel::Protected) ) RETURN_CACHED_ICON("protected_class") else if( (p & CodeCompletionModel::Class) && (p & CodeCompletionModel::Private) ) RETURN_CACHED_ICON("private_class") else RETURN_CACHED_ICON("code-class") else if( p & CodeCompletionModel::Union ) if( p & CodeCompletionModel::Private ) RETURN_CACHED_ICON("private_union") else RETURN_CACHED_ICON("union") else if( p & CodeCompletionModel::TypeAlias ) if ((p & CodeCompletionModel::Const) /*|| (p & CodeCompletionModel::Volatile)*/) RETURN_CACHED_ICON("CVtypedef") else RETURN_CACHED_ICON("typedef") else if( p & CodeCompletionModel::Function ) { if( p & CodeCompletionModel::Protected ) RETURN_CACHED_ICON("protected_function") else if( p & CodeCompletionModel::Private ) RETURN_CACHED_ICON("private_function") else RETURN_CACHED_ICON("code-function") } if( p & CodeCompletionModel::Protected ) RETURN_CACHED_ICON("protected_field") else if( p & CodeCompletionModel::Private ) RETURN_CACHED_ICON("private_field") else RETURN_CACHED_ICON("field") return QIcon(); } QIcon DUChainUtils::iconForDeclaration(const Declaration* dec) { return iconForProperties(completionProperties(dec)); } TopDUContext* DUChainUtils::contentContextFromProxyContext(TopDUContext* top) { if(!top) return 0; if(top->parsingEnvironmentFile() && top->parsingEnvironmentFile()->isProxyContext()) { if(!top->importedParentContexts().isEmpty()) { DUContext* ctx = top->importedParentContexts()[0].context(0); if(!ctx) return 0; TopDUContext* ret = ctx->topContext(); if(!ret) return 0; if(ret->url() != top->url()) qCDebug(LANGUAGE) << "url-mismatch between content and proxy:" << top->url().toUrl() << ret->url().toUrl(); if(ret->url() == top->url() && !ret->parsingEnvironmentFile()->isProxyContext()) return ret; } else { qCDebug(LANGUAGE) << "Proxy-context imports no content-context"; } } else return top; return 0; } TopDUContext* DUChainUtils::standardContextForUrl(const QUrl& url, bool preferProxyContext) { KDevelop::TopDUContext* chosen = 0; auto languages = ICore::self()->languageController()->languagesForUrl(url); foreach(const auto& language, languages) { if(!chosen) { chosen = language->standardContext(url, preferProxyContext); } } if(!chosen) chosen = DUChain::self()->chainForDocument(IndexedString(url), preferProxyContext); if(!chosen && preferProxyContext) return standardContextForUrl(url, false); // Fall back to a normal context return chosen; } Declaration* declarationUnderCursor(const CursorInRevision& c, DUContext* ctx) { foreach( Declaration* decl, ctx->localDeclarations() ) if( decl->range().contains(c, RangeInRevision::IncludeBackEdge) ) return decl; //Search all collapsed sub-contexts. In C++, those can contain declarations that have ranges out of the context foreach( DUContext* subCtx, ctx->childContexts() ) { //This is a little hacky, but we need it in case of foreach macros and similar stuff if(subCtx->range().isEmpty() || subCtx->range().start.line == c.line || subCtx->range().end.line == c.line) { Declaration* decl = declarationUnderCursor(c, subCtx); if(decl) return decl; } } return 0; } Declaration* DUChainUtils::itemUnderCursor(const QUrl& url, const KTextEditor::Cursor& _c) { KDevelop::TopDUContext* chosen = standardContextForUrl(url); if( chosen ) { CursorInRevision c = chosen->transformToLocalRevision(_c); DUContext* ctx = chosen->findContextAt(c); while( ctx ) { //Try finding a declaration under the cursor Declaration* decl = declarationUnderCursor(c, ctx); if(decl) return decl; //Try finding a use under the cursor for(int a = 0; a < ctx->usesCount(); ++a) if( ctx->uses()[a].m_range.contains(c, RangeInRevision::IncludeBackEdge) ) return ctx->topContext()->usedDeclarationForIndex(ctx->uses()[a].m_declarationIndex); ctx = ctx->parentContext(); //It may happen, for example in the case of function-declarations, that the use is one context higher. } } return 0; } KTextEditor::Range DUChainUtils::itemRangeUnderCursor(const QUrl& url, const KTextEditor::Cursor& cursor) { KDevelop::TopDUContext* chosen = standardContextForUrl(url); if( chosen ) { CursorInRevision c = chosen->transformToLocalRevision(cursor); DUContext* ctx = chosen->findContextAt(c); if (ctx) { Declaration* decl = declarationUnderCursor(c, ctx); // Some declarations need to be searched in parent context if (!decl && ctx->parentContext()) { decl = declarationUnderCursor(c, ctx->parentContext()); } if (decl && decl->range().contains(c, RangeInRevision::IncludeBackEdge) ) { return decl->rangeInCurrentRevision(); } for(int a = 0; a < ctx->usesCount(); ++a) { if( ctx->uses()[a].m_range.contains(c, RangeInRevision::IncludeBackEdge) ) { return ctx->transformFromLocalRevision(ctx->uses()[a].m_range); } } } } return KTextEditor::Range(); } Declaration* DUChainUtils::declarationForDefinition(Declaration* definition, TopDUContext* topContext) { if(!definition) return 0; if(!topContext) topContext = definition->topContext(); if(dynamic_cast(definition)) { Declaration* ret = static_cast(definition)->declaration(); if(ret) return ret; } return definition; } Declaration* DUChainUtils::declarationInLine(const KTextEditor::Cursor& _cursor, DUContext* ctx) { if(!ctx) return 0; CursorInRevision cursor = ctx->transformToLocalRevision(_cursor); foreach(Declaration* decl, ctx->localDeclarations()) { if(decl->range().start.line == cursor.line) return decl; DUContext* funCtx = getFunctionContext(decl); if(funCtx && funCtx->range().contains(cursor)) return decl; } foreach(DUContext* child, ctx->childContexts()){ Declaration* decl = declarationInLine(_cursor, child); if(decl) return decl; } return 0; } DUChainUtils::DUChainItemFilter::~DUChainItemFilter() { } void DUChainUtils::collectItems( DUContext* context, DUChainItemFilter& filter ) { QVector children = context->childContexts(); QVector localDeclarations = context->localDeclarations(); QVector::const_iterator childIt = children.constBegin(); QVector::const_iterator declIt = localDeclarations.constBegin(); while(childIt != children.constEnd() || declIt != localDeclarations.constEnd()) { DUContext* child = 0; if(childIt != children.constEnd()) child = *childIt; Declaration* decl = 0; if(declIt != localDeclarations.constEnd()) decl = *declIt; if(decl) { if(child && child->range().start.line >= decl->range().start.line) child = 0; } if(child) { if(decl && decl->range().start >= child->range().start) decl = 0; } if(decl) { if( filter.accept(decl) ) { //Action is done in the filter } ++declIt; continue; } if(child) { if( filter.accept(child) ) collectItems(child, filter); ++childIt; continue; } } } KDevelop::DUContext* DUChainUtils::getArgumentContext(KDevelop::Declaration* decl) { DUContext* internal = decl->internalContext(); if( !internal ) return 0; if( internal->type() == DUContext::Function ) return internal; foreach( const DUContext::Import &ctx, internal->importedParentContexts() ) { if( ctx.context(decl->topContext()) ) if( ctx.context(decl->topContext())->type() == DUContext::Function ) return ctx.context(decl->topContext()); } return 0; } QList DUChainUtils::collectAllVersions(Declaration* decl) { QList ret; ret << IndexedDeclaration(decl); if(decl->inSymbolTable()) { uint count; const IndexedDeclaration* allDeclarations; PersistentSymbolTable::self().declarations(decl->qualifiedIdentifier(), count, allDeclarations); for(uint a = 0; a < count; ++a) if(!(allDeclarations[a] == IndexedDeclaration(decl))) ret << allDeclarations[a]; } return ret; } -///For a class, returns all classes that inherit it -QList DUChainUtils::getInheriters(const Declaration* decl, uint& maxAllowedSteps, bool collectVersions) +static QList getInheritersInternal(const Declaration* decl, uint& maxAllowedSteps, bool collectVersions) { QList ret; if(!dynamic_cast(decl)) return ret; if(maxAllowedSteps == 0) return ret; if(decl->internalContext() && decl->internalContext()->type() == DUContext::Class) for (const IndexedDUContext& importer : decl->internalContext()->indexedImporters()) { DUContext* imp = importer.data(); if(!imp) continue; if(imp->type() == DUContext::Class && imp->owner()) ret << imp->owner(); --maxAllowedSteps; if(maxAllowedSteps == 0) return ret; } if(maxAllowedSteps == 0) return ret; if(collectVersions && decl->inSymbolTable()) { uint count; const IndexedDeclaration* allDeclarations; PersistentSymbolTable::self().declarations(decl->qualifiedIdentifier(), count, allDeclarations); for(uint a = 0; a < count; ++a) { ++maxAllowedSteps; if(allDeclarations[a].data() && allDeclarations[a].data() != decl) { - ret += getInheriters(allDeclarations[a].data(), maxAllowedSteps, false); + ret += getInheritersInternal(allDeclarations[a].data(), maxAllowedSteps, false); } if(maxAllowedSteps == 0) return ret; } } return ret; } +QList DUChainUtils::getInheriters(const Declaration* decl, uint& maxAllowedSteps, bool collectVersions) +{ + auto inheriters = getInheritersInternal(decl, maxAllowedSteps, collectVersions); + + // remove duplicates + std::sort(inheriters.begin(), inheriters.end()); + inheriters.erase(std::unique(inheriters.begin(), inheriters.end()), inheriters.end()); + + return inheriters; +} + QList DUChainUtils::getOverriders(const Declaration* currentClass, const Declaration* overriddenDeclaration, uint& maxAllowedSteps) { QList ret; if(maxAllowedSteps == 0) return ret; if(currentClass != overriddenDeclaration->context()->owner() && currentClass->internalContext()) ret += currentClass->internalContext()->findLocalDeclarations(overriddenDeclaration->identifier(), CursorInRevision::invalid(), currentClass->topContext(), overriddenDeclaration->abstractType()); foreach(Declaration* inheriter, getInheriters(currentClass, maxAllowedSteps)) ret += getOverriders(inheriter, overriddenDeclaration, maxAllowedSteps); return ret; } static bool hasUse(DUContext* context, int usedDeclarationIndex) { if(usedDeclarationIndex == std::numeric_limits::max()) return false; for(int a = 0; a < context->usesCount(); ++a) if(context->uses()[a].m_declarationIndex == usedDeclarationIndex) return true; foreach(DUContext* child, context->childContexts()) if(hasUse(child, usedDeclarationIndex)) return true; return false; } bool DUChainUtils::contextHasUse(DUContext* context, Declaration* declaration) { return hasUse(context, context->topContext()->indexForUsedDeclaration(declaration, false)); } static uint countUses(DUContext* context, int usedDeclarationIndex) { if(usedDeclarationIndex == std::numeric_limits::max()) return 0; uint ret = 0; for(int a = 0; a < context->usesCount(); ++a) if(context->uses()[a].m_declarationIndex == usedDeclarationIndex) ++ret; foreach(DUContext* child, context->childContexts()) ret += countUses(child, usedDeclarationIndex); return ret; } uint DUChainUtils::contextCountUses(DUContext* context, Declaration* declaration) { return countUses(context, context->topContext()->indexForUsedDeclaration(declaration, false)); } Declaration* DUChainUtils::getOverridden(const Declaration* decl) { const ClassFunctionDeclaration* classFunDecl = dynamic_cast(decl); if(!classFunDecl || !classFunDecl->isVirtual()) return 0; QList decls; foreach(const DUContext::Import &import, decl->context()->importedParentContexts()) { DUContext* ctx = import.context(decl->topContext()); if(ctx) decls += ctx->findDeclarations(QualifiedIdentifier(decl->identifier()), CursorInRevision::invalid(), decl->abstractType(), decl->topContext(), DUContext::DontSearchInParent); } foreach(Declaration* found, decls) { const ClassFunctionDeclaration* foundClassFunDecl = dynamic_cast(found); if(foundClassFunDecl && foundClassFunDecl->isVirtual()) return found; } return 0; } DUContext* DUChainUtils::getFunctionContext(Declaration* decl) { DUContext* functionContext = decl->internalContext(); if(functionContext && functionContext->type() != DUContext::Function) { foreach(const DUContext::Import& import, functionContext->importedParentContexts()) { DUContext* ctx = import.context(decl->topContext()); if(ctx && ctx->type() == DUContext::Function) functionContext = ctx; } } if(functionContext && functionContext->type() == DUContext::Function) return functionContext; return 0; } diff --git a/language/duchain/ducontext.h b/language/duchain/ducontext.h index a6313cd65a..c5171fc433 100644 --- a/language/duchain/ducontext.h +++ b/language/duchain/ducontext.h @@ -1,951 +1,951 @@ /* This file is part of KDevelop Copyright 2006 Hamish Rodda Copyright 2007-2009 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. */ #ifndef KDEVPLATFORM_DUCONTEXT_H #define KDEVPLATFORM_DUCONTEXT_H #include #include #include #include #include #include "identifier.h" #include "duchainbase.h" #include "types/abstracttype.h" #include "duchainpointer.h" #include "declarationid.h" #include "indexedducontext.h" class QWidget; namespace KDevelop { class Declaration; class DUChain; class Use; class TopDUContext; class DUContext; class DUContextData; class KDEVPLATFORMLANGUAGE_EXPORT DUChainVisitor { public: virtual void visit(DUContext* context) = 0; virtual void visit(Declaration* declaration) = 0; virtual ~DUChainVisitor(); }; typedef DUChainPointer DUContextPointer; /** * A single context in source code, represented as a node in a * directed acyclic graph. * * Access to context objects must be serialised by holding the * chain lock, ie. DUChain::lock(). * * NOTE: A du-context can be freely edited as long as it's parent-context is zero. * In the moment the parent-context is set, the context may only be edited when it * is allowed to edited it's top-level context(@see TopLevelContext::inDUChain() * * @todo change child relationships to a linked list within the context? */ class KDEVPLATFORMLANGUAGE_EXPORT DUContext : public DUChainBase { friend class Use; friend class Declaration; friend class DeclarationData; friend class DUContextData; friend class DUContextDynamicData; friend class Definition; friend class VisibleDeclarationIterator; public: /** * Constructor. No convenience methods, as the initialisation order is important, * * @param anonymous Whether the context should be added as an anonymous context to the parent. That way the context can never be found through any of the parent's member-functions. * * If the parent is in the symbol table and the context is not anonymous, it will also be added to the symbol table. You nead a write-lock to the DUChain then */ explicit DUContext(const RangeInRevision& range, DUContext* parent = 0, bool anonymous = false); explicit DUContext(DUContextData&); /** * Destructor. Will delete all child contexts which are defined within * the same file as this context. */ - virtual ~DUContext(); + ~DUContext() override; enum ContextType : quint8 { Global /**< A context that declares functions, namespaces or classes */, Namespace /**< A context that declares namespace members */, Class /**< A context that declares class members */, Function /**< A context that declares function-arguments */, Template /**< A context that declares template-parameters */, Enum /**< A context that contains a list of enumerators */, Helper /**< A helper context. This context is treated specially during search: * when searching within the imports of a context, and that context's parent * is a context of type DUContext::Helper, then the upwards search is continued * into that helper(The decision happens in shouldSearchInParent) */, Other /**< Represents executable code, like for example within a compound-statement */ }; enum SearchFlag { NoSearchFlags = 0 /**< Searching for everything */, InImportedParentContext = 1 /**< Internal, do not use from outside */, OnlyContainerTypes = 2 /**< Not implemented yet */, DontSearchInParent = 4 /**< IF this flag is set, findDeclarations(..) will not search for the identifier in parent-contexts(which does not include imported parent-contexts) */, NoUndefinedTemplateParams = 8 /**< For languages that support templates(like C++). If this is set, the search should fail as soon as undefined template-parameters are involved. */, DirectQualifiedLookup = 16 /**< When this flag is used, the searched qualified identifier should NOT be split up into it's components and looked up one by one. Currently only plays a role in C++ specific parts. */, NoFiltering = 32 /**< Should be set when no filtering at all is wished, not even filtering that is natural for the underlying language(For example in C++, constructors are filtered out be default) */, OnlyFunctions = 64 /**< When this is given, only function-declarations are returned. In case of C++, this also means that constructors can be retrieved, while normally they are filtered out. */, NoImportsCheck = 128 /**< With this parameter, a global search will return all matching items, from all contexts, not only from imported ones. */, NoSelfLookUp = 256 /**< With this parameter, the special-treatment during search that allows finding the context-class by its name is disabled. */, DontResolveAliases = 512 /**< Disables the resolution of alias declarations in the returned list*/, LastSearchFlag = 1024 }; Q_DECLARE_FLAGS(SearchFlags, SearchFlag) ContextType type() const; void setType(ContextType type); /** * If this context was opened by a declaration or definition, this returns that item. * * The returned declaration/definition will have this context set as @c internalContext() */ Declaration* owner() const; /** * Sets the declaration/definition, and also updates it's internal context (they are strictly paired together). * * The declaration has to be part of the same top-context. */ void setOwner(Declaration* decl); /** * Calculate the depth of this context, from the top level context in the file. */ int depth() const; /** * Find the top context. */ - virtual TopDUContext* topContext() const override; + TopDUContext* topContext() const override; /** * Visits all duchain objects in the whole duchain. * * Classes that hold a unique link to duchain objects like instantiations * have to pass the visitor over to those classes. * */ virtual void visit(DUChainVisitor& visitor); /** * Find the context which most specifically covers @a position. * * The search is recursive, so the most specific context is found. * * @param includeRightBorder When this is true, contexts will also be found that * have the position on their right border. * * @warning This uses the ranges in the local revision of the document (at last parsing time). * Use DUChainBase::transformToLocalRevision to transform the cursor into that revision first. */ DUContext* findContextAt(const CursorInRevision& position, bool includeBorders = false) const; /** * Find a child declaration that has a rang that covers the given @a position. * * The search is local, not recursive. * * @warning This uses the ranges in the local revision of the document (at last parsing time). * Use DUChainBase::transformToLocalRevision to transform the cursor into that revision first. */ Declaration* findDeclarationAt(const CursorInRevision& position) const; /** * Find the context which most specifically covers @a range. * * @warning This uses the ranges in the local revision of the document (at last parsing time). * Use DUChainBase::transformToLocalRevision to transform the cursor into that revision first. */ DUContext* findContextIncluding(const RangeInRevision& range) const; /** * Calculate the fully qualified scope identifier. */ QualifiedIdentifier scopeIdentifier(bool includeClasses = false) const; /** * Returns true if this context has the same scope identifier as the given one. * * @note This is much more efficient than computing the identifiers through @c scopeIdentifier(..) * and comparing them */ bool equalScopeIdentifier(const DUContext* rhs) const; /** * Scope identifier, used to qualify the identifiers occurring in each context. * * This is the part relative to the parent context. */ QualifiedIdentifier localScopeIdentifier() const; /** * Same as @c localScopeIdentifier(), but faster. */ IndexedQualifiedIdentifier indexedLocalScopeIdentifier() const; /** * Scope identifier, used to qualify the identifiers occurring in each context * This must not be called once this context has children. */ void setLocalScopeIdentifier(const QualifiedIdentifier& identifier); /** * Returns whether this context is listed in the symbol table (Namespaces and classes) */ bool inSymbolTable() const; /** * Move this object into/out of the symbol table. * * @note You need to have a duchain write lock, unless this is a TopDUContext. */ void setInSymbolTable(bool inSymbolTable); /** * Returns the immediate parent context of this context. */ DUContext* parentContext() const; /** * Represents an imported parent context. */ struct KDEVPLATFORMLANGUAGE_EXPORT Import { /** * @note DUChain must be read-locked when this is called */ Import(DUContext* context, const DUContext* importer, const CursorInRevision& position = CursorInRevision::invalid()); Import() : position(CursorInRevision::invalid()) { } Import(const DeclarationId& id, const CursorInRevision& position = CursorInRevision::invalid()); bool operator==(const Import& rhs) const { return m_context == rhs.m_context && m_declaration == rhs.m_declaration; } /** * @param topContext The top-context from where to start searching. * This is important to find the correct imports * in the case of templates or similar structures. */ DUContext* context(const TopDUContext* topContext, bool instantiateIfRequired = true) const; /** * Returns the top-context index, if this import is not a specialization import. */ uint topContextIndex() const { return m_context.topContextIndex(); } IndexedDUContext indexedContext() const { return m_context; } /** * Returns true if this import is direct. * * That is, the import is not referred to by its identifier, * but rather directly by its index. */ bool isDirect() const; /** * If this import is indirect, returns the imported declaration-id */ DeclarationId indirectDeclarationId() const { return m_declaration; } CursorInRevision position; private: //Either we store m_declaration, or m_context. That way we can resolve specialized contexts. ///@todo Compress using union DeclarationId m_declaration; IndexedDUContext m_context; }; /** * Returns the list of imported parent contexts for this context. * * @warning The list may contain objects that are not valid any more, * i.e. data() returns zero, @see addImportedParentContext) * @warning The import structure may contain loops if this is a TopDUContext, * so be careful when traversing the tree. * @note This is expensive. */ virtual QVector importedParentContexts() const; /** * If the given context is directly imported into this one, and * @c addImportedParentContext(..) was called with a valid cursor, * this will return that position. Otherwise an invalid cursor is returned. */ virtual CursorInRevision importPosition(const DUContext* target) const; /** * Returns true if this context imports @param origin at any depth, else false. */ virtual bool imports(const DUContext* origin, const CursorInRevision& position = CursorInRevision::invalid()) const; /** * Adds an imported context. * * @param anonymous If this is true, the import will not be registered at the imported context. * This allows du-chain contexts importing without having a write-lock. * @param position Position where the context is imported. This is mainly important in C++ with included files. * * If the context is already imported, only the position is updated. * * @note Be sure to have set the text location first, so that the chain is sorted correctly. */ virtual void addImportedParentContext(DUContext* context, const CursorInRevision& position = CursorInRevision::invalid(), bool anonymous = false, bool temporary = false); /** * Adds an imported context, which may be indirect. * * @warning This is only allowed if this context is _NOT_ a top-context. * @warning When using this mechanism, this context will not be registered as importer to the other one. * @warning The given import _must_ be indirect. * * @return true if the import was already imported before, else false. */ bool addIndirectImport(const DUContext::Import& import); /** * Removes a child context. */ virtual void removeImportedParentContext(DUContext* context); /** * Clear all imported parent contexts. */ virtual void clearImportedParentContexts(); /** * If this is set to true, all declarations that are added to this context * will also be visible in the parent-context. * * They will be visible in the parent using @c findDeclarations(...) and * @c findLocalDeclarations(...), but will not be in the list of @c localDeclarations(...). */ void setPropagateDeclarations(bool propagate); bool isPropagateDeclarations() const; /** * Returns the list of contexts importing this context. * * @note Very expensive, since the importers top-contexts need to be loaded. */ virtual QVector importers() const; /** * Returns the list of indexed importers. * * Cheap, because nothing needs to be loaded. */ KDevVarLengthArray indexedImporters() const; /** * Returns the list of immediate child contexts for this context. * * @note This is expensive. */ QVector childContexts() const; /** * Clears and deletes all child contexts recursively. * * This will not cross file boundaries. */ void deleteChildContextsRecursively(); /** * Resort the child contexts by their range. * * You must call this when you manually change the range of child contexts in a way * that could break the internal range sorting. */ void resortChildContexts(); /** * Returns true if this declaration is accessible through the du-chain, * and thus cannot be edited without a du-chain write lock */ virtual bool inDUChain() const; /** * Retrieve the context which is specialized with the given * @a specialization as seen from the given @a topContext. * * @param specialization the specialization index (see DeclarationId) * @param topContext the top context representing the perspective from which to specialize. * if @p topContext is zero, only already existing specializations are returned, * and if none exists, zero is returned. * @param upDistance upwards distance in the context-structure of the * given specialization-info. This allows specializing children. */ virtual DUContext* specialize(const IndexedInstantiationInformation& specialization, const TopDUContext* topContext, int upDistance = 0); /** * Searches for and returns a declaration with a given @a identifier in this context, which * is currently active at the given text @a position, with the given type @a dataType. * In fact, only items are returned that are declared BEFORE that position. * * @param identifier the identifier of the definition to search for * @param location the text position to search for * @param topContext the top-context from where a completion is triggered. * This is needed so delayed types (templates in C++) can be resolved in the correct context. * @param type the type to match, or null for no type matching. * * @returns the requested declaration if one was found, otherwise null. * * @warning this may return declarations which are not in this tree, you may need to lock them too... */ QList findDeclarations(const QualifiedIdentifier& identifier, const CursorInRevision& position = CursorInRevision::invalid(), const AbstractType::Ptr& dataType = AbstractType::Ptr(), const TopDUContext* topContext = 0, SearchFlags flags = NoSearchFlags) const; /** * Searches for and returns a declaration with a given @a identifier in this context, which * is currently active at the given text @a position. * * @param identifier the identifier of the definition to search for * @param topContext the top-context from where a completion is triggered. * This is needed so delayed types(templates in C++) can be resolved in the correct context. * @param location the text position to search for * * @returns the requested declaration if one was found, otherwise null. * * @warning this may return declarations which are not in this tree, you may need to lock them too... * * @overload */ QList findDeclarations(const IndexedIdentifier& identifier, const CursorInRevision& position = CursorInRevision::invalid(), const TopDUContext* topContext = 0, SearchFlags flags = NoSearchFlags) const; /** * Prefer the version above for speed reasons. */ QList findDeclarations(const Identifier& identifier, const CursorInRevision& position = CursorInRevision::invalid(), const TopDUContext* topContext = 0, SearchFlags flags = NoSearchFlags) const; /** * Returns the type of any @a identifier defined in this context, or * null if one is not found. * * Does not search imported parent-contexts(like base-classes). */ QList findLocalDeclarations(const IndexedIdentifier& identifier, const CursorInRevision& position = CursorInRevision::invalid(), const TopDUContext* topContext = 0, const AbstractType::Ptr& dataType = AbstractType::Ptr(), SearchFlags flags = NoSearchFlags) const; /** * Prefer the version above for speed reasons. */ QList findLocalDeclarations(const Identifier& identifier, const CursorInRevision& position = CursorInRevision::invalid(), const TopDUContext* topContext = 0, const AbstractType::Ptr& dataType = AbstractType::Ptr(), SearchFlags flags = NoSearchFlags) const; /** * Clears all local declarations. * * Does not delete the declaration; the caller assumes ownership. */ QVector clearLocalDeclarations(); /** * Clears all local declarations. * * Deletes these declarations, as the context has ownership. */ void deleteLocalDeclarations(); /** * Returns all local declarations * * @param source A source-context that is needed to instantiate template-declarations in some cases. * If it is zero, that signalizes that missing members should not be instantiated. */ virtual QVector localDeclarations(const TopDUContext* source = 0) const; /** * Resort the local declarations by their range. * * You must call this when you manually change the range of declarations in a way * that could break the internal range sorting. */ void resortLocalDeclarations(); /** * Searches for the most specific context for the given cursor @a position in the given @a url. * * @param location the text position to search for * @param parent the parent context to search from (this is mostly an internal detail, but if you only * want to search in a subbranch of the chain, you may specify the parent here) * * @returns the requested context if one was found, otherwise null. */ DUContext* findContext(const CursorInRevision& position, DUContext* parent = 0) const; /** * Iterates the tree to see if the provided @a context is a subcontext of this context. * * @returns true if @a context is a subcontext, otherwise false. */ bool parentContextOf(DUContext* context) const; /** * Return a list of all reachable declarations for a given cursor @a position in a given @a url. * * @param location the text position to search for * @param topContext the top-context from where a completion is triggered. * This is needed so delayed types(templates in C++) can be resolved * in the correct context. * @param searchInParents should declarations from parent-contexts be listed? * If false, only declarations from this and imported contexts will be returned. * * The returned declarations are paired together with their inheritance-depth, * which is the count of steps to into other contexts that were needed to find the declaration. * Declarations reached through a namespace- or global-context are offsetted by 1000. * * This also includes Declarations from sub-contexts that were propagated upwards * using @c setPropagateDeclarations(true). * * @returns the requested declarations, if any were active at that location. * Declarations propagated into this context(@c setPropagateDeclarations) are included. */ QList< QPair > allDeclarations(const CursorInRevision& position, const TopDUContext* topContext, bool searchInParents = true) const; /** * Delete and remove all slaves (uses, declarations, definitions, contexts) that are not in the given set. */ void cleanIfNotEncountered(const QSet& encountered); /** * Uses: * A "Use" represents any position in a document where a Declaration is used literally. * For efficiency, since there can be many many uses, they are managed efficiently by * TopDUContext and DUContext. In TopDUContext, the used declarations are registered * and assigned a "Declaration-Index" while calling TopDUContext::indexForUsedDeclaration. * From such a declaration-index, the declaration can be retrieved back by calling * @c TopDUContext::usedDeclarationForIndex. * * The actual uses are stored within DUContext, where each use consists of a range and * the declaration-index of the used declaration. * */ /** * Return a vector of all uses which occur in this context. * * To get the actual declarations, use @c TopDUContext::usedDeclarationForIndex(..) * with the declarationIndex. */ const Use* uses() const; /** * Returns the count of uses that can be accessed through @c uses() */ int usesCount() const; /** * Determines whether the given declaration has uses or not */ static bool declarationHasUses(Declaration* decl); /** * Find the use which encompasses @a position, if one exists. * @return The local index of the use, or -1 */ int findUseAt(const CursorInRevision& position) const; /** * @note The change must not break the ordering */ void changeUseRange(int useIndex, const RangeInRevision& range); /** * Assigns the declaration represented by @param declarationIndex * to the use with index @param useIndex. */ void setUseDeclaration(int useIndex, int declarationIndex); /** * Creates a new use of the declaration given through @param declarationIndex. * The index must be retrieved through @c TopDUContext::indexForUsedDeclaration(..). * * @param range The range of the use * @param insertBefore A hint where in the vector of uses to insert the use. * Must be correct so the order is preserved(ordered by position), * or -1 to automatically choose the position. * * @return Local index of the created use */ int createUse(int declarationIndex, const RangeInRevision& range, int insertBefore = -1); /** * Deletes the use number @param index. * * @param index is the position in the vector of uses, not a used declaration index. */ void deleteUse(int index); /** * Clear and delete all uses in this context. */ virtual void deleteUses(); /** * Recursively delete all uses in this context and all its child-contexts */ virtual void deleteUsesRecursively(); /** * Can be specialized by languages to create a navigation/information-widget. * * Ideally, the widget would be based on @c KDevelop::QuickOpenEmbeddedWidgetInterface * for user-interaction within the quickopen list. * * The returned widget will be owned by the caller. * * @param decl A member-declaration of this context the navigation-widget should be created for. * Zero to create a widget for this context. * @param topContext Top-context from where the navigation-widget is triggered. * In C++, this is needed to resolve forward-declarations. * @param htmlPrefix Html-formatted text that should be prepended before any information shown by this widget * @param htmlSuffix Html-formatted text that should be appended to any information shown by this widget * * Can return zero which disables the navigation widget. * * If you setProperty("DoNotCloseOnCursorMove", true) on the widget returned, * then the widget will not close when the cursor moves in the document, which * enables you to change the document contents from the widget without immediately closing the widget. */ virtual QWidget* createNavigationWidget(Declaration* decl = 0, TopDUContext* topContext = 0, const QString& htmlPrefix = QString(), const QString& htmlSuffix = QString()) const; enum { Identity = 2 }; /** * Represents multiple qualified identifiers in a way that is better * to manipulate and allows applying namespace-aliases or -imports easily. * * A SearchItem generally represents a tree of identifiers, and represents * all the qualified identifiers that can be constructed by walking * along the tree starting at an arbitrary root-node into the depth using the "next" pointers. * * The insertion order in the hierarchy determines the order of the represented list. */ struct KDEVPLATFORMLANGUAGE_EXPORT SearchItem : public QSharedData { typedef QExplicitlySharedDataPointer Ptr; typedef KDevVarLengthArray PtrList; /** * Constructs a representation of the given @param id qualified identifier, * starting at its index @param start. * * @param nextItem is set as next item to the last item in the chain */ SearchItem(const QualifiedIdentifier& id, const Ptr& nextItem = Ptr(), int start = 0); /** * Constructs a representation of the given @param id qualified identifier, * starting at its index @param start. * * @param nextItem is set as next item to the last item in the chain */ SearchItem(const QualifiedIdentifier& id, const PtrList& nextItems, int start = 0); SearchItem(bool explicitlyGlobal, const IndexedIdentifier& id, const PtrList& nextItems); SearchItem(bool explicitlyGlobal, const IndexedIdentifier& id, const Ptr& nextItem); bool isEmpty() const; bool hasNext() const; /** * Appends the given item to every item that can be reached from this item, * and not only to the end items. * * The effect to search is that the given item is searched with all prefixes * contained in this earch-item prepended. * * @warning This changes all contained sub-nodes, but they can be shared with * other SearchItem trees. You should not use this on SearchItem trees * that have shared nodes with other trees. * * @note These functions ignore explicitly global items. */ void addToEachNode(const Ptr& item); void addToEachNode(const PtrList& items); /** * Returns true if the given identifier matches one of the identifiers * represented by this SearchItem. Does not respect the explicitlyGlobal flag */ bool match(const QualifiedIdentifier& id, int offset = 0) const; /** * @note expensive */ QList toList(const QualifiedIdentifier& prefix = QualifiedIdentifier()) const; void addNext(const Ptr& other); bool isExplicitlyGlobal; IndexedIdentifier identifier; PtrList next; }; ///@todo Should be protected, moved here temporarily until I have figured ///out why the gcc 4.1.3 fails in cppducontext.h:212, which should work (within kdevelop) /// Declaration search implementation /** * This is a more complex interface to the declaration search engine. * * Always prefer @c findDeclarations(..) when possible. * * Advantage of this interface: * - You can search multiple identifiers at one time. * However, those should be aliased identifiers for one single item, because * search might stop as soon as one item is found. * - The source top-context is needed to correctly resolve template-parameters * * @param position A valid position, if in doubt use textRange().end() * * @warning @p position must be valid! * * @param depth Depth of the search in parents. This is used to prevent endless * recursions in endless import loops. * * * @return whether the search was successful. If it is false, it had to be stopped * for special reasons (like some flags) */ typedef QList DeclarationList; virtual bool findDeclarationsInternal(const SearchItem::PtrList& identifiers, const CursorInRevision& position, const AbstractType::Ptr& dataType, DeclarationList& ret, const TopDUContext* source, SearchFlags flags, uint depth ) const; /** * Returns the qualified identifier @p id with all aliases (for example namespace imports) applied * * @example: If the namespace 'Foo' is imported, and id is 'Bar', * then the returned list is 'Bar' and 'Foo::Bar' */ QList fullyApplyAliases(const QualifiedIdentifier& id, const TopDUContext* source) const; protected: /** * After one scope was searched, this function is asked whether more * results should be collected. Override it, for example to collect overloaded functions. * * The default-implementation returns true as soon as decls is not empty. */ virtual bool foundEnough( const DeclarationList& decls , SearchFlags flags ) const; /** * Merges definitions and their inheritance-depth up all branches of the * definition-use chain into one hash. * * This includes declarations propagated from sub-contexts. * * @param hadUrls is used to count together all contexts that already were * visited, so they are not visited again. */ virtual void mergeDeclarationsInternal(QList< QPair >& definitions, const CursorInRevision& position, QHash& hadContexts, const TopDUContext* source, bool searchInParents = true, int currentDepth = 0) const; void findLocalDeclarationsInternal(const Identifier& identifier, const CursorInRevision & position, const AbstractType::Ptr& dataType, DeclarationList& ret, const TopDUContext* source, SearchFlags flags ) const; virtual void findLocalDeclarationsInternal(const IndexedIdentifier& identifier, const CursorInRevision & position, const AbstractType::Ptr& dataType, DeclarationList& ret, const TopDUContext* source, SearchFlags flags ) const; /** * Applies namespace-imports and namespace-aliases and returns * possible absolute identifiers that need to be searched. * * @param targetIdentifiers will be filled with all identifiers that should * be searched for, instead of identifier. * @param onlyImports if this is true, namespace-aliases will not be respected, * but only imports. This is faster. */ void applyAliases(const SearchItem::PtrList& identifiers, SearchItem::PtrList& targetIdentifiers, const CursorInRevision& position, bool canBeNamespace, bool onlyImports = false) const; /** * Applies the aliases that need to be applied when moving the search * from this context up to the parent-context. * * The default-implementation adds a set of identifiers with the own local * identifier prefixed, if this is a namespace. * * For C++, this is needed when searching out of a namespace, so the item * can be found within that namespace in another place. */ virtual void applyUpwardsAliases(SearchItem::PtrList& identifiers, const TopDUContext* source) const; DUContext(DUContextData& dd, const RangeInRevision& range, DUContext* parent = 0, bool anonymous = false); /** * Just uses the data from the given context. Doesn't copy or change anything, * and the data will not be deleted on this contexts destruction. */ DUContext(DUContext& useDataFrom); /** * Whether this context, or any of its parent contexts, has been inserte * anonymously into the du-chain * * @see DUContext::DUContext */ bool isAnonymous() const; /** * This is called whenever the search needs to do the decision whether it * should be continued in the parent context. * * It is not called when the DontSearchInParent flag is set. Else this should * be overridden to do language-specific logic. * * The default implementation returns false if the flag InImportedParentContext is set. */ virtual bool shouldSearchInParent(SearchFlags flags) const; private: void rebuildDynamicData(DUContext* parent, uint ownIndex) override; friend class TopDUContext; friend class IndexedDUContext; friend class LocalIndexedDUContext; friend class TopDUContextDynamicData; DUCHAIN_DECLARE_DATA(DUContext) class DUContextDynamicData* m_dynamicData; }; /** * This is the identifier that can be used to search namespace-import declarations, * and should be used to store namespace-imports. * * It is stored statically for performance-reasons, so it doesn't need to be * constructed every time it is used. * * @see NamespaceAliasDeclaration. */ KDEVPLATFORMLANGUAGE_EXPORT const Identifier& globalImportIdentifier(); /** * This is the identifier that can be used to search namespace-alias declarations. * * It is stored statically for performance-reasons, so it doesn't need to be * constructed every time it is used. * * @see NamespaceAliasDeclaration. */ KDEVPLATFORMLANGUAGE_EXPORT const Identifier& globalAliasIdentifier(); /** * This is the identifier that can be used to search namespace-import declarations, * and should be used to store namespace-imports. * * It is stored statically for performance-reasons, so it doesn't need to be * constructed every time it is used. * * @see NamespaceAliasDeclaration. */ KDEVPLATFORMLANGUAGE_EXPORT const IndexedIdentifier& globalIndexedImportIdentifier(); /** * This is the identifier that can be used to search namespace-alias declarations. * * It is stored statically for performance-reasons, so it doesn't need to be * constructed every time it is used. * * @see NamespaceAliasDeclaration. */ KDEVPLATFORMLANGUAGE_EXPORT const IndexedIdentifier& globalIndexedAliasIdentifier(); /** * Collects all uses of the given @param declarationIndex */ KDEVPLATFORMLANGUAGE_EXPORT QList allUses(DUContext* context, int declarationIndex, bool noEmptyRanges = false); } Q_DECLARE_TYPEINFO(KDevelop::DUContext::Import, Q_MOVABLE_TYPE); KDEVPLATFORMLANGUAGE_EXPORT QDebug operator<<(QDebug dbg, const KDevelop::DUContext::Import& import); #endif // KDEVPLATFORM_DUCONTEXT_H diff --git a/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp b/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp index 71d5296528..c2983d8c76 100644 --- a/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp +++ b/language/duchain/navigation/abstractdeclarationnavigationcontext.cpp @@ -1,731 +1,754 @@ /* Copyright 2007 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 "abstractdeclarationnavigationcontext.h" #include #include #include "../functiondeclaration.h" #include "../functiondefinition.h" #include "../classfunctiondeclaration.h" #include "../namespacealiasdeclaration.h" #include "../forwarddeclaration.h" #include "../types/enumeratortype.h" #include "../types/enumerationtype.h" #include "../types/functiontype.h" #include "../duchainutils.h" #include "../types/pointertype.h" #include "../types/referencetype.h" #include "../types/typeutils.h" #include "../types/typesystem.h" #include "../persistentsymboltable.h" #include "util/debug.h" #include #include #include #include #include namespace KDevelop { -AbstractDeclarationNavigationContext::AbstractDeclarationNavigationContext( DeclarationPointer decl, KDevelop::TopDUContextPointer topContext, AbstractNavigationContext* previousContext) + +AbstractDeclarationNavigationContext::AbstractDeclarationNavigationContext( DeclarationPointer decl, TopDUContextPointer topContext, AbstractNavigationContext* previousContext) : AbstractNavigationContext((topContext ? topContext : TopDUContextPointer(decl ? decl->topContext() : 0)), previousContext), m_declaration(decl), m_fullBackwardSearch(false) { //Jump from definition to declaration if possible FunctionDefinition* definition = dynamic_cast(m_declaration.data()); if(definition && definition->declaration()) m_declaration = DeclarationPointer(definition->declaration()); } QString AbstractDeclarationNavigationContext::name() const { if(m_declaration.data()) return prettyQualifiedIdentifier(m_declaration).toString(); else return declarationName(m_declaration); } QString AbstractDeclarationNavigationContext::html(bool shorten) { clear(); m_shorten = shorten; modifyHtml() += "

" + fontSizePrefix(shorten); addExternalHtml(m_prefix); if(!m_declaration.data()) { modifyHtml() += i18n("
lost declaration
"); return currentHtml(); } if( m_previousContext ) { QString link = createLink( m_previousContext->name(), m_previousContext->name(), NavigationAction(m_previousContext) ); modifyHtml() += navigationHighlight(i18n("Back to %1
", link)); } QExplicitlySharedDataPointer doc; if( !shorten ) { doc = ICore::self()->documentationController()->documentationForDeclaration(m_declaration.data()); const AbstractFunctionDeclaration* function = dynamic_cast(m_declaration.data()); if( function ) { htmlFunction(); } else if( m_declaration->isTypeAlias() || m_declaration->type() || m_declaration->kind() == Declaration::Instance ) { if( m_declaration->isTypeAlias() ) modifyHtml() += importantHighlight("typedef "); if(m_declaration->type()) modifyHtml() += i18n("enumerator "); AbstractType::Ptr useType = m_declaration->abstractType(); if(m_declaration->isTypeAlias()) { //Do not show the own name as type of typedefs if(useType.cast()) useType = useType.cast()->type(); } eventuallyMakeTypeLinks( useType ); modifyHtml() += ' ' + identifierHighlight(declarationName(m_declaration).toHtmlEscaped(), m_declaration); if(auto integralType = m_declaration->type()) { const QString plainValue = integralType->valueAsString(); if (!plainValue.isEmpty()) { modifyHtml() += QStringLiteral(" = ") + plainValue; } } modifyHtml() += "
"; }else{ if( m_declaration->kind() == Declaration::Type && m_declaration->abstractType().cast() ) { htmlClass(); } if ( m_declaration->kind() == Declaration::Namespace ) { modifyHtml() += i18n("namespace %1 ", identifierHighlight(m_declaration->qualifiedIdentifier().toString().toHtmlEscaped(), m_declaration)); } else if ( m_declaration->kind() == Declaration::NamespaceAlias ) { modifyHtml() += identifierHighlight(declarationName(m_declaration).toHtmlEscaped(), m_declaration); } if(m_declaration->type()) { EnumerationType::Ptr enumeration = m_declaration->type(); modifyHtml() += i18n("enumeration %1 ", identifierHighlight(m_declaration->identifier().toString().toHtmlEscaped(), m_declaration)); } if(m_declaration->isForwardDeclaration()) { ForwardDeclaration* forwardDec = static_cast(m_declaration.data()); Declaration* resolved = forwardDec->resolve(m_topContext.data()); if(resolved) { modifyHtml() += i18n("(resolved forward-declaration: "); - makeLink(resolved->identifier().toString(), KDevelop::DeclarationPointer(resolved), NavigationAction::NavigateDeclaration ); + makeLink(resolved->identifier().toString(), DeclarationPointer(resolved), NavigationAction::NavigateDeclaration ); modifyHtml() += i18n(") "); }else{ modifyHtml() += i18n("(unresolved forward-declaration) "); QualifiedIdentifier id = forwardDec->qualifiedIdentifier(); uint count; const IndexedDeclaration* decls; PersistentSymbolTable::self().declarations(id, count, decls); for(uint a = 0; a < count; ++a) { if(decls[a].isValid() && !decls[a].data()->isForwardDeclaration()) { modifyHtml() += "
"; - makeLink(i18n("possible resolution from"), KDevelop::DeclarationPointer(decls[a].data()), NavigationAction::NavigateDeclaration); + makeLink(i18n("possible resolution from"), DeclarationPointer(decls[a].data()), NavigationAction::NavigateDeclaration); modifyHtml() += ' ' + decls[a].data()->url().str(); } } } } modifyHtml() += "
"; } }else{ AbstractType::Ptr showType = m_declaration->abstractType(); if(showType && showType.cast()) { showType = showType.cast()->returnType(); if(showType) modifyHtml() += labelHighlight(i18n("Returns: ")); }else if(showType) { modifyHtml() += labelHighlight(i18n("Type: ")); } if(showType) { eventuallyMakeTypeLinks(showType); modifyHtml() += " "; } } QualifiedIdentifier identifier = m_declaration->qualifiedIdentifier(); if( identifier.count() > 1 ) { if( m_declaration->context() && m_declaration->context()->owner() ) { Declaration* decl = m_declaration->context()->owner(); FunctionDefinition* definition = dynamic_cast(decl); if(definition && definition->declaration()) decl = definition->declaration(); if(decl->abstractType().cast()) modifyHtml() += labelHighlight(i18n("Enum: ")); else modifyHtml() += labelHighlight(i18n("Container: ")); makeLink( declarationName(DeclarationPointer(decl)), DeclarationPointer(decl), NavigationAction::NavigateDeclaration ); modifyHtml() += " "; } else { QualifiedIdentifier parent = identifier; parent.pop(); modifyHtml() += labelHighlight(i18n("Scope: %1 ", typeHighlight(parent.toString().toHtmlEscaped()))); } } if( shorten && !m_declaration->comment().isEmpty() ) { QString comment = QString::fromUtf8(m_declaration->comment()); if( comment.length() > 60 ) { comment.truncate(60); comment += "..."; } comment.replace('\n', " "); comment.replace("
", " "); comment.replace("
", " "); modifyHtml() += commentHighlight(comment.toHtmlEscaped()) + " "; } QString access = stringFromAccess(m_declaration); if( !access.isEmpty() ) modifyHtml() += labelHighlight(i18n("Access: %1 ", propertyHighlight(access.toHtmlEscaped()))); ///@todo Enumerations QString detailsHtml; QStringList details = declarationDetails(m_declaration); if( !details.isEmpty() ) { bool first = true; foreach( const QString &str, details ) { if( !first ) detailsHtml += ", "; first = false; detailsHtml += propertyHighlight(str); } } QString kind = declarationKind(m_declaration); if( !kind.isEmpty() ) { if( !detailsHtml.isEmpty() ) modifyHtml() += labelHighlight(i18n("Kind: %1 %2 ", importantHighlight(kind.toHtmlEscaped()), detailsHtml)); else modifyHtml() += labelHighlight(i18n("Kind: %1 ", importantHighlight(kind.toHtmlEscaped()))); } if (m_declaration->isDeprecated()) { modifyHtml() += labelHighlight(i18n("Status: %1 ", propertyHighlight(i18n("Deprecated")))); } modifyHtml() += "
"; if(!shorten) htmlAdditionalNavigation(); if( !shorten ) { if(dynamic_cast(m_declaration.data())) modifyHtml() += labelHighlight(i18n( "Def.: " )); else modifyHtml() += labelHighlight(i18n( "Decl.: " )); makeLink( QStringLiteral("%1 :%2").arg( m_declaration->url().toUrl().fileName() ).arg( m_declaration->rangeInCurrentRevision().start().line()+1 ), m_declaration, NavigationAction::JumpToSource ); modifyHtml() += " "; //modifyHtml() += "
"; if(!dynamic_cast(m_declaration.data())) { if( FunctionDefinition* definition = FunctionDefinition::definition(m_declaration.data()) ) { modifyHtml() += labelHighlight(i18n( " Def.: " )); makeLink( QStringLiteral("%1 :%2").arg( definition->url().toUrl().fileName() ).arg( definition->rangeInCurrentRevision().start().line()+1 ), DeclarationPointer(definition), NavigationAction::JumpToSource ); } } if( FunctionDefinition* definition = dynamic_cast(m_declaration.data()) ) { if(definition->declaration()) { modifyHtml() += labelHighlight(i18n( " Decl.: " )); makeLink( QStringLiteral("%1 :%2").arg( definition->declaration()->url().toUrl().fileName() ).arg( definition->declaration()->rangeInCurrentRevision().start().line()+1 ), DeclarationPointer(definition->declaration()), NavigationAction::JumpToSource ); } } modifyHtml() += " "; //The action name _must_ stay "show_uses", since that is also used from outside makeLink(i18n("Show uses"), "show_uses", NavigationAction(m_declaration, NavigationAction::NavigateUses)); } QByteArray declarationComment = m_declaration->comment(); if( !shorten && (!declarationComment.isEmpty() || doc) ) { modifyHtml() += "
"; if(doc) { QString comment = doc->description(); connect(doc.data(), &IDocumentation::descriptionChanged, this, &AbstractDeclarationNavigationContext::contentsChanged); if(!comment.isEmpty()) { modifyHtml() += "
" + commentHighlight(comment); } } QString comment = QString::fromUtf8(declarationComment); if(!comment.isEmpty()) { // if the first paragraph does not contain a tag, we assume that this is a plain-text comment if (!Qt::mightBeRichText(comment)) { // still might contain extra html tags for line breaks (this is the case for doxygen-style comments sometimes) // let's protect them from being removed completely comment.replace(QRegExp("
"), "\n"); comment = comment.toHtmlEscaped(); comment.replace('\n', "
"); //Replicate newlines in html } modifyHtml() += commentHighlight(comment); modifyHtml() += "
"; } } if(!shorten && doc) { modifyHtml() += "
" + i18n("Show documentation for "); - makeLink( prettyQualifiedIdentifier(m_declaration).toString(), m_declaration, NavigationAction::ShowDocumentation ); + makeLink(prettyQualifiedName(m_declaration), + m_declaration, NavigationAction::ShowDocumentation); } //modifyHtml() += "
"; addExternalHtml(m_suffix); modifyHtml() += fontSizeSuffix(shorten) + "

"; return currentHtml(); } -KDevelop::AbstractType::Ptr AbstractDeclarationNavigationContext::typeToShow(KDevelop::AbstractType::Ptr type) { +AbstractType::Ptr AbstractDeclarationNavigationContext::typeToShow(AbstractType::Ptr type) { return type; } void AbstractDeclarationNavigationContext::htmlFunction() { const AbstractFunctionDeclaration* function = dynamic_cast(m_declaration.data()); Q_ASSERT(function); const ClassFunctionDeclaration* classFunDecl = dynamic_cast(m_declaration.data()); const FunctionType::Ptr type = m_declaration->abstractType().cast(); if( !type ) { modifyHtml() += errorHighlight("Invalid type
"); return; } if( !classFunDecl || (!classFunDecl->isConstructor() && !classFunDecl->isDestructor()) ) { // only print return type for global functions and non-ctor/dtor methods eventuallyMakeTypeLinks( type->returnType() ); } modifyHtml() += ' ' + identifierHighlight(prettyIdentifier(m_declaration).toString().toHtmlEscaped(), m_declaration); if( type->indexedArgumentsSize() == 0 ) { modifyHtml() += "()"; } else { modifyHtml() += "( "; bool first = true; int firstDefaultParam = type->indexedArgumentsSize() - function->defaultParametersSize(); int currentArgNum = 0; QVector decls; - if (KDevelop::DUContext* argumentContext = DUChainUtils::getArgumentContext(m_declaration.data())) { + if (DUContext* argumentContext = DUChainUtils::getArgumentContext(m_declaration.data())) { decls = argumentContext->localDeclarations(m_topContext.data()); } foreach(const AbstractType::Ptr& argType, type->arguments()) { if( !first ) modifyHtml() += ", "; first = false; eventuallyMakeTypeLinks( argType ); if (currentArgNum < decls.size()) { modifyHtml() += ' ' + identifierHighlight(decls[currentArgNum]->identifier().toString().toHtmlEscaped(), m_declaration); } if( currentArgNum >= firstDefaultParam ) modifyHtml() += " = " + function->defaultParameters()[ currentArgNum - firstDefaultParam ].str().toHtmlEscaped(); ++currentArgNum; } modifyHtml() += " )"; } modifyHtml() += "
"; } Identifier AbstractDeclarationNavigationContext::prettyIdentifier(DeclarationPointer decl) const { Identifier ret; QualifiedIdentifier q = prettyQualifiedIdentifier(decl); if(!q.isEmpty()) ret = q.last(); return ret; } QualifiedIdentifier AbstractDeclarationNavigationContext::prettyQualifiedIdentifier(DeclarationPointer decl) const { if(decl) return decl->qualifiedIdentifier(); else return QualifiedIdentifier(); } + +QString AbstractDeclarationNavigationContext::prettyQualifiedName(DeclarationPointer decl) const +{ + const auto qid = prettyQualifiedIdentifier(decl); + if (qid.isEmpty()) { + return i18nc("An anonymous declaration (class, function, etc.)", ""); + } + + return qid.toString(); +} + void AbstractDeclarationNavigationContext::htmlAdditionalNavigation() { ///Check if the function overrides or hides another one const ClassFunctionDeclaration* classFunDecl = dynamic_cast(m_declaration.data()); if(classFunDecl) { Declaration* overridden = DUChainUtils::getOverridden(m_declaration.data()); if(overridden) { modifyHtml() += i18n("Overrides a "); - makeLink(i18n("function"), QStringLiteral("jump_to_overridden"), NavigationAction(DeclarationPointer(overridden), KDevelop::NavigationAction::NavigateDeclaration)); + makeLink(i18n("function"), QStringLiteral("jump_to_overridden"), NavigationAction(DeclarationPointer(overridden), NavigationAction::NavigateDeclaration)); modifyHtml() += i18n(" from "); - makeLink(prettyQualifiedIdentifier(DeclarationPointer(overridden->context()->owner())).toString(), QStringLiteral("jump_to_overridden_container"), NavigationAction(DeclarationPointer(overridden->context()->owner()), KDevelop::NavigationAction::NavigateDeclaration)); + makeLink(prettyQualifiedName(DeclarationPointer(overridden->context()->owner())), + QStringLiteral("jump_to_overridden_container"), + NavigationAction(DeclarationPointer(overridden->context()->owner()), + NavigationAction::NavigateDeclaration)); modifyHtml() += "
"; }else{ //Check if this declarations hides other declarations QList decls; foreach(const DUContext::Import &import, m_declaration->context()->importedParentContexts()) if(import.context(m_topContext.data())) decls += import.context(m_topContext.data())->findDeclarations(QualifiedIdentifier(m_declaration->identifier()), CursorInRevision::invalid(), AbstractType::Ptr(), m_topContext.data(), DUContext::DontSearchInParent); uint num = 0; foreach(Declaration* decl, decls) { modifyHtml() += i18n("Hides a "); - makeLink(i18n("function"), QStringLiteral("jump_to_hide_%1").arg(num), NavigationAction(DeclarationPointer(decl), KDevelop::NavigationAction::NavigateDeclaration)); + makeLink(i18n("function"), QStringLiteral("jump_to_hide_%1").arg(num), + NavigationAction(DeclarationPointer(decl), + NavigationAction::NavigateDeclaration)); modifyHtml() += i18n(" from "); - makeLink(prettyQualifiedIdentifier(DeclarationPointer(decl->context()->owner())).toString(), QStringLiteral("jump_to_hide_container_%1").arg(num), NavigationAction(DeclarationPointer(decl->context()->owner()), KDevelop::NavigationAction::NavigateDeclaration)); + makeLink(prettyQualifiedName(DeclarationPointer(decl->context()->owner())), + QStringLiteral("jump_to_hide_container_%1").arg(num), + NavigationAction(DeclarationPointer(decl->context()->owner()), + NavigationAction::NavigateDeclaration)); modifyHtml() += "
"; ++num; } } ///Show all places where this function is overridden if(classFunDecl->isVirtual()) { Declaration* classDecl = m_declaration->context()->owner(); if(classDecl) { uint maxAllowedSteps = m_fullBackwardSearch ? (uint)-1 : 10; QList overriders = DUChainUtils::getOverriders(classDecl, classFunDecl, maxAllowedSteps); if(!overriders.isEmpty()) { modifyHtml() += i18n("Overridden in "); bool first = true; foreach(Declaration* overrider, overriders) { if(!first) modifyHtml() += ", "; first = false; - QString name = prettyQualifiedIdentifier(DeclarationPointer(overrider->context()->owner())).toString(); + const auto owner = DeclarationPointer(overrider->context()->owner()); + const QString name = prettyQualifiedName(owner); makeLink(name, name, NavigationAction(DeclarationPointer(overrider), NavigationAction::NavigateDeclaration)); } modifyHtml() += "
"; } if(maxAllowedSteps == 0) createFullBackwardSearchLink(overriders.isEmpty() ? i18n("Overriders possible, show all") : i18n("More overriders possible, show all")); } } } ///Show all classes that inherit this one uint maxAllowedSteps = m_fullBackwardSearch ? (uint)-1 : 10; QList inheriters = DUChainUtils::getInheriters(m_declaration.data(), maxAllowedSteps); if(!inheriters.isEmpty()) { modifyHtml() += i18n("Inherited by "); bool first = true; foreach(Declaration* importer, inheriters) { if(!first) modifyHtml() += ", "; first = false; - QString importerName = prettyQualifiedIdentifier(DeclarationPointer(importer)).toString(); - makeLink(importerName, importerName, NavigationAction(DeclarationPointer(importer), KDevelop::NavigationAction::NavigateDeclaration)); + const QString importerName = prettyQualifiedName(DeclarationPointer(importer)); + makeLink(importerName, importerName, + NavigationAction(DeclarationPointer(importer), NavigationAction::NavigateDeclaration)); } modifyHtml() += "
"; } if(maxAllowedSteps == 0) createFullBackwardSearchLink(inheriters.isEmpty() ? i18n("Inheriters possible, show all") : i18n("More inheriters possible, show all")); } void AbstractDeclarationNavigationContext::createFullBackwardSearchLink(QString string) { makeLink(string, "m_fullBackwardSearch=true", NavigationAction("m_fullBackwardSearch=true")); modifyHtml() += "
"; } NavigationContextPointer AbstractDeclarationNavigationContext::executeKeyAction( QString key ) { if(key == "m_fullBackwardSearch=true") { m_fullBackwardSearch = true; clear(); } return NavigationContextPointer(this); } void AbstractDeclarationNavigationContext::htmlClass() { StructureType::Ptr klass = m_declaration->abstractType().cast(); Q_ASSERT(klass); ClassDeclaration* classDecl = dynamic_cast(klass->declaration(m_topContext.data())); if(classDecl) { switch ( classDecl->classType() ) { case ClassDeclarationData::Class: modifyHtml() += "class "; break; case ClassDeclarationData::Struct: modifyHtml() += "struct "; break; case ClassDeclarationData::Union: modifyHtml() += "union "; break; case ClassDeclarationData::Interface: modifyHtml() += "interface "; break; case ClassDeclarationData::Trait: modifyHtml() += "trait "; break; default: modifyHtml() += " "; break; } eventuallyMakeTypeLinks( klass.cast() ); - FOREACH_FUNCTION( const KDevelop::BaseClassInstance& base, classDecl->baseClasses ) { + FOREACH_FUNCTION( const BaseClassInstance& base, classDecl->baseClasses ) { modifyHtml() += ", " + stringFromAccess(base.access) + " " + (base.virtualInheritance ? QStringLiteral("virtual") : QString()) + " "; eventuallyMakeTypeLinks(base.baseClass.abstractType()); } } else { /// @todo How can we get here? and should this really be a class? modifyHtml() += "class "; eventuallyMakeTypeLinks( klass.cast() ); } modifyHtml() += " "; } void AbstractDeclarationNavigationContext::htmlIdentifiedType(AbstractType::Ptr type, const IdentifiedType* idType) { Q_ASSERT(type); Q_ASSERT(idType); if( Declaration* decl = idType->declaration(m_topContext.data()) ) { //Remove the last template-identifiers, because we create those directly QualifiedIdentifier id = prettyQualifiedIdentifier(DeclarationPointer(decl)); Identifier lastId = id.last(); id.pop(); lastId.clearTemplateIdentifiers(); id.push(lastId); if(decl->context() && decl->context()->owner()) { //Also create full type-links for the context around AbstractType::Ptr contextType = decl->context()->owner()->abstractType(); IdentifiedType* contextIdType = dynamic_cast(contextType.data()); if(contextIdType && !contextIdType->equals(idType)) { //Create full type information for the context if(!id.isEmpty()) id = id.mid(id.count()-1); htmlIdentifiedType(contextType, contextIdType); modifyHtml() += QStringLiteral("::").toHtmlEscaped(); } } //We leave out the * and & reference and pointer signs, those are added to the end makeLink(id.toString() , DeclarationPointer(idType->declaration(m_topContext.data())), NavigationAction::NavigateDeclaration ); } else { qCDebug(LANGUAGE) << "could not resolve declaration:" << idType->declarationId().isDirect() << idType->qualifiedIdentifier().toString() << "in top-context" << m_topContext->url().str(); modifyHtml() += typeHighlight(type->toString().toHtmlEscaped()); } } void AbstractDeclarationNavigationContext::eventuallyMakeTypeLinks( AbstractType::Ptr type ) { type = typeToShow(type); if( !type ) { modifyHtml() += typeHighlight(QStringLiteral("").toHtmlEscaped()); return; } AbstractType::Ptr target = TypeUtils::targetTypeKeepAliases( type, m_topContext.data() ); const IdentifiedType* idType = dynamic_cast( target.data() ); qCDebug(LANGUAGE) << "making type-links for" << type->toString(); if( idType && idType->declaration(m_topContext.data()) ) { ///@todo This is C++ specific, move into subclass if(target->modifiers() & AbstractType::ConstModifier) modifyHtml() += typeHighlight("const "); htmlIdentifiedType(target, idType); //We need to exchange the target type, else template-parameters may confuse this SimpleTypeExchanger exchangeTarget(target, AbstractType::Ptr()); AbstractType::Ptr exchanged = exchangeTarget.exchange(type); if(exchanged) { QString typeSuffixString = exchanged->toString(); QRegExp suffixExp("\\&|\\*"); int suffixPos = typeSuffixString.indexOf(suffixExp); if(suffixPos != -1) modifyHtml() += typeHighlight(typeSuffixString.mid(suffixPos)); } } else { if(idType) { qCDebug(LANGUAGE) << "identified type could not be resolved:" << idType->qualifiedIdentifier() << idType->declarationId().isValid() << idType->declarationId().isDirect(); } modifyHtml() += typeHighlight(type->toString().toHtmlEscaped()); } } DeclarationPointer AbstractDeclarationNavigationContext::declaration() const { return m_declaration; } QString AbstractDeclarationNavigationContext::identifierHighlight(const QString& identifier, const DeclarationPointer& decl) const { QString ret = nameHighlight(identifier); if (!decl) { return ret; } if (decl->isDeprecated()) { ret = QStringLiteral("") + ret + QStringLiteral(""); } return ret; } QString AbstractDeclarationNavigationContext::stringFromAccess(Declaration::AccessPolicy access) { switch(access) { case Declaration::Private: return "private"; case Declaration::Protected: return "protected"; case Declaration::Public: return "public"; default: break; } return ""; } QString AbstractDeclarationNavigationContext::stringFromAccess(DeclarationPointer decl) { const ClassMemberDeclaration* memberDecl = dynamic_cast(decl.data()); if( memberDecl ) { return stringFromAccess(memberDecl->accessPolicy()); } return QString(); } QString AbstractDeclarationNavigationContext::declarationName( DeclarationPointer decl ) const { if( NamespaceAliasDeclaration* alias = dynamic_cast(decl.data()) ) { if( alias->identifier().isEmpty() ) return "using namespace " + alias->importIdentifier().toString(); else return "namespace " + alias->identifier().toString() + " = " + alias->importIdentifier().toString(); } if( !decl ) return i18nc("A declaration that is unknown", "Unknown"); else return prettyIdentifier(decl).toString(); } QStringList AbstractDeclarationNavigationContext::declarationDetails(DeclarationPointer decl) { QStringList details; const AbstractFunctionDeclaration* function = dynamic_cast(decl.data()); const ClassMemberDeclaration* memberDecl = dynamic_cast(decl.data()); if( memberDecl ) { if( memberDecl->isMutable() ) details << "mutable"; if( memberDecl->isRegister() ) details << "register"; if( memberDecl->isStatic() ) details << "static"; if( memberDecl->isAuto() ) details << "auto"; if( memberDecl->isExtern() ) details << "extern"; if( memberDecl->isFriend() ) details << "friend"; } if( decl->isDefinition() ) details << i18nc("tells if a declaration is defining the variable's value", "definition"); if( decl->isExplicitlyDeleted() ) details << "deleted"; if( memberDecl && memberDecl->isForwardDeclaration() ) details << i18nc("as in c++ forward declaration", "forward"); AbstractType::Ptr t(decl->abstractType()); if( t ) { if( t->modifiers() & AbstractType::ConstModifier ) details << i18nc("a variable that won't change, const", "constant"); if( t->modifiers() & AbstractType::VolatileModifier ) details << "volatile"; } if( function ) { if( function->isInline() ) details << "inline"; if( function->isExplicit() ) details << "explicit"; if( function->isVirtual() ) details << "virtual"; const ClassFunctionDeclaration* classFunDecl = dynamic_cast(decl.data()); if( classFunDecl ) { if( classFunDecl->isSignal() ) details << "signal"; if( classFunDecl->isSlot() ) details << "slot"; if( classFunDecl->isConstructor() ) details << "constructor"; if( classFunDecl->isDestructor() ) details << "destructor"; if( classFunDecl->isConversionFunction() ) details << "conversion-function"; if( classFunDecl->isAbstract() ) details << "abstract"; } } return details; } } diff --git a/language/duchain/navigation/abstractdeclarationnavigationcontext.h b/language/duchain/navigation/abstractdeclarationnavigationcontext.h index 383c3af26a..2356416f43 100644 --- a/language/duchain/navigation/abstractdeclarationnavigationcontext.h +++ b/language/duchain/navigation/abstractdeclarationnavigationcontext.h @@ -1,92 +1,94 @@ /* Copyright 2007 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. */ #ifndef KDEVPLATFORM_ABSTRACTDECLARATIONNAVIGATIONCONTEXT_H #define KDEVPLATFORM_ABSTRACTDECLARATIONNAVIGATIONCONTEXT_H #include "abstractnavigationcontext.h" #include "../declaration.h" #include "../duchainpointer.h" #include "../types/abstracttype.h" namespace KDevelop { class IdentifiedType; class Identifier; class QualifiedIdentifier; class KDEVPLATFORMLANGUAGE_EXPORT AbstractDeclarationNavigationContext : public AbstractNavigationContext { public: AbstractDeclarationNavigationContext( DeclarationPointer decl, KDevelop::TopDUContextPointer topContext, AbstractNavigationContext* previousContext = 0 ); virtual QString name() const override; DeclarationPointer declaration() const; ///Execute an action. For example "show_uses" shows the uses of the declaration. ///Returns the context pointer for the new state. virtual NavigationContextPointer executeKeyAction(QString key) override; protected: virtual QString html(bool shorten = false) override; DeclarationPointer m_declaration; ///Should returns a stripped version of the declarations qualified identifier, with all implicit/redundant parts removed virtual QualifiedIdentifier prettyQualifiedIdentifier(DeclarationPointer decl) const; ///Returns a stripped version of the declarations identifier, using prettyQualifiedIdentifier Identifier prettyIdentifier(DeclarationPointer decl) const; + /// @return String version of the qualified identifier of @p decl, '' on an invalid QID + QString prettyQualifiedName(DeclarationPointer decl) const; /** * Return a rich-text version of the identifier @p identifier representing the declaration @p decl * * @note In case @p declaration is deprecated, the resulting string will get a special formatting */ QString identifierHighlight(const QString& identifier, const DeclarationPointer& decl) const; static QString stringFromAccess(Declaration::AccessPolicy access); static QString stringFromAccess(DeclarationPointer decl); QString declarationName( DeclarationPointer decl ) const; static QStringList declarationDetails(DeclarationPointer decl); ///This can be used for example to resolve typedefs within the type. ///All types that are visualized in the navigation-context are/should be mangled through this. ///The default-implementation returns the original type. virtual AbstractType::Ptr typeToShow(AbstractType::Ptr type); ///Print the function-signature in a way that return-type and argument can be jumped to virtual void htmlFunction(); ///Navigation for additional less important links, like what function was overloaded etc. virtual void htmlAdditionalNavigation(); virtual void htmlClass(); virtual void htmlIdentifiedType(AbstractType::Ptr type, const IdentifiedType* idType); ///Creates and registers a link for the given type that jumps to its declaration and to the template-argument declarations virtual void eventuallyMakeTypeLinks( KDevelop::AbstractType::Ptr type ); ///Creates a link that triggers a recomputation of this context with m_fullBackwardSearch set to true void createFullBackwardSearchLink(QString string); bool m_fullBackwardSearch; }; } #endif diff --git a/language/duchain/navigation/abstractnavigationwidget.h b/language/duchain/navigation/abstractnavigationwidget.h index ec07546d14..69facf6972 100644 --- a/language/duchain/navigation/abstractnavigationwidget.h +++ b/language/duchain/navigation/abstractnavigationwidget.h @@ -1,106 +1,106 @@ /* Copyright 2007 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. */ #ifndef KDEVPLATFORM_ABSTRACTNAVIGATIONWIDGET_H #define KDEVPLATFORM_ABSTRACTNAVIGATIONWIDGET_H #include #include #include #include #include "../../interfaces/quickopendataprovider.h" #include #include "abstractnavigationcontext.h" class QTextBrowser; namespace KDevelop { /** * This class deleted itself when its part is deleted, so always use a QPointer when referencing it. * The duchain must be read-locked for most operations * */ class KDEVPLATFORMLANGUAGE_EXPORT AbstractNavigationWidget : public QWidget, public QuickOpenEmbeddedWidgetInterface { Q_OBJECT public: AbstractNavigationWidget(); - virtual ~AbstractNavigationWidget(); + ~AbstractNavigationWidget() override; void setContext(NavigationContextPointer context, int initBrowser = 400); QSize sizeHint() const override; public slots: ///Keyboard-action "next" - virtual void next() override; + void next() override; ///Keyboard-action "previous" - virtual void previous() override; + void previous() override; ///Keyboard-action "accept" - virtual void accept() override; - virtual void up() override; - virtual void down() override; + void accept() override; + void up() override; + void down() override; virtual void back(); ///These are temporarily for gettings these events directly from kate ///@todo Do this through a public interface post 4.2 void embeddedWidgetRight(); ///Keyboard-action "previous" void embeddedWidgetLeft(); ///Keyboard-action "accept" void embeddedWidgetAccept(); void embeddedWidgetUp(); void embeddedWidgetDown(); NavigationContextPointer context(); Q_SIGNALS: void sizeHintChanged(); /// Emitted whenever the current navigation-context has changed /// @param wasInitial whether the previous context was the initial context /// @param isInitial whether the current context is the initial context void contextChanged(bool wasInitial, bool isInitial); public slots: void navigateDeclaration(KDevelop::IndexedDeclaration decl); private slots: void anchorClicked(const QUrl&); protected: - virtual void wheelEvent(QWheelEvent* ) override; + void wheelEvent(QWheelEvent* ) override; void updateIdealSize() const; void initBrowser(int height); void update(); NavigationContextPointer m_startContext; TopDUContextPointer m_topContext; QPointer m_browser; QWidget* m_currentWidget; QString m_currentText; mutable QSize m_idealTextSize; private: NavigationContextPointer m_context; }; } #endif diff --git a/language/duchain/navigation/usescollector.h b/language/duchain/navigation/usescollector.h index 7aa205486b..b7e58d074f 100644 --- a/language/duchain/navigation/usescollector.h +++ b/language/duchain/navigation/usescollector.h @@ -1,131 +1,131 @@ /* 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. */ #ifndef KDEVPLATFORM_USESCOLLECTOR_H #define KDEVPLATFORM_USESCOLLECTOR_H #include #include #include #include namespace KDevelop { class IndexedDeclaration; class IndexedString; ///A helper base-class for collecting the top-contexts that contain all uses of a declaration ///The most important part is that this also updates the duchain if it's not up-to-date or doesn't contain ///the required features. The virtual function processUses(..) is called with each up-to-date top-context found ///that contains uses of the declaration. class KDEVPLATFORMLANGUAGE_EXPORT UsesCollector : public QObject { Q_OBJECT public: explicit UsesCollector(IndexedDeclaration declaration); - virtual ~UsesCollector(); + ~UsesCollector() override; ///@warning For most tasks, you should use declarations() instead, and respect all of them! IndexedDeclaration declaration() const; ///This must be called to start the actual collecting! void startCollecting(); ///Override this to decide whether a file should be respect while computation. ///If true is returned, the uses will be computed for this file, and for all files ///in the import-chain between that file, and the file where the declaration occurs. ///The default-implementation returns true if the file is part of an open project, or ///if no project is opened and the file is open in an editor. virtual bool shouldRespectFile(IndexedString url); bool isReady() const; ///If this is true, the complete overload-chain is computed, and the uses of all overloaded functions together ///are computed. ///They are also returned in declarations(): ///The default is "true" void setCollectOverloads(bool collect); ///If this is true, all definitions are loaded too, and part of the processed declarations. ///This also means that the collector will first jump from any definition to its declaration, and start ///collecting from there. ///They are also returned in declarations(): ///The default is "true" void setCollectDefinitions(bool collectDefinition); ///Use this to set whether processUses should also be called on contexts that only contain ///a declaration that was used for searching the uses ///The default is "true". void setProcessDeclarations(bool process); ///If the searched declaration is a class, this can be used to decide whether constructors ///searched as well. The constructors and destructors will also be part of the declarations() list. ///The default is "true". This only works with constructors that have the same name as the class. ///If this is set to true, also destructors are searched and eventually renamed. void setCollectConstructors(bool process); ///The declarations that were used as base for the search ///For classes this contains forward-declarations etc. ///@warning When doing refactoring, you have to respect all of these as possible used declarations, /// even within the same context. Multiple different of them may have been used in the same top-context, /// with different local use-indices. QList declarations(); Q_SIGNALS: ///@see maximumProgress() void maximumProgressSignal(uint); ///@see progress() void progressSignal(uint, uint); ///@see processUses() void processUsesSignal(KDevelop::ReferencedTopDUContext); private slots: void updateReady(KDevelop::IndexedString url, KDevelop::ReferencedTopDUContext topContext); private: ///Called with every top-context that can contain uses of the declaration, or if setProcessDeclarations(false) ///has not been called also with all contexts that contain declarations used as base for the search. ///Override this to do your custom processing. You do not need to recurse into imports, that's done for you. ///The duchain is not locked when this is called. virtual void processUses(KDevelop::ReferencedTopDUContext topContext) = 0; ///Indicates the maximum progress this collector can make. If zero is given, this collector is not going to ///do any progress, and progress(..) is never called. virtual void maximumProgress(uint max); ///Called whenever progress has been made. max equals the value given initially by maximumProgress virtual void progress(uint processed, uint max); IndexedDeclaration m_declaration; QSet m_waitForUpdate; QSet m_updateReady; //All files that already have been feed to processUses QSet m_processed; //To prevent endless recursion in updateReady() QSet m_checked; ///Set of all files where the features were manipulated statically through ParseJob QSet m_staticFeaturesManipulated; QList m_declarations; QSet m_declarationTopContexts; bool m_collectOverloads; bool m_collectDefinitions; bool m_collectConstructors; bool m_processDeclarations; }; } #endif diff --git a/language/duchain/navigation/useswidget.h b/language/duchain/navigation/useswidget.h index 5aa09401b5..2fd7439b55 100644 --- a/language/duchain/navigation/useswidget.h +++ b/language/duchain/navigation/useswidget.h @@ -1,162 +1,162 @@ /* 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. */ #ifndef KDEVPLATFORM_USESWIDGET_H #define KDEVPLATFORM_USESWIDGET_H #include #include #include #include #include #include #include "usescollector.h" #include class QLabel; class QToolButton; class QVBoxLayout; class QHBoxLayout; class QBoxLayout; class QPushButton; class QProgressBar; namespace KDevelop { class CodeRepresentation; class IndexedDeclaration; ///A widget representing one use of a Declaration in a speicific context class KDEVPLATFORMLANGUAGE_EXPORT OneUseWidget : public QWidget { Q_OBJECT public: OneUseWidget(IndexedDeclaration declaration, IndexedString document, KTextEditor::Range range, const CodeRepresentation& code); - ~OneUseWidget(); + ~OneUseWidget() override; private slots: void jumpTo(); private: - virtual void resizeEvent ( QResizeEvent * event ) override; + void resizeEvent ( QResizeEvent * event ) override; PersistentMovingRange::Ptr m_range; IndexedDeclaration m_declaration; IndexedString m_document; QString m_sourceLine; QLabel* m_label; QLabel* m_icon; QHBoxLayout* m_layout; }; class KDEVPLATFORMLANGUAGE_EXPORT NavigatableWidgetList : public QScrollArea { Q_OBJECT public: explicit NavigatableWidgetList(bool allowScrolling = false, uint maxHeight = 0, bool vertical = true); - ~NavigatableWidgetList(); + ~NavigatableWidgetList() override; void addItem(QWidget* widget, int pos = -1); void addHeaderItem(QWidget* widget, Qt::Alignment alignment = 0); ///Whether items were added to this list using addItem(..) bool hasItems() const; ///Deletes all items that were added using addItem void deleteItems(); QList items() const; void setShowHeader(bool show); protected: QBoxLayout* m_itemLayout; QVBoxLayout* m_layout; private: QHBoxLayout* m_headerLayout; QToolButton *m_previousButton, *m_nextButton; bool m_allowScrolling, m_useArrows; }; class KDEVPLATFORMLANGUAGE_EXPORT ContextUsesWidget : public NavigatableWidgetList { Q_OBJECT public: ContextUsesWidget(const CodeRepresentation& code, QList usedDeclaration, IndexedDUContext context); Q_SIGNALS: void navigateDeclaration(KDevelop::IndexedDeclaration); private Q_SLOTS: void linkWasActivated(QString); private: IndexedDUContext m_context; }; class KDEVPLATFORMLANGUAGE_EXPORT DeclarationWidget : public NavigatableWidgetList { Q_OBJECT public: DeclarationWidget(const KDevelop::CodeRepresentation& code, const KDevelop::IndexedDeclaration& declaration); }; /** * Represents the uses of a declaration within one top-context */ class KDEVPLATFORMLANGUAGE_EXPORT TopContextUsesWidget : public NavigatableWidgetList { Q_OBJECT public: TopContextUsesWidget(IndexedDeclaration declaration, QList localDeclarations, IndexedTopDUContext topContext); void setExpanded(bool); int usesCount() const; private slots: void labelClicked(); private: IndexedTopDUContext m_topContext; IndexedDeclaration m_declaration; QLabel* m_icon; QLabel* m_toggleButton; QList m_allDeclarations; int m_usesCount; }; /** * A widget that allows browsing through all the uses of a declaration, and also through all declarations of it. */ class KDEVPLATFORMLANGUAGE_EXPORT UsesWidget : public NavigatableWidgetList { Q_OBJECT public: ///This class can be overridden to do additional processing while the uses-widget shows the uses. struct KDEVPLATFORMLANGUAGE_EXPORT UsesWidgetCollector : public UsesCollector { public: void setWidget(UsesWidget* widget ); UsesWidgetCollector(IndexedDeclaration decl); - virtual void processUses(KDevelop::ReferencedTopDUContext topContext) override; - virtual void maximumProgress(uint max) override; - virtual void progress(uint processed, uint total) override; + void processUses(KDevelop::ReferencedTopDUContext topContext) override; + void maximumProgress(uint max) override; + void progress(uint processed, uint total) override; UsesWidget* m_widget; }; - virtual QSize sizeHint () const override; + QSize sizeHint () const override; ///@param customCollector allows specifying an own subclass of UsesWidgetCollector. explicit UsesWidget(const IndexedDeclaration& declaration, QSharedPointer customCollector = {}); - ~UsesWidget(); + ~UsesWidget() override; void setAllExpanded(bool expanded); unsigned int countAllUses() const; Q_SIGNALS: void navigateDeclaration(KDevelop::IndexedDeclaration); private: const QString headerLineText() const; QLabel* m_headerLine; QSharedPointer m_collector; QProgressBar* m_progressBar; public slots: void headerLinkActivated(QString linkName); void redrawHeaderLine(); }; } #endif diff --git a/language/duchain/topducontext.cpp b/language/duchain/topducontext.cpp index bcdc2f6cd7..f3a64a8b21 100644 --- a/language/duchain/topducontext.cpp +++ b/language/duchain/topducontext.cpp @@ -1,1164 +1,1164 @@ /* This is part of KDevelop Copyright 2006 Hamish Rodda Copyright 2007-2009 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 "topducontext.h" #include "topducontextutils.h" #include #include #include "persistentsymboltable.h" #include "problem.h" #include "declaration.h" #include "duchain.h" #include "duchainlock.h" #include "parsingenvironment.h" #include "duchainpointer.h" #include "declarationid.h" #include "namespacealiasdeclaration.h" #include "aliasdeclaration.h" #include "uses.h" #include "topducontextdata.h" #include "duchainregister.h" #include "topducontextdynamicdata.h" #include "util/debug.h" // #define DEBUG_SEARCH const uint maxApplyAliasesRecursion = 100; namespace KDevelop { Utils::BasicSetRepository* RecursiveImportRepository::repository() { static Utils::BasicSetRepository recursiveImportRepositoryObject("Recursive Imports", &KDevelop::globalItemRepositoryRegistry()); return &recursiveImportRepositoryObject; } ReferencedTopDUContext::ReferencedTopDUContext(TopDUContext* context) : m_topContext(context) { if(m_topContext) DUChain::self()->refCountUp(m_topContext); } ReferencedTopDUContext::ReferencedTopDUContext(const ReferencedTopDUContext& rhs) : m_topContext(rhs.m_topContext) { if(m_topContext) DUChain::self()->refCountUp(m_topContext); } ReferencedTopDUContext::~ReferencedTopDUContext() { if(m_topContext && !DUChain::deleted()) DUChain::self()->refCountDown(m_topContext); } ReferencedTopDUContext& ReferencedTopDUContext::operator=(const ReferencedTopDUContext& rhs) { if(m_topContext == rhs.m_topContext) return *this; if(m_topContext) DUChain::self()->refCountDown(m_topContext); m_topContext = rhs.m_topContext; if(m_topContext) DUChain::self()->refCountUp(m_topContext); return *this; } DEFINE_LIST_MEMBER_HASH(TopDUContextData, m_usedDeclarationIds, DeclarationId) DEFINE_LIST_MEMBER_HASH(TopDUContextData, m_problems, LocalIndexedProblem) REGISTER_DUCHAIN_ITEM(TopDUContext); template void removeFromVector(QVector& vec, const T& t) { for(int a =0; a < vec.size(); ++a) { if(vec[a] == t) { vec.remove(a); removeFromVector(vec, t); return; } } } QMutex importStructureMutex(QMutex::Recursive); //Contains data that is not shared among top-contexts that share their duchain entries class TopDUContextLocalPrivate { public: TopDUContextLocalPrivate (TopDUContext* ctxt, uint index) : m_ctxt(ctxt), m_ownIndex(index), m_inDuChain(false) { m_indexedRecursiveImports.insert(index); } ~TopDUContextLocalPrivate() { //Either we use some other contexts data and have no users, or we own the data and have users that share it. QMutexLocker lock(&importStructureMutex); foreach(const DUContext::Import& import, m_importedContexts) if(DUChain::self()->isInMemory(import.topContextIndex()) && dynamic_cast(import.context(0))) dynamic_cast(import.context(0))->m_local->m_directImporters.remove(m_ctxt); } ///@todo Make all this work consistently together with import-caching //After loading, should rebuild the links void rebuildDynamicImportStructure() { //Currently we do not store the whole data in TopDUContextLocalPrivate, so we reconstruct it from what was stored by DUContext. Q_ASSERT(m_importedContexts.isEmpty()); FOREACH_FUNCTION(const DUContext::Import& import, m_ctxt->d_func()->m_importedContexts) { if(DUChain::self()->isInMemory(import.topContextIndex())) { Q_ASSERT(import.context(0)); TopDUContext* top = import.context(0)->topContext(); Q_ASSERT(top); addImportedContextRecursively(top, false, true); } } FOREACH_FUNCTION(const IndexedDUContext& importer, m_ctxt->d_func()->m_importers) { if(DUChain::self()->isInMemory(importer.topContextIndex())) { Q_ASSERT(importer.context()); TopDUContext* top = importer.context()->topContext(); Q_ASSERT(top); top->m_local->addImportedContextRecursively(m_ctxt, false, true); } } } //Index of this top-context within the duchain //Since the data of top-contexts can be shared among multiple, this can be used to add imports that are local to this top-context. QVector m_importedContexts; // mutable bool m_haveImportStructure : 1; TopDUContext* m_ctxt; QSet m_directImporters; ParsingEnvironmentFilePointer m_file; QExplicitlySharedDataPointer m_ast; uint m_ownIndex; bool m_inDuChain; void clearImportedContextsRecursively() { QMutexLocker lock(&importStructureMutex); // Q_ASSERT(m_recursiveImports.size() == m_indexedRecursiveImports.count()-1); QSet > rebuild; foreach(const DUContext::Import &import, m_importedContexts) { TopDUContext* top = dynamic_cast(import.context(0)); if(top) { top->m_local->m_directImporters.remove(m_ctxt); if(!m_ctxt->usingImportsCache()) { removeImportedContextRecursion(top, top, 1, rebuild); QHash > b = top->m_local->m_recursiveImports; for(RecursiveImports::const_iterator it = b.constBegin(); it != b.constEnd(); ++it) { if(m_recursiveImports.contains(it.key()) && m_recursiveImports[it.key()].second == top) removeImportedContextRecursion(top, it.key(), it->first+1, rebuild); //Remove all contexts that are imported through the context } } } } m_importedContexts.clear(); rebuildImportStructureRecursion(rebuild); Q_ASSERT(m_recursiveImports.isEmpty()); // Q_ASSERT(m_recursiveImports.size() == m_indexedRecursiveImports.count()-1); } //Adds the context to this and all contexts that import this, and manages m_recursiveImports void addImportedContextRecursively(TopDUContext* context, bool temporary, bool local) { QMutexLocker lock(&importStructureMutex); context->m_local->m_directImporters.insert(m_ctxt); if(local) m_importedContexts << DUContext::Import(context, m_ctxt); if(!m_ctxt->usingImportsCache()) { addImportedContextRecursion(context, context, 1, temporary); QHash > b = context->m_local->m_recursiveImports; for(RecursiveImports::const_iterator it = b.constBegin(); it != b.constEnd(); ++it) addImportedContextRecursion(context, it.key(), (*it).first+1, temporary); //Add contexts that were imported earlier into the given one } } //Removes the context from this and all contexts that import this, and manages m_recursiveImports void removeImportedContextRecursively(TopDUContext* context, bool local) { QMutexLocker lock(&importStructureMutex); context->m_local->m_directImporters.remove(m_ctxt); if(local) removeFromVector(m_importedContexts, DUContext::Import(context, m_ctxt)); QSet > rebuild; if(!m_ctxt->usingImportsCache()) { removeImportedContextRecursion(context, context, 1, rebuild); QHash > b = context->m_local->m_recursiveImports; for(RecursiveImports::const_iterator it = b.constBegin(); it != b.constEnd(); ++it) { if(m_recursiveImports.contains(it.key()) && m_recursiveImports[it.key()].second == context) removeImportedContextRecursion(context, it.key(), it->first+1, rebuild); //Remove all contexts that are imported through the context } } rebuildImportStructureRecursion(rebuild); } void removeImportedContextsRecursively(const QList& contexts, bool local) { QMutexLocker lock(&importStructureMutex); QSet > rebuild; foreach(TopDUContext* context, contexts) { context->m_local->m_directImporters.remove(m_ctxt); if(local) removeFromVector(m_importedContexts, DUContext::Import(context, m_ctxt)); if(!m_ctxt->usingImportsCache()) { removeImportedContextRecursion(context, context, 1, rebuild); QHash > b = context->m_local->m_recursiveImports; for(RecursiveImports::const_iterator it = b.constBegin(); it != b.constEnd(); ++it) { if(m_recursiveImports.contains(it.key()) && m_recursiveImports[it.key()].second == context) removeImportedContextRecursion(context, it.key(), it->first+1, rebuild); //Remove all contexts that are imported through the context } } } rebuildImportStructureRecursion(rebuild); } //Has an entry for every single recursively imported file, that contains the shortest path, and the next context on that path to the imported context. //This does not need to be stored to disk, because it is defined implicitly. //What makes this most complicated is the fact that loops are allowed in the import structure. typedef QHash > RecursiveImports; mutable RecursiveImports m_recursiveImports; mutable TopDUContext::IndexedRecursiveImports m_indexedRecursiveImports; private: void addImportedContextRecursion(const TopDUContext* traceNext, const TopDUContext* imported, int depth, bool temporary = false) { if(m_ctxt->usingImportsCache()) return; // if(!m_haveImportStructure) // return; if(imported == m_ctxt) return; const bool computeShortestPaths = false; ///@todo We do not compute the shortest path. Think what's right. // traceNext->m_local->needImportStructure(); // imported->m_local->needImportStructure(); RecursiveImports::iterator it = m_recursiveImports.find(imported); if(it == m_recursiveImports.end()) { //Insert new path to "imported" m_recursiveImports[imported] = qMakePair(depth, traceNext); m_indexedRecursiveImports.insert(imported->indexed()); // Q_ASSERT(m_indexedRecursiveImports.size() == m_recursiveImports.size()+1); Q_ASSERT(traceNext != m_ctxt); }else{ if(!computeShortestPaths) return; if(temporary) //For temporary imports, we don't record the best path. return; //It would be better if we would use the following code, but it creates too much cost in updateImportedContextRecursion when imports are removed again. //Check whether the new way to "imported" is shorter than the stored one if((*it).first > depth) { //Add a shorter path (*it).first = depth; Q_ASSERT(traceNext); (*it).second = traceNext; Q_ASSERT(traceNext == imported || (traceNext->m_local->m_recursiveImports.contains(imported) && traceNext->m_local->m_recursiveImports[imported].first < (*it).first)); }else{ //The imported context is already imported through a same/better path, so we can just stop processing. This saves us from endless recursion. return; } } if(temporary) return; for(QSet::const_iterator it = m_directImporters.constBegin(); it != m_directImporters.constEnd(); ++it) { TopDUContext* top = dynamic_cast(const_cast(*it)); //Avoid detaching, so use const_cast if(top) ///@todo also record this for local imports top->m_local->addImportedContextRecursion(m_ctxt, imported, depth+1); } } void removeImportedContextRecursion(const TopDUContext* traceNext, const TopDUContext* imported, int distance, QSet >& rebuild) { if(m_ctxt->usingImportsCache()) return; if(imported == m_ctxt) return; // if(!m_haveImportStructure) // return; RecursiveImports::iterator it = m_recursiveImports.find(imported); if(it == m_recursiveImports.end()) { //We don't import. Just return, this saves us from endless recursion. return; }else{ //Check whether we have imported "imported" through "traceNext". If not, return. Else find a new trace. if((*it).second == traceNext && (*it).first == distance) { //We need to remove the import through traceNext. Check whether there is another imported context that imports it. m_recursiveImports.erase(it); //In order to prevent problems, we completely remove everything, and re-add it. //Just updating these complex structures is very hard. Q_ASSERT(imported != m_ctxt); m_indexedRecursiveImports.remove(imported->indexed()); // Q_ASSERT(m_indexedRecursiveImports.size() == m_recursiveImports.size()); rebuild.insert(qMakePair(m_ctxt, imported)); //We MUST do this before finding another trace, because else we would create loops for(QSet::const_iterator childIt = m_directImporters.constBegin(); childIt != m_directImporters.constEnd(); ++childIt) { TopDUContext* top = dynamic_cast(const_cast(*childIt)); //Avoid detaching, so use const iterator if(top) top->m_local->removeImportedContextRecursion(m_ctxt, imported, distance+1, rebuild); //Don't use 'it' from here on, it may be invalid } } } } //Updates the trace to 'imported' void rebuildStructure(const TopDUContext* imported); void rebuildImportStructureRecursion(const QSet >& rebuild) { for(QSet >::const_iterator it = rebuild.constBegin(); it != rebuild.constEnd(); ++it) { //for(int a = rebuild.size()-1; a >= 0; --a) { //Find the best imported parent it->first->m_local->rebuildStructure(it->second); } } }; const TopDUContext::IndexedRecursiveImports& TopDUContext::recursiveImportIndices() const { // No lock-check for performance reasons QMutexLocker lock(&importStructureMutex); if(!d_func()->m_importsCache.isEmpty()) return d_func()->m_importsCache; return m_local->m_indexedRecursiveImports; } void TopDUContextData::updateImportCacheRecursion(uint baseIndex, IndexedTopDUContext currentContext, TopDUContext::IndexedRecursiveImports& visited) { if(visited.contains(currentContext.index())) return; Q_ASSERT(currentContext.index()); //The top-context must be in the repository when this is called if(!currentContext.data()) { qCDebug(LANGUAGE) << "importing invalid context"; return; } visited.insert(currentContext.index()); const TopDUContextData* currentData = currentContext.data()->topContext()->d_func(); if(currentData->m_importsCache.contains(baseIndex) || currentData->m_importsCache.isEmpty()) { //If we have a loop or no imports-cache is used, we have to look at each import separately. const KDevelop::DUContext::Import* imports = currentData->m_importedContexts(); uint importsSize = currentData->m_importedContextsSize(); for(uint a = 0; a < importsSize; ++a) { IndexedTopDUContext next(imports[a].topContextIndex()); if(next.isValid()) updateImportCacheRecursion(baseIndex, next, visited); } }else{ //If we don't have a loop with baseIndex, we can safely just merge with the imported importscache visited += currentData->m_importsCache; } } void TopDUContextData::updateImportCacheRecursion(IndexedTopDUContext currentContext, std::set& visited) { if(visited.find(currentContext.index()) != visited.end()) return; Q_ASSERT(currentContext.index()); //The top-context must be in the repository when this is called if(!currentContext.data()) { qCDebug(LANGUAGE) << "importing invalid context"; return; } visited.insert(currentContext.index()); const TopDUContextData* currentData = currentContext.data()->topContext()->d_func(); const KDevelop::DUContext::Import* imports = currentData->m_importedContexts(); uint importsSize = currentData->m_importedContextsSize(); for(uint a = 0; a < importsSize; ++a) { IndexedTopDUContext next(imports[a].topContextIndex()); if(next.isValid()) updateImportCacheRecursion(next, visited); } } void TopDUContext::updateImportsCache() { QMutexLocker lock(&importStructureMutex); const bool use_fully_recursive_import_cache_computation = false; if(use_fully_recursive_import_cache_computation) { std::set visited; TopDUContextData::updateImportCacheRecursion(this, visited); Q_ASSERT(visited.find(ownIndex()) != visited.end()); d_func_dynamic()->m_importsCache = IndexedRecursiveImports(visited); }else{ d_func_dynamic()->m_importsCache = IndexedRecursiveImports(); TopDUContextData::updateImportCacheRecursion(ownIndex(), this, d_func_dynamic()->m_importsCache); } Q_ASSERT(d_func_dynamic()->m_importsCache.contains(IndexedTopDUContext(this))); Q_ASSERT(usingImportsCache()); Q_ASSERT(imports(this, CursorInRevision::invalid())); if(parsingEnvironmentFile()) parsingEnvironmentFile()->setImportsCache(d_func()->m_importsCache); } bool TopDUContext::usingImportsCache() const { return !d_func()->m_importsCache.isEmpty(); } CursorInRevision TopDUContext::importPosition(const DUContext* target) const { ENSURE_CAN_READ DUCHAIN_D(DUContext); Import import(const_cast(target), const_cast(this), CursorInRevision::invalid()); for(unsigned int a = 0; a < d->m_importedContextsSize(); ++a) if(d->m_importedContexts()[a] == import) return d->m_importedContexts()[a].position; return DUContext::importPosition(target); } void TopDUContextLocalPrivate::rebuildStructure(const TopDUContext* imported) { if(m_ctxt == imported) return; for(QVector::const_iterator parentIt = m_importedContexts.constBegin(); parentIt != m_importedContexts.constEnd(); ++parentIt) { TopDUContext* top = dynamic_cast(const_cast(parentIt->context(0))); //To avoid detaching, use const iterator if(top) { // top->m_local->needImportStructure(); if(top == imported) { addImportedContextRecursion(top, imported, 1); }else{ RecursiveImports::const_iterator it2 = top->m_local->m_recursiveImports.constFind(imported); if(it2 != top->m_local->m_recursiveImports.constEnd()) { addImportedContextRecursion(top, imported, (*it2).first + 1); } } } } for(unsigned int a = 0; a < m_ctxt->d_func()->m_importedContextsSize(); ++a) { TopDUContext* top = dynamic_cast(const_cast(m_ctxt->d_func()->m_importedContexts()[a].context(0))); //To avoid detaching, use const iterator if(top) { // top->m_local->needImportStructure(); if(top == imported) { addImportedContextRecursion(top, imported, 1); }else{ RecursiveImports::const_iterator it2 = top->m_local->m_recursiveImports.constFind(imported); if(it2 != top->m_local->m_recursiveImports.constEnd()) { addImportedContextRecursion(top, imported, (*it2).first + 1); } } } } } void TopDUContext::rebuildDynamicImportStructure() { m_local->rebuildDynamicImportStructure(); } void TopDUContext::rebuildDynamicData(DUContext* parent, uint ownIndex) { Q_ASSERT(parent == 0 && ownIndex != 0); m_local->m_ownIndex = ownIndex; DUContext::rebuildDynamicData(parent, 0); } IndexedTopDUContext TopDUContext::indexed() const { return IndexedTopDUContext(m_local->m_ownIndex); } uint TopDUContext::ownIndex() const { return m_local->m_ownIndex; } TopDUContext::TopDUContext(TopDUContextData& data) : DUContext(data), m_local(new TopDUContextLocalPrivate(this, data.m_ownIndex)), m_dynamicData(new TopDUContextDynamicData(this)) { } TopDUContext::TopDUContext(const IndexedString& url, const RangeInRevision& range, ParsingEnvironmentFile* file) : DUContext(*new TopDUContextData(url), range) , m_local(new TopDUContextLocalPrivate(this, DUChain::newTopContextIndex())) , m_dynamicData(new TopDUContextDynamicData(this)) { Q_ASSERT(url.toUrl().isValid() && !url.toUrl().isRelative()); d_func_dynamic()->setClassId(this); setType(Global); DUCHAIN_D_DYNAMIC(TopDUContext); d->m_features = VisibleDeclarationsAndContexts; d->m_ownIndex = m_local->m_ownIndex; setParsingEnvironmentFile(file); setInSymbolTable(true); } QExplicitlySharedDataPointer TopDUContext::parsingEnvironmentFile() const { return m_local->m_file; } TopDUContext::~TopDUContext( ) { m_dynamicData->m_deleting = true; //Clear the AST, so that the 'feature satisfaction' cache is eventually updated clearAst(); if(!isOnDisk()) { //Clear the 'feature satisfaction' cache which is managed in ParsingEnvironmentFile setFeatures(Empty); clearUsedDeclarationIndices(); } deleteChildContextsRecursively(); deleteLocalDeclarations(); m_dynamicData->clear(); } void TopDUContext::deleteSelf() { //We've got to make sure that m_dynamicData and m_local are still valid while all the sub-contexts are destroyed TopDUContextLocalPrivate* local = m_local; TopDUContextDynamicData* dynamicData = m_dynamicData; m_dynamicData->m_deleting = true; delete this; delete local; delete dynamicData; } TopDUContext::Features TopDUContext::features() const { uint ret = d_func()->m_features; if(ast()) ret |= TopDUContext::AST; return (TopDUContext::Features)ret; } void TopDUContext::setFeatures(Features features) { features = (TopDUContext::Features)(features & (~Recursive)); //Remove the "Recursive" flag since that's only for searching features = (TopDUContext::Features)(features & (~ForceUpdateRecursive)); //Remove the update flags features = (TopDUContext::Features)(features & (~AST)); //Remove the AST flag, it's only used while updating d_func_dynamic()->m_features = features; //Replicate features to ParsingEnvironmentFile if(parsingEnvironmentFile()) parsingEnvironmentFile()->setFeatures(this->features()); } void TopDUContext::setAst(QExplicitlySharedDataPointer ast) { ENSURE_CAN_WRITE m_local->m_ast = ast; if(parsingEnvironmentFile()) parsingEnvironmentFile()->setFeatures(features()); } void TopDUContext::setParsingEnvironmentFile(ParsingEnvironmentFile* file) { if(m_local->m_file) //Clear the "feature satisfaction" cache m_local->m_file->setFeatures(Empty); //We do not enforce a duchain lock here, since this is also used while loading a top-context m_local->m_file = QExplicitlySharedDataPointer(file); //Replicate features to ParsingEnvironmentFile if(file) { file->setTopContext(IndexedTopDUContext(ownIndex())); Q_ASSERT(file->indexedTopContext().isValid()); file->setFeatures(d_func()->m_features); file->setImportsCache(d_func()->m_importsCache); } } struct TopDUContext::FindDeclarationsAcceptor { FindDeclarationsAcceptor(const TopDUContext* _top, DeclarationList& _target, const DeclarationChecker& _check, SearchFlags _flags) : top(_top), target(_target), check(_check) { flags = _flags; } bool operator() (const QualifiedIdentifier& id) { #ifdef DEBUG_SEARCH qCDebug(LANGUAGE) << "accepting" << id.toString(); #endif PersistentSymbolTable::Declarations allDecls; //This iterator efficiently filters the visible declarations out of all declarations PersistentSymbolTable::FilteredDeclarationIterator filter; //This is used if filtering is disabled PersistentSymbolTable::Declarations::Iterator unchecked; if(check.flags & DUContext::NoImportsCheck) { allDecls = PersistentSymbolTable::self().getDeclarations(id); unchecked = allDecls.iterator(); } else filter = PersistentSymbolTable::self().getFilteredDeclarations(id, top->recursiveImportIndices()); while(filter || unchecked) { IndexedDeclaration iDecl; if(filter) { iDecl = *filter; ++filter; } else { iDecl = *unchecked; ++unchecked; } Declaration* decl = iDecl.data(); if(!decl) continue; if(!check(decl)) continue; if( ! (flags & DontResolveAliases) && decl->kind() == Declaration::Alias ) { //Apply alias declarations AliasDeclaration* alias = static_cast(decl); if(alias->aliasedDeclaration().isValid()) { decl = alias->aliasedDeclaration().declaration(); } else { qCDebug(LANGUAGE) << "lost aliased declaration"; } } target.append(decl); } check.createVisibleCache = 0; return !top->foundEnough(target, flags); } const TopDUContext* top; DeclarationList& target; const DeclarationChecker& check; QFlags< KDevelop::DUContext::SearchFlag > flags; }; bool TopDUContext::findDeclarationsInternal(const SearchItem::PtrList& identifiers, const CursorInRevision& position, const AbstractType::Ptr& dataType, DeclarationList& ret, const TopDUContext* /*source*/, SearchFlags flags, uint /*depth*/) const { ENSURE_CAN_READ #ifdef DEBUG_SEARCH for (const SearchItem::Ptr& idTree : identifiers) foreach(const QualifiedIdentifier &id, idTree->toList()) qCDebug(LANGUAGE) << "searching item" << id.toString(); #endif DeclarationChecker check(this, position, dataType, flags); FindDeclarationsAcceptor storer(this, ret, check, flags); ///The actual scopes are found within applyAliases, and each complete qualified identifier is given to FindDeclarationsAcceptor. ///That stores the found declaration to the output. applyAliases(identifiers, storer, position, false); return true; } //This is used to prevent endless recursion due to "using namespace .." declarations, by storing all imports that are already being used. struct TopDUContext::ApplyAliasesBuddyInfo { ApplyAliasesBuddyInfo(uint importChainType, ApplyAliasesBuddyInfo* predecessor, IndexedQualifiedIdentifier importId) : m_importChainType(importChainType), m_predecessor(predecessor), m_importId(importId) { if(m_predecessor && m_predecessor->m_importChainType != importChainType) m_predecessor = 0; } //May also be called when this is zero. bool alreadyImporting(IndexedQualifiedIdentifier id) { ApplyAliasesBuddyInfo* current = this; while(current) { if(current->m_importId == id) return true; current = current->m_predecessor; } return false; } uint m_importChainType; ApplyAliasesBuddyInfo* m_predecessor; IndexedQualifiedIdentifier m_importId; }; ///@todo Implement a cache so at least the global import checks don't need to be done repeatedly. The cache should be thread-local, using DUChainPointer for the hashed items, and when an item was deleted, it should be discarded template bool TopDUContext::applyAliases( const QualifiedIdentifier& previous, const SearchItem::Ptr& identifier, Acceptor& accept, const CursorInRevision& position, bool canBeNamespace, ApplyAliasesBuddyInfo* buddy, uint recursionDepth ) const { if(recursionDepth > maxApplyAliasesRecursion) { QList searches = identifier->toList(); QualifiedIdentifier id; if(!searches.isEmpty()) id = searches.first(); qCDebug(LANGUAGE) << "maximum apply-aliases recursion reached while searching" << id; } bool foundAlias = false; QualifiedIdentifier id(previous); id.push(identifier->identifier); if(!id.inRepository()) return true; //If the qualified identifier is not in the identifier repository, it cannot be registered anywhere, so there's nothing we need to do if( !identifier->next.isEmpty() || canBeNamespace ) { //If it cannot be a namespace, the last part of the scope will be ignored //Search for namespace-aliases, by using globalAliasIdentifier, which is inserted into the symbol-table by NamespaceAliasDeclaration QualifiedIdentifier aliasId(id); aliasId.push(globalIndexedAliasIdentifier()); #ifdef DEBUG_SEARCH qCDebug(LANGUAGE) << "checking" << id.toString(); #endif if(aliasId.inRepository()) { //This iterator efficiently filters the visible declarations out of all declarations PersistentSymbolTable::FilteredDeclarationIterator filter = PersistentSymbolTable::self().getFilteredDeclarations(aliasId, recursiveImportIndices()); if(filter) { DeclarationChecker check(this, position, AbstractType::Ptr(), NoSearchFlags, 0); //The first part of the identifier has been found as a namespace-alias. //In c++, we only need the first alias. However, just to be correct, follow them all for now. for(; filter; ++filter) { Declaration* aliasDecl = filter->data(); if(!aliasDecl) continue; if(!check(aliasDecl)) continue; if(aliasDecl->kind() != Declaration::NamespaceAlias) continue; if(foundAlias) break; Q_ASSERT(dynamic_cast(aliasDecl)); NamespaceAliasDeclaration* alias = static_cast(aliasDecl); foundAlias = true; QualifiedIdentifier importIdentifier = alias->importIdentifier(); if(importIdentifier.isEmpty()) { qCDebug(LANGUAGE) << "found empty import"; continue; } if(buddy->alreadyImporting( importIdentifier )) continue; //This import has already been applied to this search ApplyAliasesBuddyInfo info(1, buddy, importIdentifier); if(identifier->next.isEmpty()) { //Just insert the aliased namespace identifier if(!accept(importIdentifier)) return false; }else{ //Create an identifiers where namespace-alias part is replaced with the alias target for (const SearchItem::Ptr& item : identifier->next) if(!applyAliases(importIdentifier, item, accept, position, canBeNamespace, &info, recursionDepth+1)) return false; } } } } } if(!foundAlias) { //If we haven't found an alias, put the current versions into the result list. Additionally we will compute the identifiers transformed through "using". if(identifier->next.isEmpty()) { if(!accept(id)) //We're at the end of a qualified identifier, accept it return false; } else { for (const SearchItem::Ptr& next : identifier->next) if(!applyAliases(id, next, accept, position, canBeNamespace, 0, recursionDepth+1)) return false; } } /*if( !prefix.explicitlyGlobal() || !prefix.isEmpty() ) {*/ ///@todo check iso c++ if using-directives should be respected on top-level when explicitly global ///@todo this is bad for a very big repository(the chains should be walked for the top-context instead) //Find all namespace-imports at given scope { QualifiedIdentifier importId(previous); importId.push(globalIndexedImportIdentifier()); #ifdef DEBUG_SEARCH // qCDebug(LANGUAGE) << "checking imports in" << (backPointer ? id.toString() : QStringLiteral("global")); #endif if(importId.inRepository()) { //This iterator efficiently filters the visible declarations out of all declarations PersistentSymbolTable::FilteredDeclarationIterator filter = PersistentSymbolTable::self().getFilteredDeclarations(importId, recursiveImportIndices()); if(filter) { DeclarationChecker check(this, position, AbstractType::Ptr(), NoSearchFlags, 0); for(; filter; ++filter) { Declaration* importDecl = filter->data(); if(!importDecl) continue; //We must never break or return from this loop, because else we might be creating a bad cache if(!check(importDecl)) continue; //Search for the identifier with the import-identifier prepended Q_ASSERT(dynamic_cast(importDecl)); NamespaceAliasDeclaration* alias = static_cast(importDecl); #ifdef DEBUG_SEARCH qCDebug(LANGUAGE) << "found import of" << alias->importIdentifier().toString(); #endif QualifiedIdentifier importIdentifier = alias->importIdentifier(); if(importIdentifier.isEmpty()) { qCDebug(LANGUAGE) << "found empty import"; continue; } if(buddy->alreadyImporting( importIdentifier )) continue; //This import has already been applied to this search ApplyAliasesBuddyInfo info(2, buddy, importIdentifier); if(previous != importIdentifier) if(!applyAliases(importIdentifier, identifier, accept, importDecl->topContext() == this ? importDecl->range().start : position, canBeNamespace, &info, recursionDepth+1)) return false; } } } } return true; } template void TopDUContext::applyAliases( const SearchItem::PtrList& identifiers, Acceptor& acceptor, const CursorInRevision& position, bool canBeNamespace ) const { QualifiedIdentifier emptyId; for (const SearchItem::Ptr& item : identifiers) applyAliases(emptyId, item, acceptor, position, canBeNamespace, 0, 0); } TopDUContext * TopDUContext::topContext() const { return const_cast(this); } bool TopDUContext::deleting() const { return m_dynamicData->m_deleting; } QList TopDUContext::problems() const { ENSURE_CAN_READ const auto data = d_func(); QList ret; ret.reserve(data->m_problemsSize()); for (uint i = 0; i < data->m_problemsSize(); ++i) { ret << ProblemPointer(data->m_problems()[i].data(this)); } return ret; } void TopDUContext::setProblems(const QList& problems) { ENSURE_CAN_WRITE clearProblems(); for (const auto& problem : problems) { addProblem(problem); } } void TopDUContext::addProblem(const ProblemPointer& problem) { ENSURE_CAN_WRITE Q_ASSERT(problem); auto data = d_func_dynamic(); // store for indexing LocalIndexedProblem indexedProblem(problem, this); Q_ASSERT(indexedProblem.isValid()); data->m_problemsList().append(indexedProblem); Q_ASSERT(indexedProblem.data(this)); } void TopDUContext::clearProblems() { ENSURE_CAN_WRITE d_func_dynamic()->m_problemsList().clear(); m_dynamicData->clearProblems(); } QVector TopDUContext::importers() const { ENSURE_CAN_READ return QVector::fromList( m_local->m_directImporters.toList() ); } QList TopDUContext::loadedImporters() const { ENSURE_CAN_READ return m_local->m_directImporters.toList(); } QVector TopDUContext::importedParentContexts() const { ENSURE_CAN_READ return DUContext::importedParentContexts(); } bool TopDUContext::imports(const DUContext * origin, const CursorInRevision& position) const { return importsPrivate(origin, position); } bool TopDUContext::importsPrivate(const DUContext * origin, const CursorInRevision& position) const { Q_UNUSED(position); if( const TopDUContext* top = dynamic_cast(origin) ) { QMutexLocker lock(&importStructureMutex); bool ret = recursiveImportIndices().contains(IndexedTopDUContext(const_cast(top))); if(top == this) Q_ASSERT(ret); return ret; } else { //Cannot import a non top-context return false; } } void TopDUContext::clearImportedParentContexts() { if(usingImportsCache()) { d_func_dynamic()->m_importsCache = IndexedRecursiveImports(); d_func_dynamic()->m_importsCache.insert(IndexedTopDUContext(this)); } DUContext::clearImportedParentContexts(); m_local->clearImportedContextsRecursively(); Q_ASSERT(m_local->m_recursiveImports.count() == 0); Q_ASSERT(m_local->m_indexedRecursiveImports.count() == 1); Q_ASSERT(imports(this, CursorInRevision::invalid())); } void TopDUContext::addImportedParentContext(DUContext* context, const CursorInRevision& position, bool anonymous, bool temporary) { if(context == this) return; if(!dynamic_cast(context)) { //We cannot do this, because of the extended way we treat top-context imports. qCDebug(LANGUAGE) << "tried to import a non top-context into a top-context. This is not possible."; return; } //Always make the contexts anonymous, because we care about importers in TopDUContextLocalPrivate DUContext::addImportedParentContext(context, position, anonymous, temporary); m_local->addImportedContextRecursively(static_cast(context), temporary, true); } void TopDUContext::removeImportedParentContext(DUContext* context) { DUContext::removeImportedParentContext(context); m_local->removeImportedContextRecursively(static_cast(context), true); } void TopDUContext::addImportedParentContexts(const QList >& contexts, bool temporary) { typedef QPair Pair; foreach(const Pair &pair, contexts) addImportedParentContext(pair.first, pair.second, false, temporary); } void TopDUContext::removeImportedParentContexts(const QList& contexts) { foreach(TopDUContext* context, contexts) DUContext::removeImportedParentContext(context); m_local->removeImportedContextsRecursively(contexts, true); } /// Returns true if this object is registered in the du-chain. If it is not, all sub-objects(context, declarations, etc.) bool TopDUContext::inDUChain() const { return m_local->m_inDuChain; } /// This flag is only used by DUChain, never change it from outside. void TopDUContext::setInDuChain(bool b) { m_local->m_inDuChain = b; } bool TopDUContext::isOnDisk() const { ///@todo Change this to releasingToDisk, and only enable it while saving a top-context to disk. return m_dynamicData->isOnDisk(); } void TopDUContext::clearUsedDeclarationIndices() { ENSURE_CAN_WRITE for(unsigned int a = 0; a < d_func()->m_usedDeclarationIdsSize(); ++a) DUChain::uses()->removeUse(d_func()->m_usedDeclarationIds()[a], this); d_func_dynamic()->m_usedDeclarationIdsList().clear(); } void TopDUContext::deleteUsesRecursively() { clearUsedDeclarationIndices(); KDevelop::DUContext::deleteUsesRecursively(); } Declaration* TopDUContext::usedDeclarationForIndex(unsigned int declarationIndex) const { ENSURE_CAN_READ if(declarationIndex & (1<<31)) { //We use the highest bit to mark direct indices into the local declarations - declarationIndex &= (0xffffffff - (1<<31)); //unset the highest bit + declarationIndex &= ~(1<<31); //unset the highest bit return m_dynamicData->getDeclarationForIndex(declarationIndex); }else if(declarationIndex < d_func()->m_usedDeclarationIdsSize()) return d_func()->m_usedDeclarationIds()[declarationIndex].getDeclaration(this); else return 0; } int TopDUContext::indexForUsedDeclaration(Declaration* declaration, bool create) { if(create) { ENSURE_CAN_WRITE }else{ ENSURE_CAN_READ } if(!declaration) { return std::numeric_limits::max(); } if(declaration->topContext() == this && !declaration->inSymbolTable() && !m_dynamicData->isTemporaryDeclarationIndex(declaration->ownIndex())) { uint index = declaration->ownIndex(); Q_ASSERT(!(index & (1<<31))); return (int)(index | (1<<31)); //We don't put context-local declarations into the list, that's a waste. We just use the mark them with the highest bit. } DeclarationId id(declaration->id()); int index = -1; uint size = d_func()->m_usedDeclarationIdsSize(); const DeclarationId* ids = d_func()->m_usedDeclarationIds(); ///@todo Make m_usedDeclarationIds sorted, and find the decl. using binary search for(unsigned int a = 0; a < size; ++a) if(ids[a] == id) { index = a; break; } if(index != -1) return index; if(!create) return std::numeric_limits::max(); d_func_dynamic()->m_usedDeclarationIdsList().append(id); if(declaration->topContext() != this) DUChain::uses()->addUse(id, this); return d_func()->m_usedDeclarationIdsSize()-1; } QList allUses(TopDUContext* context, Declaration* declaration, bool noEmptyRanges) { QList ret; int declarationIndex = context->indexForUsedDeclaration(declaration, false); if(declarationIndex == std::numeric_limits::max()) return ret; return allUses(context, declarationIndex, noEmptyRanges); } QExplicitlySharedDataPointer TopDUContext::ast() const { return m_local->m_ast; } void TopDUContext::clearAst() { setAst(QExplicitlySharedDataPointer(0)); } IndexedString TopDUContext::url() const { return d_func()->m_url; } } diff --git a/language/editor/modificationrevisionset.cpp b/language/editor/modificationrevisionset.cpp index a14e930303..af23f32abe 100644 --- a/language/editor/modificationrevisionset.cpp +++ b/language/editor/modificationrevisionset.cpp @@ -1,329 +1,329 @@ /* 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 "modificationrevisionset.h" #include "util/debug.h" #include #include #include //When uncommented, the reason for needed updates is printed // #define DEBUG_NEEDSUPDATE namespace KDevelop { QMutex modificationRevisionSetMutex(QMutex::Recursive); struct FileModificationPair { KDevelop::IndexedString file; KDevelop::ModificationRevision revision; FileModificationPair() { } FileModificationPair(KDevelop::IndexedString _file, KDevelop::ModificationRevision _revision) : file(_file), revision(_revision) { } unsigned int hash() const { return ((file.hash() + revision.modificationTime) * 17 + revision.revision) * 73; } unsigned short int itemSize() const { return sizeof(FileModificationPair); } bool operator==(const FileModificationPair& rhs) const { return file == rhs.file && revision == rhs.revision; } }; struct FileModificationPairRequest { FileModificationPairRequest(const FileModificationPair& data) : m_data(data) { } const FileModificationPair& m_data; enum { AverageSize = sizeof(FileModificationPair) }; unsigned int hash() const { return m_data.hash(); } uint itemSize() const { return m_data.itemSize(); } void createItem(FileModificationPair* item) const { new (item) FileModificationPair(m_data); } bool equals(const FileModificationPair* item) const { return *item == m_data; } static void destroy(FileModificationPair* item, KDevelop::AbstractItemRepository&) { item->~FileModificationPair(); } static bool persistent(const FileModificationPair* /*item*/) { return true; //Reference-counting is done implicitly using the set-repository } }; typedef KDevelop::ItemRepository FileModificationPairRepository; static FileModificationPairRepository& fileModificationPairRepository() { static FileModificationPairRepository rep("file modification repository"); rep.setMutex(&modificationRevisionSetMutex); return rep; } void initModificationRevisionSetRepository() { fileModificationPairRepository(); } QHash > needsUpdateCache; void ModificationRevisionSet::clearCache() { QMutexLocker lock(&modificationRevisionSetMutex); ///@todo More intelligent clearing. We actually need to watch the directory for changes, and if there are changes, clear the cache. needsUpdateCache.clear(); } struct FileModificationSetRepository : public Utils::BasicSetRepository { FileModificationSetRepository() : Utils::BasicSetRepository("file modification sets", &globalItemRepositoryRegistry(), true) { } - virtual void itemRemovedFromSets(uint index) override; + void itemRemovedFromSets(uint index) override; }; //FileModificationSetRepository fileModificationSetRepository; struct FileModificationSetRepositoryRepresenter { static FileModificationSetRepository& repository() { static FileModificationSetRepository fileModificationSetRepository; return fileModificationSetRepository; } }; ModificationRevisionSet::ModificationRevisionSet(unsigned int index) : m_index(index) { } uint ModificationRevisionSet::size() const { Utils::Set set = Utils::Set(m_index, &FileModificationSetRepositoryRepresenter::repository()); return set.count(); } void ModificationRevisionSet::clear() { QMutexLocker lock(&modificationRevisionSetMutex); if(m_index) { Utils::Set oldModificationTimes = Utils::Set(m_index, &FileModificationSetRepositoryRepresenter::repository()); oldModificationTimes.staticUnref(); m_index = 0; } } void ModificationRevisionSet::addModificationRevision(const IndexedString& url, const KDevelop::ModificationRevision& revision) { QMutexLocker lock(&modificationRevisionSetMutex); if(m_index == 0) { Utils::Set set = FileModificationSetRepositoryRepresenter::repository().createSet(fileModificationPairRepository().index(FileModificationPair(url, revision))); set.staticRef(); m_index = set.setIndex(); }else{ Utils::Set oldModificationTimes = Utils::Set(m_index, &FileModificationSetRepositoryRepresenter::repository()); Utils::Set newModificationTimes = oldModificationTimes; Utils::Set tempSet = FileModificationSetRepositoryRepresenter::repository().createSet(fileModificationPairRepository().index(FileModificationPair(url, revision))); tempSet.staticRef(); newModificationTimes += tempSet; newModificationTimes.staticRef(); oldModificationTimes.staticUnref(); tempSet.staticUnref(); m_index = newModificationTimes.setIndex(); } } bool ModificationRevisionSet::removeModificationRevision(const IndexedString& url, const KDevelop::ModificationRevision& revision) { QMutexLocker lock(&modificationRevisionSetMutex); if(!m_index) return false; Utils::Set oldModificationTimes = Utils::Set(m_index, &FileModificationSetRepositoryRepresenter::repository()); Utils::Set newModificationTimes = oldModificationTimes; Utils::Set tempSet = FileModificationSetRepositoryRepresenter::repository().createSet(fileModificationPairRepository().index(FileModificationPair(url, revision))); tempSet.staticRef(); newModificationTimes -= tempSet; newModificationTimes.staticRef(); oldModificationTimes.staticUnref(); tempSet.staticUnref(); m_index = newModificationTimes.setIndex(); return m_index != oldModificationTimes.setIndex(); } // const QMap ModificationRevisionSet::allModificationTimes() const { // QMap ret; // Utils::Set::Iterator it = m_allModificationTimes.iterator(); // while(it) { // const FileModificationPair* data = fileModificationPairRepository().itemFromIndex(*it); // ret[data->file] = data->revision; // ++it; // } // return ret; // } typedef Utils::VirtualSetNode, FileModificationSetRepositoryRepresenter> ModificationRevisionSetNode; // static bool (const Utils::SetNodeData* node) { // ModificationRevisionSetNode // if(!node) // return false; // } static bool nodeNeedsUpdate(uint index) { QMutexLocker lock(&modificationRevisionSetMutex); if(!index) return false; const auto currentTime = QDateTime::currentDateTime(); auto cached = needsUpdateCache.constFind(index); if(cached != needsUpdateCache.constEnd()) { if((*cached).first.secsTo(currentTime) < cacheModificationTimesForSeconds ) { return cached->second; } } bool result = false; const Utils::SetNodeData* nodeData = FileModificationSetRepositoryRepresenter::repository().nodeFromIndex(index); if(nodeData->contiguous()) { //Do the actual checking for(unsigned int a = nodeData->start(); a < nodeData->end(); ++a) { const FileModificationPair* data = fileModificationPairRepository().itemFromIndex(a); ModificationRevision revision = KDevelop::ModificationRevision::revisionForFile( data->file ); if( revision != data->revision ) { result = true; break; } } }else{ result = nodeNeedsUpdate(nodeData->leftNode()) || nodeNeedsUpdate(nodeData->rightNode()); } needsUpdateCache.insert(index, std::make_pair(currentTime, result)); return result; } QString ModificationRevisionSet::toString() const { QMutexLocker lock(&modificationRevisionSetMutex); QString ret = "["; // krazy:exclude=doublequote_chars Utils::Set set(m_index, &FileModificationSetRepositoryRepresenter::repository()); Utils::Set::Iterator it = set.iterator(); bool first = true; while(it) { if(!first) ret += ", "; first = false; const FileModificationPair* data = fileModificationPairRepository().itemFromIndex(*it); ret += data->file.str() + ':' + data->revision.toString(); ++it; } ret += ']'; return ret; } bool ModificationRevisionSet::needsUpdate() const { QMutexLocker lock(&modificationRevisionSetMutex); #ifdef DEBUG_NEEDSUPDATE Utils::Set set(m_index, &FileModificationSetRepositoryRepresenter::repository()); Utils::Set::Iterator it = set.iterator(); while(it) { const FileModificationPair* data = fileModificationPairRepository().itemFromIndex(*it); ModificationRevision revision = KDevelop::ModificationRevision::revisionForFile( data->file ); if( revision != data->revision ) { qCDebug(LANGUAGE) << "dependency" << data->file.str() << "has changed, stored stamp:" << data->revision << "new time:" << revision ; return true; } ++it; } return false; #else return nodeNeedsUpdate(m_index); #endif } ModificationRevisionSet& ModificationRevisionSet::operator+=(const ModificationRevisionSet& rhs) { QMutexLocker lock(&modificationRevisionSetMutex); Utils::Set oldModificationTimes = Utils::Set(m_index, &FileModificationSetRepositoryRepresenter::repository()); Utils::Set otherModificationTimes = Utils::Set(rhs.m_index, &FileModificationSetRepositoryRepresenter::repository()); Utils::Set newModificationTimes = oldModificationTimes; newModificationTimes += otherModificationTimes; newModificationTimes.staticRef(); oldModificationTimes.staticUnref(); m_index = newModificationTimes.setIndex(); return *this; } ModificationRevisionSet& ModificationRevisionSet::operator-=(const ModificationRevisionSet& rhs) { QMutexLocker lock(&modificationRevisionSetMutex); Utils::Set oldModificationTimes = Utils::Set(m_index, &FileModificationSetRepositoryRepresenter::repository()); Utils::Set otherModificationTimes = Utils::Set(rhs.m_index, &FileModificationSetRepositoryRepresenter::repository()); Utils::Set newModificationTimes = oldModificationTimes; newModificationTimes -= otherModificationTimes; newModificationTimes.staticRef(); oldModificationTimes.staticUnref(); m_index = newModificationTimes.setIndex(); return *this; } void FileModificationSetRepository::itemRemovedFromSets(uint index) { fileModificationPairRepository().deleteItem(index); needsUpdateCache.remove(index); } } diff --git a/language/highlighting/codehighlighting.h b/language/highlighting/codehighlighting.h index 02fb4f9c86..d508c0fc4d 100644 --- a/language/highlighting/codehighlighting.h +++ b/language/highlighting/codehighlighting.h @@ -1,221 +1,221 @@ /* * This file is part of KDevelop * * Copyright 2007-2010 David Nolden * Copyright 2006 Hamish Rodda * Copyright 2009 Milian Wolff * * 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. */ #ifndef KDEVPLATFORM_CODEHIGHLIGHTING_H #define KDEVPLATFORM_CODEHIGHLIGHTING_H #include #include #include #include #include #include #include #include #include namespace KDevelop { class DUContext; class Declaration; typedef QVector ColorMap; class CodeHighlighting; struct HighlightingEnumContainer { enum Types { UnknownType, //Primary highlighting: LocalClassMemberType, InheritedClassMemberType, LocalVariableType, //Other highlighting: ClassType, FunctionType, ForwardDeclarationType, EnumType, EnumeratorType, TypeAliasType, MacroType, /// Declaration of a macro such as "#define FOO" MacroFunctionLikeType, /// Declaration of a function like macro such as "#define FOO()" //If none of the above match: MemberVariableType, NamespaceVariableType, GlobalVariableType, //Most of these are currently not used: ArgumentType, CodeType, FileType, NamespaceType, ScopeType, TemplateType, TemplateParameterType, FunctionVariableType, ErrorVariableType }; enum Contexts { DefinitionContext, DeclarationContext, ReferenceContext }; }; struct HighlightedRange { RangeInRevision range; KTextEditor::Attribute::Ptr attribute; bool operator<(const HighlightedRange& rhs) const { return range.start < rhs.range.start; } }; /** * Code highlighting instance that is used to apply code highlighting to one specific top context * */ class KDEVPLATFORMLANGUAGE_EXPORT CodeHighlightingInstance : public HighlightingEnumContainer { public: CodeHighlightingInstance(const CodeHighlighting* highlighting) : m_useClassCache(false), m_highlighting(highlighting) { } virtual ~CodeHighlightingInstance() { } virtual void highlightDeclaration(KDevelop::Declaration* declaration, const QColor &color); virtual void highlightUse(KDevelop::DUContext* context, int index, const QColor &color); virtual void highlightUses(KDevelop::DUContext* context); void highlightDUChain(KDevelop::TopDUContext* context); void highlightDUChain(KDevelop::DUContext* context, QHash colorsForDeclarations, ColorMap); KDevelop::Declaration* localClassFromCodeContext(KDevelop::DUContext* context) const; /** * @param context Should be the context from where the declaration is used, if a use is highlighted. * */ virtual Types typeForDeclaration(KDevelop::Declaration* dec, KDevelop::DUContext* context) const; /** * Decides whether to apply auto-generated rainbow colors to @p dec. * Default implementation only applies that to local variables in functions. */ virtual bool useRainbowColor(KDevelop::Declaration* dec) const; //A temporary hash for speedup mutable QHash m_contextClasses; //Here the colors of function context are stored until they are merged into the function body mutable QMap > m_functionColorsForDeclarations; mutable QMap m_functionDeclarationsForColors; mutable bool m_useClassCache; const CodeHighlighting* m_highlighting; QVector m_highlight; }; /** * General class representing the code highlighting for one language * */ class KDEVPLATFORMLANGUAGE_EXPORT CodeHighlighting : public QObject, public KDevelop::ICodeHighlighting, public HighlightingEnumContainer { Q_OBJECT Q_INTERFACES(KDevelop::ICodeHighlighting) public: explicit CodeHighlighting(QObject* parent); - virtual ~CodeHighlighting(); + ~CodeHighlighting() override; /// This function is thread-safe /// @warning The duchain must not be locked when this is called (->possible deadlock) void highlightDUChain(ReferencedTopDUContext context) override; //color should be zero when undecided KTextEditor::Attribute::Ptr attributeForType(Types type, Contexts context, const QColor &color) const; KTextEditor::Attribute::Ptr attributeForDepth(int depth) const; /// This function is thread-safe /// Returns whether a highlighting is already given for the given url bool hasHighlighting(IndexedString url) const override; private: //Returns whether the given attribute was set by the code highlighting, and not by something else //Always returns true when the attribute is zero bool isCodeHighlight(KTextEditor::Attribute::Ptr attr) const; protected: //Can be overridden to create an own instance type virtual CodeHighlightingInstance* createInstance() const; private: /// Highlighting of one specific document struct DocumentHighlighting { IndexedString m_document; qint64 m_waitingRevision; // The ranges are sorted by range start, so they can easily be matched QVector m_waiting; QVector m_highlightedRanges; }; QMap m_highlights; friend class CodeHighlightingInstance; mutable QHash m_definitionAttributes; mutable QHash m_declarationAttributes; mutable QHash m_referenceAttributes; mutable QList m_depthAttributes; // Should be used to enable/disable the colorization of local variables and their uses bool m_localColorization; // Should be used to enable/disable the colorization of global types and their uses bool m_globalColorization; mutable QMutex m_dataMutex; private Q_SLOTS: void clearHighlightingForDocument(KDevelop::IndexedString document); void applyHighlighting(void* highlighting); void trackerDestroyed(QObject* object); /// when the colors change we must invalidate our local caches void adaptToColorChanges(); void aboutToInvalidateMovingInterfaceContent(KTextEditor::Document*); void aboutToRemoveText(const KTextEditor::Range&); }; } #endif // kate: space-indent on; indent-width 2; replace-trailing-space-save on; show-tabs on; tab-indents on; tab-width 2; diff --git a/language/highlighting/colorcache.h b/language/highlighting/colorcache.h index 4183626431..b75c211990 100644 --- a/language/highlighting/colorcache.h +++ b/language/highlighting/colorcache.h @@ -1,182 +1,182 @@ /* * This file is part of KDevelop * * Copyright 2009 Milian Wolff * * 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. */ #ifndef KDEVPLATFORM_COLORCACHE_H #define KDEVPLATFORM_COLORCACHE_H #include #include #include #include #include namespace KTextEditor { class Document; class View; } namespace KDevelop { class CodeHighlightingColors; class IDocument; /** * A singleton which holds the global default colors, adapted to the current color scheme */ class KDEVPLATFORMLANGUAGE_EXPORT ColorCache : public QObject { Q_OBJECT public: - ~ColorCache(); + ~ColorCache() override; /// access the global color cache static ColorCache* self(); /// adapt a given foreground color to the current color scheme /// @p ratio between 0 and 255 where 0 gives @see m_foregroundColor /// and 255 gives @p color /// /// @note if you are looking for a background color, simply setting an alpha /// value should work. QColor blend(QColor color, uchar ratio) const; /// adapt a given background color to the current color scheme /// @p ratio between 0 and 255 where 0 gives @see m_foregroundColor /// and 255 gives @p color /// /// @note if you are looking for a background color, simply setting an alpha /// value should work. QColor blendBackground(QColor color, uchar ratio) const; /// blend a color for local colorization according to the user settings /// @see blend() QColor blendLocalColor(QColor color) const; /// blend a color for global colorization according to the user settings /// @see blend() QColor blendGlobalColor(QColor color) const; /// access the default colors CodeHighlightingColors* defaultColors() const; /** * @returns a primary color if @p num less primaryColorCount and a supplementary color if @p num >= primaryColorCount and < validColorCount * @see validColorCount() * @see primaryColorCount() */ QColor generatedColor(uint num) const; /** * @returns the number of primary and supplementary colors * * @see generatedColor() * @see primaryColorCount() */ uint validColorCount() const; /** * @returns number of primary colors * * When you run out of primary colors use supplementary colors */ uint primaryColorCount() const; /// access the foreground color QColor foregroundColor() const; signals: /// will be emitted whenever the colors got changed /// @see update() void colorsGotChanged(); private slots: /// if necessary, adapt to the colors of this document void slotDocumentActivated(); /// settings got changed, update to the settings of the sender void slotViewSettingsChanged(); /// will regenerate colors from global KDE color scheme void updateColorsFromScheme(); /// will regenerate colors with the proper intensity settings void updateColorsFromSettings(); /// regenerate colors and emits @p colorsGotChanged() /// and finally triggers a rehighlight of the opened documents void updateInternal(); bool tryActiveDocument(); private: ColorCache(QObject *parent = 0); static ColorCache* m_self; /// get @p totalGeneratedColors colors from the color wheel and adapt them to the current color scheme void generateColors(); /// calls @c updateInternal() delayed to prevent double loading of language plugins. void update(); /// try to access the KatePart settings for the given doc or fallback to the global KDE scheme /// and update the colors if necessary /// @see generateColors(), updateColorsFromScheme() void updateColorsFromView(KTextEditor::View* view); /// the default colors for the different types CodeHighlightingColors* m_defaultColors; /// the generated colors QList m_colors; uint m_validColorCount; uint m_primaryColorCount; /// Maybe make this configurable: An offset where to start stepping through the color wheel uint m_colorOffset; /// the text color for the current color scheme QColor m_foregroundColor; /// the editor background color color for the current color scheme QColor m_backgroundColor; /// How generated colors for local variables should be mixed with the foreground color. /// Between 0 and 255, where 255 means only foreground color, and 0 only the chosen color. uchar m_localColorRatio; /// How global colors (i.e. for types, uses, etc.) should be mixed with the foreground color. /// Between 0 and 255, where 255 means only foreground color, and 0 only the chosen color. uchar m_globalColorRatio; /// Whether declarations have to be rendered with a bold style or not. bool m_boldDeclarations; /// The view we are listening to for setting changes. QPointer m_view; }; } #endif // KDEVPLATFORM_COLORCACHE_H // kate: space-indent on; indent-width 2; replace-trailing-space-save on; show-tabs on; tab-indents on; tab-width 2; diff --git a/language/interfaces/quickopendataprovider.h b/language/interfaces/quickopendataprovider.h index 8d88feb1a6..2e7d0ce5ff 100644 --- a/language/interfaces/quickopendataprovider.h +++ b/language/interfaces/quickopendataprovider.h @@ -1,206 +1,206 @@ /* * This file is part of KDevelop * * Copyright 2007 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. */ #ifndef KDEVPLATFORM_QUICKOPENDATAPROVIDER_H #define KDEVPLATFORM_QUICKOPENDATAPROVIDER_H #include #include #include #include #include class QString; class QStringList; class QIcon; namespace KDevelop { class IndexedString; /** * Hint: When implementing a data-provider, do not forget to export it! Else it won't work. * */ /** * If your plugin manages a list of files, you can use this to return that list. * The file-list can be queried by other data-providers(for example functions/methods) so they * can manipulate their content based on those file-lists. The file-list should not be filtered at all, * it should only depend on the enabled models/items * * Example: A list of files in the include-path, a list of files in the project, etc. * */ class KDEVPLATFORMLANGUAGE_EXPORT QuickOpenFileSetInterface { public: virtual QSet files() const = 0; virtual ~QuickOpenFileSetInterface(); }; /** * You can use this as additional base-class for your embedded widgets to get additional interaction * */ class KDEVPLATFORMLANGUAGE_EXPORT QuickOpenEmbeddedWidgetInterface { public: virtual ~QuickOpenEmbeddedWidgetInterface(); ///Is called when the keyboard-shortcut "next" is triggered on the widget, which currently is SHIFT+Right virtual void next() = 0; ///Is called when the keyboard-shortcut "previous" is triggered on the widget, which currently is SHIFT+Left virtual void previous() = 0; ///Is called when the keyboard-shortcut "accept" is triggered on the widget, which currently is SHIFT+Return virtual void accept() = 0; ///Is called when the keyboard-shortcut "scroll up" is triggered on the widget, which currently is SHIFT+Up virtual void up() = 0; ///Is called when the keyboard-shortcut "scroll down" is triggered on the widget, which currently is SHIFT+Down virtual void down() = 0; }; /** * Reimplement this to represent single entries within the quickopen list. * */ class KDEVPLATFORMLANGUAGE_EXPORT QuickOpenDataBase : public QSharedData { public: virtual ~QuickOpenDataBase(); ///Return the text to be shown in the list for this item virtual QString text() const = 0; virtual QString htmlDescription() const = 0; /**Can return Custom highlighting triplets as explained in * the kde header ktexteditor/codecompletionmodel.h * The default-implementation returns an empty list, which means no * special highlighting will be applied. * */ virtual QList highlighting() const; /** * May return an icon to mark the item in the quickopen-list. * The standard-implementation returns an invalid item, which means that * no icon will be shown. * */ virtual QIcon icon() const; /** * Is called when the item should be executed. * * @param filterText Current content of the quickopen-dialogs filter line-edit. * If this is changed, and false is returned, the content of the * line-edit will be changed according to the new text. * @return Whether the dialog should be closed. * */ virtual bool execute( QString& filterText ) = 0; /** * Return true here if this data-item should be expandable with * an own embedded widget. * The default-implementation returns false. * */ virtual bool isExpandable() const; /** * This will be called if isExpandable() returns true. * * A widget should be returned that will be embedded into the quickopen-list. * The widget will be owned by the quickopen-list and will be deleted at will. * * If the widget can be dynamic_cast'ed to QuickOpenEmbeddedWidgetInterface, * the additional interaction defined there will be possible. * * The default-implementation returns 0, which means no widget will be shown. * */ virtual QWidget* expandingWidget() const; }; typedef QExplicitlySharedDataPointer QuickOpenDataPointer; /** * Use this interface to provide custom quickopen-data to the quickopen-widget. * * If possible, you should use KDevelop::Filter (@file quickopenfilter.h ) * to implement the actual filtering, so it is consistent. * */ class KDEVPLATFORMLANGUAGE_EXPORT QuickOpenDataProviderBase : public QObject { Q_OBJECT public: - virtual ~QuickOpenDataProviderBase(); + ~QuickOpenDataProviderBase() override; /** * For efficiency, all changes to the filter-text are provided by the following 3 difference-operations. * */ /** * Search-text was changed. * This is called whenever the search-text was changed, and the UI should be updated. * Store the text to track the exact difference. * */ virtual void setFilterText( const QString& text ) = 0; /** * Filter-text should be completely reset and the context re-computed. * */ virtual void reset() = 0; /** * Returns the count of items this provider currently represents * */ virtual uint itemCount() const = 0; /** * Returns the count of *unfiltered* items this provider currently represents */ virtual uint unfilteredItemCount() const = 0; /** * Returns the data-item for a given row. * * Generally, the items must addressed alphabetically, * they will be displayed in the same order in the * quickopen list. * * For performance-reasons the underlying models should * create the QuickOpenDataBase items on demand, because only * those that will really be shown will be requested. * * @param row Index of item to be returned. * */ virtual QuickOpenDataPointer data( uint row ) const = 0; /** * If the data-provider supports multiple different scopes/items, this will be called * with the enabled scopes/items. * If the data-provider supports only one scope/item, this can be ignored. * The lists contains all scopes/items, even those that are not supported by this provider. * */ virtual void enableData( const QStringList& items, const QStringList& scopes ); }; /** * Try parsing string according to "path_to_file":"line number" template. "line number" may be empty. * @param from Source string * @param path Set to parsed path to file, or left unchanged if @ref from doesn't match the template. May refer to the same object as @ref from * @param lineNumber Set to parsed line number, zero if "line number" is empty or left unchanged if @ref from doesn't match the template. * @return Whether @ref from did match the expected template. * */ bool KDEVPLATFORMLANGUAGE_EXPORT extractLineNumber(const QString& from, QString& path, uint& lineNumber); } #endif diff --git a/outputview/outputexecutejob.h b/outputview/outputexecutejob.h index b30cb34c4b..aadba6606d 100644 --- a/outputview/outputexecutejob.h +++ b/outputview/outputexecutejob.h @@ -1,250 +1,250 @@ /* This file is part of KDevelop C opyright 2012 Ivan Shapoval*ov 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 KDEVPLATFORM_OUTPUTEXECUTEJOB_H #define KDEVPLATFORM_OUTPUTEXECUTEJOB_H #include "outputjob.h" #include "outputmodel.h" #include #include class KProcess; namespace KDevelop { class ProcessLineMaker; class OutputExecuteJobPrivate; class KDEVPLATFORMOUTPUTVIEW_EXPORT OutputExecuteJob : public OutputJob { Q_OBJECT public: enum JobStatus { JobRunning = 0, /**< The job is running */ JobSucceeded = 1, /**< The job has succeeded */ JobCanceled = 2, /**< The job has been cancelled */ JobFailed = 3, /**< The job has failed */ JobNotStarted = 4 /**< The job hasn't been started so far */ }; enum { InvalidWorkingDirectoryError = OutputJob::UserDefinedError, UserDefinedError }; enum JobProperty { AppendProcessString = 0x001, /**< Whether to append a process string to the user-specified job name */ NeedWorkingDirectory = 0x002, /**< Whether to require a non-empty working directory to be provided */ CheckWorkingDirectory = 0x004, /**< Whether to check that the working directory actually exists (and not to create it if needed) */ PortableMessages = 0x008, /**< Whether to set LC_MESSAGES=C in the process' environment */ DisplayStdout = 0x010, /**< Whether to pass process' stdout to the output model */ DisplayStderr = 0x020, /**< Whether to pass process' stderr to the output model */ NoSilentOutput = 0x040, /**< Whether to call \ref startOutput() only if verbosity is \ref OutputJob::Verbose */ PostProcessOutput = 0x080, /**< Whether to connect line maker's signals to \ref postProcessStdout() and \ref postProcessStderr() */ IsBuilderHint = 0x100, /**< Whether to use builder-specific messages to talk to user (e. g. "build directory" instead of "working directory" */ }; Q_FLAGS(JobProperty JobProperties) Q_DECLARE_FLAGS(JobProperties, JobProperty) OutputExecuteJob( QObject* parent = 0, OutputJobVerbosity verbosity = OutputJob::Verbose ); - virtual ~OutputExecuteJob(); + ~OutputExecuteJob() override; /** * Get the job's status (associated with the process). * * @returns The job's status. * @see JobStatus */ JobStatus status() const; /** * Get the job's output model. * * @returns The job's output model, downcasted to \ref OutputModel */ OutputModel* model() const; /** * Returns a working directory for the job's process. * * @returns URL which has been set through \ref setWorkingDirectory(); empty URL if unset. */ virtual QUrl workingDirectory() const; /** * Set a working directory for the job's process. * Effective if \ref workingDirectory() hasn't been overridden. * * @param directory a valid local directory URL, or an empty URL to unset. */ void setWorkingDirectory( const QUrl& directory ); /** * Get process' command line. * * @returns The command line for the process, with first element in list being the program path. */ virtual QStringList commandLine() const; /** * Append an element to the command line argument list for this process. * If no executable is set yet, it will be set instead. * Effective if \ref commandLine() hasn't been overridden. * * @param argument the argument to add */ OutputExecuteJob& operator<<( const QString& argument ); /** * Append a list of elements to the command line argument list for this process. * If no executable is set yet, it will be set from the first argument in given list. * Effective if \ref commandLine() hasn't been overridden. * * @param arguments the arguments to add */ OutputExecuteJob& operator<<( const QStringList& arguments ); /** * Get the privilege escalation command ("su", "sudo", etc.) used for the job's process. * * @returns The privilege escalation command name and arguments; empty list if not set. */ virtual QStringList privilegedExecutionCommand() const; /** * Set the privilege escalation command ("su", "sudo", etc.) which will be used for the job's process. * Effective if \ref privilegedExecutionCommand() hasn't been overridden. * * @param command The privilege escalation command's name and arguments; empty list to unset. * @see privilegedCommand */ void setPrivilegedExecutionCommand( const QStringList& command ); /** * A convenience function to set the job name. * * Calls \ref setTitle() and \ref setObjectName(). * * @note If you need the command-line to be appended to the job name, * make sure that it is already configured upon calling this function. * * @param name The name to set; empty string to use default (process string). */ void setJobName( const QString& name ); /** * Set the filtering strategy for the output model. */ void setFilteringStrategy( OutputModel::OutputFilterStrategy strategy ); /** * Get the current properties of the job. * * @note Default-set properties are: \ref DisplayStdout. */ virtual JobProperties properties() const; /** * Set properties of the job. * Effective if \ref properties() hasn't been overridden. * * @param properties Which flags to add to the job. * @param override Whether to assign instead of doing bitwise OR. * @see JobProperties, properties(), unsetProperties() */ void setProperties( JobProperties properties, bool override = false ); /** * Unset properties of the job. * * @param properties Which flags to remove from the job * @see JobProperties, properties(), setProperties() */ void unsetProperties( JobProperties properties ); /** * Add a variable to the job's process environment. * * The variables added with this method override ones from the system environment and * the global environment profile, but are overridden by "PortableMessages" property. * * @param name The name of a variable to add * @param value The value of a variable to add; empty string to unset. */ void addEnvironmentOverride( const QString& name, const QString& value ); /** * Remove a variable from the override set. * * @param name The name of a variable to remove. * @note This does not force a variable to empty value; this is to undo the overriding itself. */ void removeEnvironmentOverride( const QString& name ); /** * Get the global environment profile name for the job's process. * * @returns The environment profile name to use in the job's process; empty if unset. */ virtual QString environmentProfile() const; /** * Set the environment profile name for the job's process. * Effective if \ref environmentProfile() hasn't been overridden. * * @param profile The name of profile to set. */ void setEnvironmentProfile( const QString& profile ); - virtual void start(); + void start() override; protected: - virtual bool doKill(); + bool doKill() override; protected slots: // Redefine these functions if you want to post-process the output somehow // before it hits the output model. // Default implementations for either function call "model()->appendLines( lines );". // Do the same if you need the output to be visible. virtual void postProcessStdout( const QStringList& lines ); virtual void postProcessStderr( const QStringList& lines ); // Redefine these functions if you want to handle process' exit codes in a special manner. // One possible usage is in "cvs diff" job which returns 1 on success. virtual void childProcessExited( int exitCode, QProcess::ExitStatus exitStatus ); virtual void childProcessError( QProcess::ProcessError processError ); private: OutputExecuteJobPrivate* d; Q_PRIVATE_SLOT(d, void childProcessStdout()); Q_PRIVATE_SLOT(d, void childProcessStderr()); }; } // namespace KDevelop Q_DECLARE_OPERATORS_FOR_FLAGS(KDevelop::OutputExecuteJob::JobProperties); #endif // KDEVPLATFORM_OUTPUTEXECUTEJOB_H diff --git a/outputview/outputmodel.cpp b/outputview/outputmodel.cpp index fe70067f74..046626683e 100644 --- a/outputview/outputmodel.cpp +++ b/outputview/outputmodel.cpp @@ -1,414 +1,421 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2007 Andreas Pakulat * * Copyright 2010 Aleix Pol Gonzalez * * Copyright (C) 2012 Morten Danielsen Volden mvolden2@gmail.com * * * * 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 Library 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 "outputmodel.h" #include "filtereditem.h" #include "outputfilteringstrategies.h" #include "debug.h" #include #include +#include #include #include #include #include #include #include +#include #include Q_DECLARE_METATYPE(QVector) Q_DECLARE_METATYPE(KDevelop::IFilterStrategy*) namespace KDevelop { /** * Number of lines that are processed in one go before we notify the GUI thread * about the result. It is generally faster to add multiple items to a model * in one go compared to adding each item independently. */ static const int BATCH_SIZE = 50; /** * Time in ms that we wait in the parse worker for new incoming lines before * actually processing them. If we already have enough for one batch though * we process immediately. */ static const int BATCH_AGGREGATE_TIME_DELAY = 50; class ParseWorker : public QObject { Q_OBJECT public: ParseWorker() : QObject(0) - , m_filter( new NoFilterStrategy ) + , m_filter(new NoFilterStrategy) , m_timer(new QTimer(this)) { m_timer->setInterval(BATCH_AGGREGATE_TIME_DELAY); m_timer->setSingleShot(true); connect(m_timer, &QTimer::timeout, this, &ParseWorker::process); } public slots: void changeFilterStrategy( KDevelop::IFilterStrategy* newFilterStrategy ) { m_filter = QSharedPointer( newFilterStrategy ); } void addLines( const QStringList& lines ) { m_cachedLines << lines; if (m_cachedLines.size() >= BATCH_SIZE) { // if enough lines were added, process immediately m_timer->stop(); process(); } else if (!m_timer->isActive()) { m_timer->start(); } } void flushBuffers() { m_timer->stop(); process(); emit allDone(); } signals: void parsedBatch(const QVector& filteredItems); void allDone(); private slots: /** * Process *all* cached lines, emit parsedBatch for each batch */ void process() { QVector filteredItems; filteredItems.reserve(qMin(BATCH_SIZE, m_cachedLines.size())); + // apply pre-filtering functions + std::transform(m_cachedLines.constBegin(), m_cachedLines.constEnd(), + m_cachedLines.begin(), &KDevelop::stripAnsiSequences); + + // apply filtering strategy foreach(const QString& line, m_cachedLines) { FilteredItem item = m_filter->errorInLine(line); if( item.type == FilteredItem::InvalidItem ) { item = m_filter->actionInLine(line); } filteredItems << item; if( filteredItems.size() == BATCH_SIZE ) { emit parsedBatch(filteredItems); filteredItems.clear(); filteredItems.reserve(qMin(BATCH_SIZE, m_cachedLines.size())); } } // Make sure to emit the rest as well if( !filteredItems.isEmpty() ) { emit parsedBatch(filteredItems); } m_cachedLines.clear(); } private: QSharedPointer m_filter; QStringList m_cachedLines; QTimer* m_timer; }; class ParsingThread { public: ParsingThread() { m_thread.setObjectName("OutputFilterThread"); } virtual ~ParsingThread() { if (m_thread.isRunning()) { m_thread.quit(); m_thread.wait(); } } void addWorker(ParseWorker* worker) { if (!m_thread.isRunning()) { m_thread.start(); } worker->moveToThread(&m_thread); } private: QThread m_thread; }; Q_GLOBAL_STATIC(ParsingThread, s_parsingThread); struct OutputModelPrivate { OutputModelPrivate( OutputModel* model, const QUrl& builddir = QUrl() ); ~OutputModelPrivate(); bool isValidIndex( const QModelIndex&, int currentRowCount ) const; OutputModel* model; ParseWorker* worker; QVector m_filteredItems; // We use std::set because that is ordered std::set m_errorItems; // Indices of all items that we want to move to using previous and next QUrl m_buildDir; void linesParsed(const QVector& items) { model->beginInsertRows( QModelIndex(), model->rowCount(), model->rowCount() + items.size() - 1); foreach( const FilteredItem& item, items ) { if( item.type == FilteredItem::ErrorItem ) { m_errorItems.insert(m_filteredItems.size()); } m_filteredItems << item; } model->endInsertRows(); } }; OutputModelPrivate::OutputModelPrivate( OutputModel* model_, const QUrl& builddir) : model(model_) , worker(new ParseWorker ) , m_buildDir( builddir ) { qRegisterMetaType >(); qRegisterMetaType(); s_parsingThread->addWorker(worker); model->connect(worker, &ParseWorker::parsedBatch, model, [=] (const QVector& items) { linesParsed(items); }); model->connect(worker, &ParseWorker::allDone, model, &OutputModel::allDone); } bool OutputModelPrivate::isValidIndex( const QModelIndex& idx, int currentRowCount ) const { return ( idx.isValid() && idx.row() >= 0 && idx.row() < currentRowCount && idx.column() == 0 ); } OutputModelPrivate::~OutputModelPrivate() { worker->deleteLater(); } OutputModel::OutputModel( const QUrl& builddir, QObject* parent ) : QAbstractListModel(parent) , d( new OutputModelPrivate( this, builddir ) ) { } OutputModel::OutputModel( QObject* parent ) : QAbstractListModel(parent) , d( new OutputModelPrivate( this ) ) { } OutputModel::~OutputModel() { delete d; } QVariant OutputModel::data(const QModelIndex& idx , int role ) const { if( d->isValidIndex(idx, rowCount()) ) { switch( role ) { case Qt::DisplayRole: return d->m_filteredItems.at( idx.row() ).shortenedText; break; case OutputModel::OutputItemTypeRole: return static_cast(d->m_filteredItems.at( idx.row() ).type); break; case Qt::FontRole: return QFontDatabase::systemFont(QFontDatabase::FixedFont); break; default: break; } } return QVariant(); } int OutputModel::rowCount( const QModelIndex& parent ) const { if( !parent.isValid() ) return d->m_filteredItems.count(); return 0; } QVariant OutputModel::headerData( int, Qt::Orientation, int ) const { return QVariant(); } void OutputModel::activate( const QModelIndex& index ) { if( index.model() != this || !d->isValidIndex(index, rowCount()) ) { return; } qCDebug(OUTPUTVIEW) << "Model activated" << index.row(); FilteredItem item = d->m_filteredItems.at( index.row() ); if( item.isActivatable ) { qCDebug(OUTPUTVIEW) << "activating:" << item.lineNo << item.url; KTextEditor::Cursor range( item.lineNo, item.columnNo ); KDevelop::IDocumentController *docCtrl = KDevelop::ICore::self()->documentController(); QUrl url = item.url; if (item.url.isEmpty()) { qWarning() << "trying to open empty url"; return; } if(url.isRelative()) { url = d->m_buildDir.resolved(url); } Q_ASSERT(!url.isRelative()); docCtrl->openDocument( url, range ); } else { qCDebug(OUTPUTVIEW) << "not an activateable item"; } } QModelIndex OutputModel::nextHighlightIndex( const QModelIndex ¤tIdx ) { int startrow = d->isValidIndex(currentIdx, rowCount()) ? currentIdx.row() + 1 : 0; if( !d->m_errorItems.empty() ) { qCDebug(OUTPUTVIEW) << "searching next error"; // Jump to the next error item std::set< int >::const_iterator next = d->m_errorItems.lower_bound( startrow ); if( next == d->m_errorItems.end() ) next = d->m_errorItems.begin(); return index( *next, 0, QModelIndex() ); } for( int row = 0; row < rowCount(); ++row ) { int currow = (startrow + row) % rowCount(); if( d->m_filteredItems.at( currow ).isActivatable ) { return index( currow, 0, QModelIndex() ); } } return QModelIndex(); } QModelIndex OutputModel::previousHighlightIndex( const QModelIndex ¤tIdx ) { //We have to ensure that startrow is >= rowCount - 1 to get a positive value from the % operation. int startrow = rowCount() + (d->isValidIndex(currentIdx, rowCount()) ? currentIdx.row() : rowCount()) - 1; if(!d->m_errorItems.empty()) { qCDebug(OUTPUTVIEW) << "searching previous error"; // Jump to the previous error item std::set< int >::const_iterator previous = d->m_errorItems.lower_bound( currentIdx.row() ); if( previous == d->m_errorItems.begin() ) previous = d->m_errorItems.end(); --previous; return index( *previous, 0, QModelIndex() ); } for ( int row = 0; row < rowCount(); ++row ) { int currow = (startrow - row) % rowCount(); if( d->m_filteredItems.at( currow ).isActivatable ) { return index( currow, 0, QModelIndex() ); } } return QModelIndex(); } void OutputModel::setFilteringStrategy(const OutputFilterStrategy& currentStrategy) { // TODO: Turn into factory, decouple from OutputModel IFilterStrategy* filter = 0; switch( currentStrategy ) { case NoFilter: filter = new NoFilterStrategy; break; case CompilerFilter: filter = new CompilerFilterStrategy( d->m_buildDir ); break; case ScriptErrorFilter: filter = new ScriptErrorFilterStrategy; break; case NativeAppErrorFilter: filter = new NativeAppErrorFilterStrategy; break; case StaticAnalysisFilter: filter = new StaticAnalysisFilterStrategy; break; default: // assert(false); filter = new NoFilterStrategy; break; } Q_ASSERT(filter); QMetaObject::invokeMethod(d->worker, "changeFilterStrategy", Q_ARG(KDevelop::IFilterStrategy*, filter)); } void OutputModel::appendLines( const QStringList& lines ) { if( lines.isEmpty() ) return; QMetaObject::invokeMethod(d->worker, "addLines", Q_ARG(QStringList, lines)); } void OutputModel::appendLine( const QString& l ) { appendLines( QStringList() << l ); } void OutputModel::ensureAllDone() { QMetaObject::invokeMethod(d->worker, "flushBuffers"); } } #include "outputmodel.moc" #include "moc_outputmodel.cpp" diff --git a/outputview/outputmodel.h b/outputview/outputmodel.h index 1abd9b0b23..09a7a64c30 100644 --- a/outputview/outputmodel.h +++ b/outputview/outputmodel.h @@ -1,90 +1,90 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2007 Andreas Pakulat * * Copyright (C) 2012 Morten Danielsen Volden mvolden2@gmail.com * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_OUTPUTMODEL_H #define KDEVPLATFORM_OUTPUTMODEL_H #include "outputviewexport.h" #include "ioutputviewmodel.h" #include #include namespace KDevelop { struct FilteredItem; struct OutputModelPrivate; class KDEVPLATFORMOUTPUTVIEW_EXPORT OutputModel : public QAbstractListModel, public KDevelop::IOutputViewModel { Q_OBJECT public: enum CustomRoles { OutputItemTypeRole = Qt::UserRole + 1 }; enum OutputFilterStrategy { NoFilter, CompilerFilter, ScriptErrorFilter, NativeAppErrorFilter, StaticAnalysisFilter }; explicit OutputModel( const QUrl& builddir , QObject* parent = 0 ); explicit OutputModel( QObject* parent = 0 ); - virtual ~OutputModel(); + ~OutputModel() override; /// IOutputViewModel interfaces void activate( const QModelIndex& index ) override; QModelIndex nextHighlightIndex( const QModelIndex ¤t ) override; QModelIndex previousHighlightIndex( const QModelIndex ¤t ) override; /// QAbstractItemModel interfaces QVariant data( const QModelIndex&, int = Qt::DisplayRole ) const override; int rowCount( const QModelIndex& = QModelIndex() ) const override; QVariant headerData( int, Qt::Orientation, int = Qt::DisplayRole ) const override; void setFilteringStrategy(const OutputFilterStrategy& currentStrategy); public Q_SLOTS: void appendLine( const QString& ); void appendLines( const QStringList& ); void ensureAllDone(); signals: void allDone(); private: OutputModelPrivate* const d; friend struct OutputModelPrivate; }; } Q_DECLARE_METATYPE( KDevelop::OutputModel::OutputFilterStrategy ) #endif diff --git a/plugins/appwizard/appwizardplugin.h b/plugins/appwizard/appwizardplugin.h index 84646412ef..306c08100a 100644 --- a/plugins/appwizard/appwizardplugin.h +++ b/plugins/appwizard/appwizardplugin.h @@ -1,60 +1,60 @@ /*************************************************************************** * Copyright 2001 Bernd Gehrmann * * Copyright 2004-2005 Sascha Cunz * * Copyright 2007 Alexander Dymo * * * * 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. * * * ***************************************************************************/ #ifndef _APPWIZARDPLUGIN_H_ #define _APPWIZARDPLUGIN_H_ #include #include #include #include class ProjectTemplatesModel; class ApplicationInfo; class KArchiveDirectory; class QTemporaryDir; class AppWizardPlugin: public KDevelop::IPlugin, public KDevelop::ITemplateProvider { Q_OBJECT Q_INTERFACES(KDevelop::ITemplateProvider) public: explicit AppWizardPlugin(QObject *parent, const QVariantList & = QVariantList()); - ~AppWizardPlugin(); - virtual KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; - - virtual QAbstractItemModel* templatesModel() override; - virtual QString knsConfigurationFile() const override; - virtual QStringList supportedMimeTypes() const override; - virtual QString name() const override; - virtual QIcon icon() const override; - virtual void loadTemplate(const QString& fileName) override; - virtual void reload() override; + ~AppWizardPlugin() override; + KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; + + QAbstractItemModel* templatesModel() override; + QString knsConfigurationFile() const override; + QStringList supportedMimeTypes() const override; + QString name() const override; + QIcon icon() const override; + void loadTemplate(const QString& fileName) override; + void reload() override; private slots: void slotNewProject(); private: ProjectTemplatesModel* model(); QString createProject(const ApplicationInfo& ); bool unpackArchive(const KArchiveDirectory *dir, const QString &dest); bool copyFileAndExpandMacros(const QString &source, const QString &dest); ProjectTemplatesModel* m_templatesModel; QAction* m_newFromTemplate; QHash m_variables; }; #endif diff --git a/plugins/appwizard/projectselectionpage.h b/plugins/appwizard/projectselectionpage.h index b1fb6fd709..7fa7d931c5 100644 --- a/plugins/appwizard/projectselectionpage.h +++ b/plugins/appwizard/projectselectionpage.h @@ -1,68 +1,68 @@ /*************************************************************************** * Copyright 2007 Alexander Dymo * * * * 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. * * * ***************************************************************************/ #ifndef _PROJECTSELECTIONPAGE_H_ #define _PROJECTSELECTIONPAGE_H_ #include "appwizardpagewidget.h" #include "appwizarddialog.h" namespace KDevelop { class MultiLevelListView; } namespace Ui { class ProjectSelectionPage; } class ProjectTemplatesModel; class QModelIndex; class QStandardItem; class QUrl; class ProjectSelectionPage : public AppWizardPageWidget { Q_OBJECT public: explicit ProjectSelectionPage(ProjectTemplatesModel *templatesModel, AppWizardDialog *wizardDialog); - ~ProjectSelectionPage(); + ~ProjectSelectionPage() override; bool shouldContinue() override; QString selectedTemplate(); QString appName(); QUrl location(); signals: void locationChanged( const QUrl& ); void valid(); void invalid(); private slots: void itemChanged( const QModelIndex& current ); void urlEdited(); void validateData(); void nameChanged(); void typeChanged(const QModelIndex& idx); void templateChanged(int); void loadFileClicked(); void moreTemplatesClicked(); private: inline QByteArray encodedAppName(); inline QStandardItem* getCurrentItem() const; void setCurrentTemplate(const QString& fileName); Ui::ProjectSelectionPage *ui; KDevelop::MultiLevelListView* m_listView; ProjectTemplatesModel *m_templatesModel; AppWizardDialog *m_wizardDialog; }; #endif diff --git a/plugins/appwizard/projectvcspage.h b/plugins/appwizard/projectvcspage.h index 359873f738..2cd448f5c4 100644 --- a/plugins/appwizard/projectvcspage.h +++ b/plugins/appwizard/projectvcspage.h @@ -1,69 +1,69 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2007 Andreas Pakulat * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_PROJECTVCSPAGE_H #define KDEVPLATFORM_PLUGIN_PROJECTVCSPAGE_H #include #include "appwizardpagewidget.h" #include namespace Ui { class ProjectVcsPage; } namespace KDevelop { class IPluginController; class VcsImportMetadataWidget; } class QUrl; class ProjectVcsPage : public AppWizardPageWidget { Q_OBJECT public: explicit ProjectVcsPage( KDevelop::IPluginController*, QWidget* parent = 0 ); - ~ProjectVcsPage(); + ~ProjectVcsPage() override; bool shouldContinue() override; signals: void valid(); void invalid(); public slots: void setSourceLocation( const QUrl& ); void vcsTypeChanged(int); void validateData(); public: QString pluginName() const; QUrl source() const; KDevelop::VcsLocation destination() const; QString commitMessage() const; private: QList importWidgets; QList > vcsPlugins; Ui::ProjectVcsPage* m_ui; }; #endif //kate: space-indent on; indent-width 4; replace-tabs on; auto-insert-doxygen on; indent-mode cstyle; diff --git a/plugins/bazaar/bazaarplugin.h b/plugins/bazaar/bazaarplugin.h index 4f2fdbfd02..d7e9a215c5 100644 --- a/plugins/bazaar/bazaarplugin.h +++ b/plugins/bazaar/bazaarplugin.h @@ -1,83 +1,83 @@ /*************************************************************************** * Copyright 2013-2014 Maciej Poleski * * * * 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 BAZAAR_BAZAARPLUGIN_H #define BAZAAR_BAZAARPLUGIN_H #include #include #include #include namespace KDevelop { class DVcsJob; } class BazaarPlugin : public KDevelop::IPlugin, public KDevelop::IDistributedVersionControl { Q_OBJECT Q_INTERFACES(KDevelop::IBasicVersionControl KDevelop::IDistributedVersionControl) public: explicit BazaarPlugin(QObject* parent, const QVariantList& args = QVariantList()); - virtual ~BazaarPlugin(); + ~BazaarPlugin() override; - virtual bool hasError() const override; - virtual QString errorDescription() const override; + bool hasError() const override; + QString errorDescription() const override; - virtual QString name() const override; + QString name() const override; - virtual KDevelop::VcsJob* add(const QList& localLocations, RecursionMode recursion=Recursive) override; - virtual KDevelop::VcsJob* annotate(const QUrl& localLocation, const KDevelop::VcsRevision& rev) override; - virtual KDevelop::VcsJob* commit(const QString& message, const QList& localLocations, RecursionMode recursion=Recursive) override; - virtual KDevelop::VcsJob* copy(const QUrl& localLocationSrc, const QUrl& localLocationDstn) override; - virtual KDevelop::VcsImportMetadataWidget* createImportMetadataWidget(QWidget* parent) override; - virtual KDevelop::VcsJob* createWorkingCopy(const KDevelop::VcsLocation& sourceRepository, const QUrl& destinationDirectory, RecursionMode recursion=Recursive) override; - virtual KDevelop::VcsJob* diff(const QUrl& fileOrDirectory, const KDevelop::VcsRevision& srcRevision, const KDevelop::VcsRevision& dstRevision, KDevelop::VcsDiff::Type, RecursionMode recursion=Recursive) override; - virtual KDevelop::VcsJob* init(const QUrl& localRepositoryRoot) override; - virtual bool isVersionControlled(const QUrl& localLocation) override; - virtual KDevelop::VcsJob* log(const QUrl& localLocation, const KDevelop::VcsRevision& rev, long unsigned int limit) override; - virtual KDevelop::VcsJob* log(const QUrl& localLocation, const KDevelop::VcsRevision& rev, const KDevelop::VcsRevision& limit) override; - virtual KDevelop::VcsJob* move(const QUrl& localLocationSrc, const QUrl& localLocationDst) override; - virtual KDevelop::VcsJob* pull(const KDevelop::VcsLocation& localOrRepoLocationSrc, const QUrl& localRepositoryLocation) override; - virtual KDevelop::VcsJob* push(const QUrl& localRepositoryLocation, const KDevelop::VcsLocation& localOrRepoLocationDst) override; - virtual KDevelop::VcsJob* remove(const QList& localLocations) override; - virtual KDevelop::VcsJob* repositoryLocation(const QUrl& localLocation) override; - virtual KDevelop::VcsJob* resolve(const QList& localLocations, RecursionMode recursio=Recursive) override; - virtual KDevelop::VcsJob* revert(const QList& localLocations, RecursionMode recursion=Recursive) override; - virtual KDevelop::VcsJob* status(const QList& localLocations, RecursionMode recursion=Recursive) override; - virtual KDevelop::VcsJob* update(const QList& localLocations, const KDevelop::VcsRevision& rev, RecursionMode recursion=Recursive) override; - virtual KDevelop::VcsLocationWidget* vcsLocation(QWidget* parent) const override; - virtual KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; + KDevelop::VcsJob* add(const QList& localLocations, RecursionMode recursion=Recursive) override; + KDevelop::VcsJob* annotate(const QUrl& localLocation, const KDevelop::VcsRevision& rev) override; + KDevelop::VcsJob* commit(const QString& message, const QList& localLocations, RecursionMode recursion=Recursive) override; + KDevelop::VcsJob* copy(const QUrl& localLocationSrc, const QUrl& localLocationDstn) override; + KDevelop::VcsImportMetadataWidget* createImportMetadataWidget(QWidget* parent) override; + KDevelop::VcsJob* createWorkingCopy(const KDevelop::VcsLocation& sourceRepository, const QUrl& destinationDirectory, RecursionMode recursion=Recursive) override; + KDevelop::VcsJob* diff(const QUrl& fileOrDirectory, const KDevelop::VcsRevision& srcRevision, const KDevelop::VcsRevision& dstRevision, KDevelop::VcsDiff::Type, RecursionMode recursion=Recursive) override; + KDevelop::VcsJob* init(const QUrl& localRepositoryRoot) override; + bool isVersionControlled(const QUrl& localLocation) override; + KDevelop::VcsJob* log(const QUrl& localLocation, const KDevelop::VcsRevision& rev, long unsigned int limit) override; + KDevelop::VcsJob* log(const QUrl& localLocation, const KDevelop::VcsRevision& rev, const KDevelop::VcsRevision& limit) override; + KDevelop::VcsJob* move(const QUrl& localLocationSrc, const QUrl& localLocationDst) override; + KDevelop::VcsJob* pull(const KDevelop::VcsLocation& localOrRepoLocationSrc, const QUrl& localRepositoryLocation) override; + KDevelop::VcsJob* push(const QUrl& localRepositoryLocation, const KDevelop::VcsLocation& localOrRepoLocationDst) override; + KDevelop::VcsJob* remove(const QList& localLocations) override; + KDevelop::VcsJob* repositoryLocation(const QUrl& localLocation) override; + KDevelop::VcsJob* resolve(const QList& localLocations, RecursionMode recursio=Recursive) override; + KDevelop::VcsJob* revert(const QList& localLocations, RecursionMode recursion=Recursive) override; + KDevelop::VcsJob* status(const QList& localLocations, RecursionMode recursion=Recursive) override; + KDevelop::VcsJob* update(const QList& localLocations, const KDevelop::VcsRevision& rev, RecursionMode recursion=Recursive) override; + KDevelop::VcsLocationWidget* vcsLocation(QWidget* parent) const override; + KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; private slots: void parseBzrStatus(KDevelop::DVcsJob* job); void parseBzrLog(KDevelop::DVcsJob* job); void parseBzrRoot(KDevelop::DVcsJob* job); private: KDevelop::VcsPluginHelper* m_vcsPluginHelper; bool m_hasError; QString m_errorDescription; }; #endif // BAZAAR_BAZAARPLUGIN_H diff --git a/plugins/bazaar/bzrannotatejob.h b/plugins/bazaar/bzrannotatejob.h index 3b07eb0f73..48a7f16ef9 100644 --- a/plugins/bazaar/bzrannotatejob.h +++ b/plugins/bazaar/bzrannotatejob.h @@ -1,75 +1,75 @@ /*************************************************************************** * Copyright 2013-2014 Maciej Poleski * * * * 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 BAZAAR_BZRANNOTATEJOB_H #define BAZAAR_BZRANNOTATEJOB_H #include #include #include #include #include #include #include class QDir; namespace KDevelop { class DVcsJob; } class BzrAnnotateJob : public KDevelop::VcsJob { Q_OBJECT public: explicit BzrAnnotateJob(const QDir& workingDir, const QString& revisionSpec, const QUrl& localLocation, KDevelop::IPlugin* parent = 0, OutputJobVerbosity verbosity = OutputJob::Verbose); - virtual QVariant fetchResults() override; - virtual void start() override; - virtual JobStatus status() const override; - virtual KDevelop::IPlugin* vcsPlugin() const override; + QVariant fetchResults() override; + void start() override; + JobStatus status() const override; + KDevelop::IPlugin* vcsPlugin() const override; protected: - virtual bool doKill() override; + bool doKill() override; private slots: void parseBzrAnnotateOutput(KDevelop::DVcsJob* job); void parseNextLine(); void prepareCommitInfo(std::size_t revision); void parseBzrLog(KDevelop::DVcsJob* job); private: QDir m_workingDir; QString m_revisionSpec; QUrl m_localLocation; KDevelop::IPlugin* m_vcsPlugin; JobStatus m_status; QPointer m_job; QStringList m_outputLines; int m_currentLine; QHash m_commits; QVariantList m_results; }; #endif // BAZAAR_BZRANNOTATEJOB_H diff --git a/plugins/bazaar/copyjob.h b/plugins/bazaar/copyjob.h index f154c48390..8404b23349 100644 --- a/plugins/bazaar/copyjob.h +++ b/plugins/bazaar/copyjob.h @@ -1,65 +1,65 @@ /*************************************************************************** * Copyright 2013-2014 Maciej Poleski * * * * 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 BAZAAR_COPYJOB_H #define BAZAAR_COPYJOB_H #include #include #include namespace KIO { class Job; } class BazaarPlugin; class CopyJob : public KDevelop::VcsJob { Q_OBJECT public: CopyJob(const QUrl& localLocationSrc, const QUrl& localLocationDstn, BazaarPlugin* parent = 0, OutputJobVerbosity verbosity = OutputJob::Verbose); - virtual KDevelop::IPlugin* vcsPlugin() const override; - virtual KDevelop::VcsJob::JobStatus status() const override; - virtual QVariant fetchResults() override; - virtual void start() override; + KDevelop::IPlugin* vcsPlugin() const override; + KDevelop::VcsJob::JobStatus status() const override; + QVariant fetchResults() override; + void start() override; protected: - virtual bool doKill() override; + bool doKill() override; private slots: void finish(KJob*); void addToVcs(KIO::Job* job, const QUrl& from, const QUrl& to, const QDateTime& mtime, bool directory, bool renamed); private: BazaarPlugin* m_plugin; QUrl m_source; QUrl m_destination; JobStatus m_status; QPointer m_job; }; #endif // BAZAAR_COPYJOB_H diff --git a/plugins/bazaar/diffjob.h b/plugins/bazaar/diffjob.h index 595d849442..2d25e794d7 100644 --- a/plugins/bazaar/diffjob.h +++ b/plugins/bazaar/diffjob.h @@ -1,62 +1,62 @@ /*************************************************************************** * Copyright 2013-2014 Maciej Poleski * * * * 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 BAZAAR_DIFFJOB_H #define BAZAAR_DIFFJOB_H #include #include namespace KDevelop { class DVcsJob; } class QDir; class BazaarPlugin; class DiffJob : public KDevelop::VcsJob { Q_OBJECT public: DiffJob(const QDir& workingDir, const QString& revisionSpecRange, const QUrl& fileOrDirectory, BazaarPlugin* parent = 0, OutputJobVerbosity verbosity = OutputJob::Silent); - virtual KDevelop::IPlugin* vcsPlugin() const override; - virtual KDevelop::VcsJob::JobStatus status() const override; - virtual QVariant fetchResults() override; - virtual void start() override; + KDevelop::IPlugin* vcsPlugin() const override; + KDevelop::VcsJob::JobStatus status() const override; + QVariant fetchResults() override; + void start() override; protected: - virtual bool doKill() override; + bool doKill() override; private slots: void prepareResult(KJob*); private: BazaarPlugin* m_plugin; QVariant m_result; JobStatus m_status; QPointer m_job; }; #endif // BAZAAR_DIFFJOB_H diff --git a/plugins/classbrowser/classbrowserplugin.cpp b/plugins/classbrowser/classbrowserplugin.cpp index ba98ee3bb4..67d07b37bc 100644 --- a/plugins/classbrowser/classbrowserplugin.cpp +++ b/plugins/classbrowser/classbrowserplugin.cpp @@ -1,187 +1,187 @@ /* * This file is part of KDevelop * * Copyright 2006 Adam Treat * Copyright 2006-2008 Hamish Rodda * Copyright 2009 Lior Mualem * * 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 "classbrowserplugin.h" #include #include #include #include "interfaces/icore.h" #include "interfaces/iuicontroller.h" #include "interfaces/idocumentcontroller.h" #include "interfaces/contextmenuextension.h" #include "language/interfaces/codecontext.h" #include "language/duchain/duchainbase.h" #include "language/duchain/duchain.h" #include "language/duchain/duchainlock.h" #include "language/duchain/declaration.h" #include #include "debug.h" #include "language/classmodel/classmodel.h" #include "classtree.h" #include "classwidget.h" #include #include #include #include #include #include Q_LOGGING_CATEGORY(PLUGIN_CLASSBROWSER, "kdevplatform.plugins.classbrowser") K_PLUGIN_FACTORY_WITH_JSON(KDevClassBrowserFactory, "kdevclassbrowser.json", registerPlugin(); ) using namespace KDevelop; class ClassBrowserFactory: public KDevelop::IToolViewFactory { public: ClassBrowserFactory(ClassBrowserPlugin *plugin): m_plugin(plugin) {} - virtual QWidget* create(QWidget *parent = 0) override + QWidget* create(QWidget *parent = 0) override { return new ClassWidget(parent, m_plugin); } - virtual Qt::DockWidgetArea defaultPosition() override + Qt::DockWidgetArea defaultPosition() override { return Qt::LeftDockWidgetArea; } - virtual QString id() const override + QString id() const override { return "org.kdevelop.ClassBrowserView"; } private: ClassBrowserPlugin *m_plugin; }; ClassBrowserPlugin::ClassBrowserPlugin(QObject *parent, const QVariantList&) : KDevelop::IPlugin("kdevclassbrowser", parent) , m_factory(new ClassBrowserFactory(this)) , m_activeClassTree(0) { core()->uiController()->addToolView(i18n("Classes"), m_factory); setXMLFile( "kdevclassbrowser.rc" ); m_findInBrowser = new QAction(i18n("Find in &Class Browser"), this); connect(m_findInBrowser, &QAction::triggered, this, &ClassBrowserPlugin::findInClassBrowser); } ClassBrowserPlugin::~ClassBrowserPlugin() { } void ClassBrowserPlugin::unload() { core()->uiController()->removeToolView(m_factory); } KDevelop::ContextMenuExtension ClassBrowserPlugin::contextMenuExtension( KDevelop::Context* context) { KDevelop::ContextMenuExtension menuExt = KDevelop::IPlugin::contextMenuExtension( context ); // No context menu if we don't have a class browser at hand. if ( m_activeClassTree == 0 ) return menuExt; KDevelop::DeclarationContext *codeContext = dynamic_cast(context); if (!codeContext) return menuExt; DUChainReadLocker readLock(DUChain::lock()); Declaration* decl(codeContext->declaration().data()); if (decl) { if(decl->inSymbolTable()) { if(!ClassTree::populatingClassBrowserContextMenu() && ICore::self()->projectController()->findProjectForUrl(decl->url().toUrl()) && decl->kind() == Declaration::Type && decl->internalContext() && decl->internalContext()->type() == DUContext::Class) { //Currently "Find in Class Browser" seems to only work for classes, so only show it in that case m_findInBrowser->setData(QVariant::fromValue(DUChainBasePointer(decl))); menuExt.addAction( KDevelop::ContextMenuExtension::ExtensionGroup, m_findInBrowser); } } } return menuExt; } void ClassBrowserPlugin::findInClassBrowser() { ICore::self()->uiController()->findToolView(i18n("Classes"), m_factory, KDevelop::IUiController::CreateAndRaise); Q_ASSERT(qobject_cast(sender())); if ( m_activeClassTree == 0 ) return; DUChainReadLocker readLock(DUChain::lock()); QAction* a = static_cast(sender()); Q_ASSERT(a->data().canConvert()); DeclarationPointer decl = qvariant_cast(a->data()).dynamicCast(); if (decl) m_activeClassTree->highlightIdentifier(decl->qualifiedIdentifier()); } void ClassBrowserPlugin::showDefinition(DeclarationPointer declaration) { DUChainReadLocker readLock(DUChain::lock()); if ( !declaration ) return; Declaration* decl = declaration.data(); // If it's a function, find the function definition to go to the actual declaration. if ( decl && decl->isFunctionDeclaration() ) { FunctionDefinition* funcDefinition = dynamic_cast(decl); if ( funcDefinition == 0 ) funcDefinition = FunctionDefinition::definition(decl); if ( funcDefinition ) decl = funcDefinition; } if (decl) { QUrl url = decl->url().toUrl(); KTextEditor::Range range = decl->rangeInCurrentRevision(); readLock.unlock(); ICore::self()->documentController()->openDocument(url, range.start()); } } #include "classbrowserplugin.moc" // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/classbrowser/classbrowserplugin.h b/plugins/classbrowser/classbrowserplugin.h index 99e0f2c192..73d078c2b3 100644 --- a/plugins/classbrowser/classbrowserplugin.h +++ b/plugins/classbrowser/classbrowserplugin.h @@ -1,65 +1,65 @@ /* * This file is part of KDevelop * * Copyright 2006 Adam Treat * Copyright 2006-2008 Hamish Rodda * Copyright 2009 Lior Mualem * * 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. */ #ifndef KDEVPLATFORM_PLUGIN_CLASSBROWSERPLUGIN_H #define KDEVPLATFORM_PLUGIN_CLASSBROWSERPLUGIN_H #include #include #include class ClassTree; namespace KDevelop { class Declaration; } class ClassBrowserPlugin : public KDevelop::IPlugin { Q_OBJECT public: explicit ClassBrowserPlugin(QObject *parent, const QVariantList & = QVariantList() ); - virtual ~ClassBrowserPlugin(); + ~ClassBrowserPlugin() override; void setActiveClassTree(ClassTree* a_classTree) { m_activeClassTree = a_classTree; } public: // KDevelop::Plugin overrides - virtual void unload() override; - virtual KDevelop::ContextMenuExtension contextMenuExtension( KDevelop::Context* ) override; + void unload() override; + KDevelop::ContextMenuExtension contextMenuExtension( KDevelop::Context* ) override; // The duchain must not be locked when this is called! void showDefinition(KDevelop::DeclarationPointer declaration); private Q_SLOTS: void findInClassBrowser(); private: class ClassBrowserFactory* m_factory; ClassTree* m_activeClassTree; QAction* m_findInBrowser; }; #endif // KDEVPLATFORM_PLUGIN_CLASSBROWSERPLUGIN_H // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/classbrowser/classtree.h b/plugins/classbrowser/classtree.h index f9cf90b902..c406c798b7 100644 --- a/plugins/classbrowser/classtree.h +++ b/plugins/classbrowser/classtree.h @@ -1,65 +1,65 @@ /* * KDevelop Class viewer * * Copyright (c) 2007 Hamish Rodda * Copyright 2009 Lior Mualem * * 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. */ #ifndef KDEVPLATFORM_PLUGIN_CLASSTREE_H #define KDEVPLATFORM_PLUGIN_CLASSTREE_H #include #include #include #include "language/util/navigationtooltip.h" class ClassBrowserPlugin; class ClassModel; class ClassTree : public QTreeView { Q_OBJECT public: ClassTree(QWidget* parent, ClassBrowserPlugin* plugin); - virtual ~ClassTree(); + ~ClassTree() override; public: /// Find the given a_id in the tree and highlight it. void highlightIdentifier(KDevelop::IndexedQualifiedIdentifier a_id); static bool populatingClassBrowserContextMenu(); protected: - virtual void contextMenuEvent(QContextMenuEvent* e) override; + void contextMenuEvent(QContextMenuEvent* e) override; ClassModel* model(); - virtual bool event(QEvent* event) override; + bool event(QEvent* event) override; private Q_SLOTS: void itemActivated(const QModelIndex& index); private: ClassBrowserPlugin* m_plugin; QPointer m_tooltip; }; #endif // kate: space-indent on; indent-width 2; tab-width: 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/classbrowser/classwidget.h b/plugins/classbrowser/classwidget.h index b0c5177048..454c3eea7b 100644 --- a/plugins/classbrowser/classwidget.h +++ b/plugins/classbrowser/classwidget.h @@ -1,52 +1,52 @@ /* * KDevelop Class viewer * * Copyright (c) 2007 Hamish Rodda * Copyright 2009 Lior Mualem * * 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. */ #ifndef KDEVPLATFORM_PLUGIN_CLASSWIDGET_H #define KDEVPLATFORM_PLUGIN_CLASSWIDGET_H #include class ClassBrowserPlugin; class ClassTree; class ClassModel; class QLineEdit; /// The class browser widget class ClassWidget : public QWidget { Q_OBJECT public: ClassWidget(QWidget* parent, ClassBrowserPlugin* plugin); - virtual ~ClassWidget(); + ~ClassWidget() override; private: ClassBrowserPlugin* m_plugin; ClassModel* m_model; ClassTree* m_tree; QLineEdit* m_searchLine; }; #endif // KDEVPLATFORM_PLUGIN_CLASSWIDGET_H // kate: space-indent on; indent-width 2; tab-width: 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/codeutils/codeutilsplugin.h b/plugins/codeutils/codeutilsplugin.h index 7fb12b17e5..7cf6e959ad 100644 --- a/plugins/codeutils/codeutilsplugin.h +++ b/plugins/codeutils/codeutilsplugin.h @@ -1,43 +1,43 @@ /* * This file is part of KDevelop * Copyright 2010 Milian Wolff * * 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. */ #ifndef KDEVPLATFORM_PLUGIN_CODEUTILSPLUGIN_H #define KDEVPLATFORM_PLUGIN_CODEUTILSPLUGIN_H #include #include #include #include Q_DECLARE_LOGGING_CATEGORY(PLUGIN_CODEUTILS) class CodeUtilsPlugin : public KDevelop::IPlugin { Q_OBJECT public: explicit CodeUtilsPlugin( QObject *parent, const QVariantList & = QVariantList() ); - ~CodeUtilsPlugin(); + ~CodeUtilsPlugin() override; private slots: void documentDeclaration(); }; #endif // KDEVPLATFORM_PLUGIN_CODEUTILSPLUGIN_H diff --git a/plugins/contextbrowser/browsemanager.h b/plugins/contextbrowser/browsemanager.h index ca6461a0b3..cbe22bdaa0 100644 --- a/plugins/contextbrowser/browsemanager.h +++ b/plugins/contextbrowser/browsemanager.h @@ -1,109 +1,109 @@ /* * 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. */ #ifndef KDEVPLATFORM_PLUGIN_BROWSEMANAGER_H #define KDEVPLATFORM_PLUGIN_BROWSEMANAGER_H #include #include #include #include #include #include class QWidget; namespace KTextEditor { class View; class Document; } namespace KDevelop { class IDocument; } class EditorViewWatcher : public QObject { Q_OBJECT public: ///@param sameWindow If this is true, only views that are child of the same window as the given widget are registered explicit EditorViewWatcher(QObject* parent = 0); QList allViews(); private: ///Called for every added view. Reimplement this to catch them. virtual void viewAdded(KTextEditor::View*); private slots: void viewDestroyed(QObject* view); void viewCreated(KTextEditor::Document*, KTextEditor::View*); void documentCreated( KDevelop::IDocument* document ); private: void addViewInternal(KTextEditor::View* view); QList m_views; }; class ContextBrowserPlugin; /** * Integrates the context-browser with the editor views, by listening for navigation events, and implementing html-like source browsing */ class BrowseManager : public QObject { Q_OBJECT public: explicit BrowseManager(ContextBrowserPlugin* controller); Q_SIGNALS: //Emitted when browsing was started using the magic-modifier void startDelayedBrowsing(KTextEditor::View* view); void stopDelayedBrowsing(); public slots: ///Enabled/disables the browsing mode void setBrowsing(bool); private slots: void eventuallyStartDelayedBrowsing(); private: void viewAdded(KTextEditor::View* view); class Watcher : public EditorViewWatcher { public: explicit Watcher(BrowseManager* manager); - virtual void viewAdded(KTextEditor::View*) override; + void viewAdded(KTextEditor::View*) override; private: BrowseManager* m_manager; }; void resetChangedCursor(); void setHandCursor(QWidget* widget); //Installs/uninstalls the event-filter void applyEventFilter(QWidget* object, bool install); - virtual bool eventFilter(QObject * watched, QEvent * event) override ; + bool eventFilter(QObject * watched, QEvent * event) override ; ContextBrowserPlugin* m_plugin; bool m_browsing; int m_browsingByKey; //Whether the browsing was started because of a key Watcher m_watcher; //Maps widgets to their previously set cursors QMap, QCursor> m_oldCursors; QTimer* m_delayedBrowsingTimer; QPointer m_browingStartedInView; KTextEditor::Cursor m_buttonPressPosition; }; #endif diff --git a/plugins/contextbrowser/contextbrowser.cpp b/plugins/contextbrowser/contextbrowser.cpp index 736b71887c..5bc9a6abf0 100644 --- a/plugins/contextbrowser/contextbrowser.cpp +++ b/plugins/contextbrowser/contextbrowser.cpp @@ -1,1364 +1,1364 @@ /* * This file is part of KDevelop * * Copyright 2007 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 "contextbrowser.h" #include "contextbrowserview.h" #include "browsemanager.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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include Q_LOGGING_CATEGORY(PLUGIN_CONTEXTBROWSER, "kdevplatform.plugins.contextbrowser") using KTextEditor::Attribute; using KTextEditor::View; // Helper that follows the QObject::parent() chain, and returns the highest widget that has no parent. QWidget* masterWidget(QWidget* w) { while(w && w->parent() && qobject_cast(w->parent())) w = qobject_cast(w->parent()); return w; } namespace { const unsigned int highlightingTimeout = 150; const float highlightingZDepth = -5000; const int maxHistoryLength = 30; // Helper that determines the context to use for highlighting at a specific position DUContext* contextForHighlightingAt(const KTextEditor::Cursor& position, TopDUContext* topContext) { DUContext* ctx = topContext->findContextAt(topContext->transformToLocalRevision(position)); while(ctx && ctx->parentContext() && (ctx->type() == DUContext::Template || ctx->type() == DUContext::Helper || ctx->localScopeIdentifier().isEmpty())) { ctx = ctx->parentContext(); } return ctx; } ///Duchain must be locked DUContext* getContextAt(const QUrl& url, KTextEditor::Cursor cursor) { TopDUContext* topContext = DUChainUtils::standardContextForUrl(url); if (!topContext) return 0; return contextForHighlightingAt(KTextEditor::Cursor(cursor), topContext); } DeclarationPointer cursorDeclaration() { KTextEditor::View* view = ICore::self()->documentController()->activeTextDocumentView(); if (!view) { return DeclarationPointer(); } DUChainReadLocker lock; Declaration *decl = DUChainUtils::declarationForDefinition(DUChainUtils::itemUnderCursor(view->document()->url(), KTextEditor::Cursor(view->cursorPosition()))); return DeclarationPointer(decl); } } class ContextBrowserViewFactory: public KDevelop::IToolViewFactory { public: ContextBrowserViewFactory(ContextBrowserPlugin *plugin): m_plugin(plugin) {} - virtual QWidget* create(QWidget *parent = 0) override + QWidget* create(QWidget *parent = 0) override { ContextBrowserView* ret = new ContextBrowserView(m_plugin, parent); return ret; } - virtual Qt::DockWidgetArea defaultPosition() override + Qt::DockWidgetArea defaultPosition() override { return Qt::BottomDockWidgetArea; } - virtual QString id() const override + QString id() const override { return "org.kdevelop.ContextBrowser"; } private: ContextBrowserPlugin *m_plugin; }; KXMLGUIClient* ContextBrowserPlugin::createGUIForMainWindow( Sublime::MainWindow* window ) { KXMLGUIClient* ret = KDevelop::IPlugin::createGUIForMainWindow( window ); m_browseManager = new BrowseManager(this); connect(ICore::self()->documentController(), &IDocumentController::documentJumpPerformed, this, &ContextBrowserPlugin::documentJumpPerformed); m_previousButton = new QToolButton(); m_previousButton->setToolTip(i18n("Go back in context history")); m_previousButton->setPopupMode(QToolButton::MenuButtonPopup); m_previousButton->setIcon(QIcon::fromTheme("go-previous")); m_previousButton->setEnabled(false); m_previousButton->setFocusPolicy(Qt::NoFocus); m_previousMenu = new QMenu(); m_previousButton->setMenu(m_previousMenu); connect(m_previousButton.data(), &QToolButton::clicked, this, &ContextBrowserPlugin::historyPrevious); connect(m_previousMenu.data(), &QMenu::aboutToShow, this, &ContextBrowserPlugin::previousMenuAboutToShow); m_nextButton = new QToolButton(); m_nextButton->setToolTip(i18n("Go forward in context history")); m_nextButton->setPopupMode(QToolButton::MenuButtonPopup); m_nextButton->setIcon(QIcon::fromTheme("go-next")); m_nextButton->setEnabled(false); m_nextButton->setFocusPolicy(Qt::NoFocus); m_nextMenu = new QMenu(); m_nextButton->setMenu(m_nextMenu); connect(m_nextButton.data(), &QToolButton::clicked, this, &ContextBrowserPlugin::historyNext); connect(m_nextMenu.data(), &QMenu::aboutToShow, this, &ContextBrowserPlugin::nextMenuAboutToShow); m_browseButton = new QToolButton(); m_browseButton->setIcon(QIcon::fromTheme("games-hint")); m_browseButton->setToolTip(i18n("Enable/disable source browse mode")); m_browseButton->setWhatsThis(i18n("When this is enabled, you can browse the source-code by clicking in the editor.")); m_browseButton->setCheckable(true); m_browseButton->setFocusPolicy(Qt::NoFocus); connect(m_browseButton.data(), &QToolButton::clicked, m_browseManager, &BrowseManager::setBrowsing); IQuickOpen* quickOpen = KDevelop::ICore::self()->pluginController()->extensionForPlugin("org.kdevelop.IQuickOpen"); if(quickOpen) { m_outlineLine = quickOpen->createQuickOpenLine(QStringList(), QStringList() << i18n("Outline"), IQuickOpen::Outline); m_outlineLine->setDefaultText(i18n("Outline...")); m_outlineLine->setToolTip(i18n("Navigate outline of active document, click to browse.")); } connect(m_browseManager, &BrowseManager::startDelayedBrowsing, this, &ContextBrowserPlugin::startDelayedBrowsing); connect(m_browseManager, &BrowseManager::stopDelayedBrowsing, this, &ContextBrowserPlugin::stopDelayedBrowsing); m_toolbarWidget = toolbarWidgetForMainWindow(window); m_toolbarWidgetLayout = new QHBoxLayout; m_toolbarWidgetLayout->setSizeConstraint(QLayout::SetMaximumSize); m_previousButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_nextButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_browseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_toolbarWidgetLayout->setMargin(0); m_toolbarWidgetLayout->addWidget(m_previousButton); if (m_outlineLine) { m_toolbarWidgetLayout->addWidget(m_outlineLine); m_outlineLine->setMaximumWidth(600); connect(ICore::self()->documentController(), &IDocumentController::documentClosed, m_outlineLine.data(), &IQuickOpenLine::clear); } m_toolbarWidgetLayout->addWidget(m_nextButton); m_toolbarWidgetLayout->addWidget(m_browseButton); if(m_toolbarWidget->children().isEmpty()) m_toolbarWidget->setLayout(m_toolbarWidgetLayout); connect(ICore::self()->documentController(), &IDocumentController::documentActivated, this, &ContextBrowserPlugin::documentActivated); return ret; } void ContextBrowserPlugin::createActionsForMainWindow(Sublime::MainWindow* window, QString& xmlFile, KActionCollection& actions) { xmlFile = "kdevcontextbrowser.rc" ; QAction* previousContext = actions.addAction("previous_context"); previousContext->setText( i18n("&Previous Visited Context") ); previousContext->setIcon( QIcon::fromTheme("go-previous-context" ) ); actions.setDefaultShortcut( previousContext, Qt::META | Qt::Key_Left ); QObject::connect(previousContext, &QAction::triggered, this, &ContextBrowserPlugin::previousContextShortcut); QAction* nextContext = actions.addAction("next_context"); nextContext->setText( i18n("&Next Visited Context") ); nextContext->setIcon( QIcon::fromTheme("go-next-context" ) ); actions.setDefaultShortcut( nextContext, Qt::META | Qt::Key_Right ); QObject::connect(nextContext, &QAction::triggered, this, &ContextBrowserPlugin::nextContextShortcut); QAction* previousUse = actions.addAction("previous_use"); previousUse->setText( i18n("&Previous Use") ); previousUse->setIcon( QIcon::fromTheme("go-previous-use") ); actions.setDefaultShortcut( previousUse, Qt::META | Qt::SHIFT | Qt::Key_Left ); QObject::connect(previousUse, &QAction::triggered, this, &ContextBrowserPlugin::previousUseShortcut); QAction* nextUse = actions.addAction("next_use"); nextUse->setText( i18n("&Next Use") ); nextUse->setIcon( QIcon::fromTheme("go-next-use") ); actions.setDefaultShortcut( nextUse, Qt::META | Qt::SHIFT | Qt::Key_Right ); QObject::connect(nextUse, &QAction::triggered, this, &ContextBrowserPlugin::nextUseShortcut); QWidgetAction* outline = new QWidgetAction(this); outline->setText(i18n("Context Browser")); QWidget* w = toolbarWidgetForMainWindow(window); w->setHidden(false); outline->setDefaultWidget(w); actions.addAction("outline_line", outline); // Add to the actioncollection so one can set global shortcuts for the action actions.addAction("find_uses", m_findUses); } void ContextBrowserPlugin::nextContextShortcut() { // TODO: cleanup historyNext(); } void ContextBrowserPlugin::previousContextShortcut() { // TODO: cleanup historyPrevious(); } K_PLUGIN_FACTORY_WITH_JSON(ContextBrowserFactory, "kdevcontextbrowser.json", registerPlugin();) ContextBrowserPlugin::ContextBrowserPlugin(QObject *parent, const QVariantList&) : KDevelop::IPlugin("kdevcontextbrowser", parent) , m_viewFactory(new ContextBrowserViewFactory(this)) , m_nextHistoryIndex(0) { KDEV_USE_EXTENSION_INTERFACE( IContextBrowser ) core()->uiController()->addToolView(i18n("Code Browser"), m_viewFactory); connect( core()->documentController(), &IDocumentController::textDocumentCreated, this, &ContextBrowserPlugin::textDocumentCreated ); connect( core()->languageController()->backgroundParser(), &BackgroundParser::parseJobFinished, this, &ContextBrowserPlugin::parseJobFinished); connect( DUChain::self(), &DUChain::declarationSelected, this, &ContextBrowserPlugin::declarationSelectedInUI ); m_updateTimer = new QTimer(this); m_updateTimer->setSingleShot(true); connect( m_updateTimer, &QTimer::timeout, this, &ContextBrowserPlugin::updateViews ); //Needed global action for the context-menu extensions m_findUses = new QAction(i18n("Find Uses"), this); connect(m_findUses, &QAction::triggered, this, &ContextBrowserPlugin::findUses); } ContextBrowserPlugin::~ContextBrowserPlugin() { ///TODO: QObject inheritance should suffice? delete m_nextMenu; delete m_previousMenu; delete m_toolbarWidgetLayout; delete m_previousButton; delete m_outlineLine; delete m_nextButton; delete m_browseButton; } void ContextBrowserPlugin::unload() { core()->uiController()->removeToolView(m_viewFactory); } KDevelop::ContextMenuExtension ContextBrowserPlugin::contextMenuExtension(KDevelop::Context* context) { KDevelop::ContextMenuExtension menuExt = KDevelop::IPlugin::contextMenuExtension( context ); KDevelop::DeclarationContext *codeContext = dynamic_cast(context); if (!codeContext) return menuExt; DUChainReadLocker lock(DUChain::lock()); if(!codeContext->declaration().data()) return menuExt; qRegisterMetaType("KDevelop::IndexedDeclaration"); menuExt.addAction(KDevelop::ContextMenuExtension::ExtensionGroup, m_findUses); return menuExt; } void ContextBrowserPlugin::showUses(const DeclarationPointer& declaration) { QMetaObject::invokeMethod(this, "showUsesDelayed", Qt::QueuedConnection, Q_ARG(KDevelop::DeclarationPointer, declaration)); } void ContextBrowserPlugin::showUsesDelayed(const DeclarationPointer& declaration) { DUChainReadLocker lock; Declaration* decl = declaration.data(); if(!decl) { return; } QWidget* toolView = ICore::self()->uiController()->findToolView(i18n("Code Browser"), m_viewFactory, KDevelop::IUiController::CreateAndRaise); if(!toolView) { return; } ContextBrowserView* view = dynamic_cast(toolView); Q_ASSERT(view); view->allowLockedUpdate(); view->setDeclaration(decl, decl->topContext(), true); //We may get deleted while the call to acceptLink, so make sure we don't crash in that case QPointer widget = dynamic_cast(view->navigationWidget()); if(widget && widget->context()) { NavigationContextPointer nextContext = widget->context()->execute( NavigationAction(declaration, KDevelop::NavigationAction::ShowUses)); if(widget) { widget->setContext( nextContext ); } } } void ContextBrowserPlugin::findUses() { showUses(cursorDeclaration()); } ContextBrowserHintProvider::ContextBrowserHintProvider(ContextBrowserPlugin* plugin) : m_plugin(plugin) { } QString ContextBrowserHintProvider::textHint(View* view, const KTextEditor::Cursor& cursor) { m_plugin->m_mouseHoverCursor = KTextEditor::Cursor(cursor); if(!view) { qWarning() << "could not cast to view"; }else{ m_plugin->m_mouseHoverDocument = view->document()->url(); m_plugin->m_updateViews << view; } m_plugin->m_updateTimer->start(1); // triggers updateViews() m_plugin->showToolTip(view, cursor); return QString(); } void ContextBrowserPlugin::stopDelayedBrowsing() { hideToolTip(); } void ContextBrowserPlugin::startDelayedBrowsing(KTextEditor::View* view) { if(!m_currentToolTip) { showToolTip(view, view->cursorPosition()); } } void ContextBrowserPlugin::hideToolTip() { if(m_currentToolTip) { m_currentToolTip->deleteLater(); m_currentToolTip = 0; m_currentNavigationWidget = 0; } } void ContextBrowserPlugin::showToolTip(KTextEditor::View* view, KTextEditor::Cursor position) { ContextBrowserView* contextView = browserViewForWidget(view); if(contextView && contextView->isVisible() && !contextView->isLocked()) return; // If the context-browser view is visible, it will care about updating by itself QUrl viewUrl = view->document()->url(); auto languages = ICore::self()->languageController()->languagesForUrl(viewUrl); QWidget* navigationWidget = 0; { DUChainReadLocker lock(DUChain::lock()); foreach (const auto& language, languages) { auto widget = language->specialLanguageObjectNavigationWidget(viewUrl, KTextEditor::Cursor(position)); navigationWidget = qobject_cast(widget); if(navigationWidget) break; } if(!navigationWidget) { Declaration* decl = DUChainUtils::declarationForDefinition( DUChainUtils::itemUnderCursor(viewUrl, KTextEditor::Cursor(position)) ); if (decl && decl->kind() == Declaration::Alias) { AliasDeclaration* alias = dynamic_cast(decl); Q_ASSERT(alias); DUChainReadLocker lock; decl = alias->aliasedDeclaration().declaration(); } if(decl) { if(m_currentToolTipDeclaration == IndexedDeclaration(decl) && m_currentToolTip) return; m_currentToolTipDeclaration = IndexedDeclaration(decl); navigationWidget = decl->context()->createNavigationWidget(decl, DUChainUtils::standardContextForUrl(viewUrl)); } } } if(navigationWidget) { // If we have an invisible context-view, assign the tooltip navigation-widget to it. // If the user makes the context-view visible, it will instantly contain the correct widget. if(contextView && !contextView->isLocked()) contextView->setNavigationWidget(navigationWidget); if(m_currentToolTip) { m_currentToolTip->deleteLater(); m_currentToolTip = 0; m_currentNavigationWidget = 0; } KDevelop::NavigationToolTip* tooltip = new KDevelop::NavigationToolTip(view, view->mapToGlobal(view->cursorToCoordinate(position)) + QPoint(20, 40), navigationWidget); KTextEditor::Range itemRange; { DUChainReadLocker lock; itemRange = DUChainUtils::itemRangeUnderCursor(viewUrl, KTextEditor::Cursor(position)); } tooltip->setHandleRect(getItemBoundingRect(view, itemRange)); tooltip->resize( navigationWidget->sizeHint() + QSize(10, 10) ); qCDebug(PLUGIN_CONTEXTBROWSER) << "tooltip size" << tooltip->size(); m_currentToolTip = tooltip; m_currentNavigationWidget = navigationWidget; ActiveToolTip::showToolTip(tooltip); if ( ! navigationWidget->property("DoNotCloseOnCursorMove").toBool() ) { connect(view, &View::cursorPositionChanged, this, &ContextBrowserPlugin::hideToolTip, Qt::UniqueConnection); } else { disconnect(view, &View::cursorPositionChanged, this, &ContextBrowserPlugin::hideToolTip); } }else{ qCDebug(PLUGIN_CONTEXTBROWSER) << "not showing tooltip, no navigation-widget"; } } void ContextBrowserPlugin::clearMouseHover() { m_mouseHoverCursor = KTextEditor::Cursor::invalid(); m_mouseHoverDocument.clear(); } Attribute::Ptr highlightedUseAttribute() { static Attribute::Ptr standardAttribute = Attribute::Ptr(); if( !standardAttribute ) { standardAttribute= Attribute::Ptr( new Attribute() ); standardAttribute->setBackgroundFillWhitespace(true); // mixing (255, 255, 0, 100) with white yields this: standardAttribute->setBackground(QColor(251, 250, 150)); // force a foreground color to overwrite default Kate highlighting, i.e. of Q_OBJECT or similar // foreground color could change, hence apply it everytime standardAttribute->setForeground(QColor(0, 0, 0, 255)); //Don't use alpha here, as kate uses the alpha only to blend with the document background color } return standardAttribute; } Attribute::Ptr highlightedSpecialObjectAttribute() { static Attribute::Ptr standardAttribute = Attribute::Ptr(); if( !standardAttribute ) { standardAttribute = Attribute::Ptr( new Attribute() ); standardAttribute->setBackgroundFillWhitespace(true); // mixing (90, 255, 0, 100) with white yields this: standardAttribute->setBackground(QColor(190, 255, 155)); // force a foreground color to overwrite default Kate highlighting, i.e. of Q_OBJECT or similar // foreground color could change, hence apply it everytime standardAttribute->setForeground(QColor(0, 0, 0, 255)); //Don't use alpha here, as kate uses the alpha only to blend with the document background color } return standardAttribute; } void ContextBrowserPlugin::addHighlight( View* view, KDevelop::Declaration* decl ) { if( !view || !decl ) { qCDebug(PLUGIN_CONTEXTBROWSER) << "invalid view/declaration"; return; } ViewHighlights& highlights(m_highlightedRanges[view]); KDevelop::DUChainReadLocker lock; // Highlight the declaration highlights.highlights << decl->createRangeMoving(); highlights.highlights.back()->setAttribute(highlightedUseAttribute()); highlights.highlights.back()->setZDepth(highlightingZDepth); // Highlight uses { QMap< IndexedString, QList< KTextEditor::Range > > currentRevisionUses = decl->usesCurrentRevision(); for(QMap< IndexedString, QList< KTextEditor::Range > >::iterator fileIt = currentRevisionUses.begin(); fileIt != currentRevisionUses.end(); ++fileIt) { for(QList< KTextEditor::Range >::const_iterator useIt = (*fileIt).constBegin(); useIt != (*fileIt).constEnd(); ++useIt) { highlights.highlights << PersistentMovingRange::Ptr(new PersistentMovingRange(*useIt, fileIt.key())); highlights.highlights.back()->setAttribute(highlightedUseAttribute()); highlights.highlights.back()->setZDepth(highlightingZDepth); } } } if( FunctionDefinition* def = FunctionDefinition::definition(decl) ) { highlights.highlights << def->createRangeMoving(); highlights.highlights.back()->setAttribute(highlightedUseAttribute()); highlights.highlights.back()->setZDepth(highlightingZDepth); } } Declaration* ContextBrowserPlugin::findDeclaration(View* view, const KTextEditor::Cursor& position, bool mouseHighlight) { Q_UNUSED(mouseHighlight); Declaration* foundDeclaration = 0; if(m_useDeclaration.data()) { foundDeclaration = m_useDeclaration.data(); }else{ //If we haven't found a special language object, search for a use/declaration and eventually highlight it foundDeclaration = DUChainUtils::declarationForDefinition( DUChainUtils::itemUnderCursor(view->document()->url(), position) ); if (foundDeclaration && foundDeclaration->kind() == Declaration::Alias) { AliasDeclaration* alias = dynamic_cast(foundDeclaration); Q_ASSERT(alias); DUChainReadLocker lock; foundDeclaration = alias->aliasedDeclaration().declaration(); } } return foundDeclaration; } ContextBrowserView* ContextBrowserPlugin::browserViewForWidget(QWidget* widget) { foreach(ContextBrowserView* contextView, m_views) { if(masterWidget(contextView) == masterWidget(widget)) { return contextView; } } return 0; } void ContextBrowserPlugin::updateForView(View* view) { bool allowHighlight = true; if(view->selection()) { // If something is selected, we unhighlight everything, so that we don't conflict with the // kate plugin that highlights occurrences of the selected string, and also to reduce the // overall amount of concurrent highlighting. allowHighlight = false; } if(m_highlightedRanges[view].keep) { m_highlightedRanges[view].keep = false; return; } // Clear all highlighting m_highlightedRanges.clear(); // Re-highlight ViewHighlights& highlights = m_highlightedRanges[view]; QUrl url = view->document()->url(); IDocument* activeDoc = core()->documentController()->activeDocument(); bool mouseHighlight = (url == m_mouseHoverDocument) && (m_mouseHoverCursor.isValid()); bool shouldUpdateBrowser = (mouseHighlight || (view == ICore::self()->documentController()->activeTextDocumentView() && activeDoc && activeDoc->textDocument() == view->document())); KTextEditor::Cursor highlightPosition; if (mouseHighlight) highlightPosition = m_mouseHoverCursor; else highlightPosition = KTextEditor::Cursor(view->cursorPosition()); ///Pick a language ILanguageSupport* language = nullptr; if(ICore::self()->languageController()->languagesForUrl(url).isEmpty()) { qCDebug(PLUGIN_CONTEXTBROWSER) << "found no language for document" << url; return; }else{ language = ICore::self()->languageController()->languagesForUrl(url).front(); } ///Check whether there is a special language object to highlight (for example a macro) KTextEditor::Range specialRange = language->specialLanguageObjectRange(url, highlightPosition); ContextBrowserView* updateBrowserView = shouldUpdateBrowser ? browserViewForWidget(view) : 0; if(specialRange.isValid()) { // Highlight a special language object if(allowHighlight) { highlights.highlights << PersistentMovingRange::Ptr(new PersistentMovingRange(specialRange, IndexedString(url))); highlights.highlights.back()->setAttribute(highlightedSpecialObjectAttribute()); highlights.highlights.back()->setZDepth(highlightingZDepth); } if(updateBrowserView) updateBrowserView->setSpecialNavigationWidget(language->specialLanguageObjectNavigationWidget(url, highlightPosition)); }else{ KDevelop::DUChainReadLocker lock( DUChain::lock(), 100 ); if(!lock.locked()) { qCDebug(PLUGIN_CONTEXTBROWSER) << "Failed to lock du-chain in time"; return; } TopDUContext* topContext = DUChainUtils::standardContextForUrl(view->document()->url()); if (!topContext) return; DUContext* ctx = contextForHighlightingAt(highlightPosition, topContext); if (!ctx) return; //Only update the history if this context is around the text cursor if(core()->documentController()->activeDocument() && highlightPosition == KTextEditor::Cursor(view->cursorPosition()) && view->document() == core()->documentController()->activeDocument()->textDocument()) { updateHistory(ctx, highlightPosition); } Declaration* foundDeclaration = findDeclaration(view, highlightPosition, mouseHighlight); if( foundDeclaration ) { m_lastHighlightedDeclaration = highlights.declaration = IndexedDeclaration(foundDeclaration); if(allowHighlight) addHighlight( view, foundDeclaration ); if(updateBrowserView) updateBrowserView->setDeclaration(foundDeclaration, topContext); }else{ if(updateBrowserView) updateBrowserView->setContext(ctx); } } } void ContextBrowserPlugin::updateViews() { foreach( View* view, m_updateViews ) { updateForView(view); } m_updateViews.clear(); m_useDeclaration = IndexedDeclaration(); } void ContextBrowserPlugin::declarationSelectedInUI(const DeclarationPointer& decl) { m_useDeclaration = IndexedDeclaration(decl.data()); KTextEditor::View* view = core()->documentController()->activeTextDocumentView(); if(view) m_updateViews << view; if(!m_updateViews.isEmpty()) m_updateTimer->start(highlightingTimeout); // triggers updateViews() } void ContextBrowserPlugin::parseJobFinished(KDevelop::ParseJob* job) { for(QMap< View*, ViewHighlights >::iterator it = m_highlightedRanges.begin(); it != m_highlightedRanges.end(); ++it) { if(it.key()->document()->url() == job->document().toUrl()) { if(!m_updateViews.contains(it.key())) { qCDebug(PLUGIN_CONTEXTBROWSER) << "adding view for update"; m_updateViews << it.key(); // Don't change the highlighted declaration after finished parse-jobs (*it).keep = true; } } } if(!m_updateViews.isEmpty()) m_updateTimer->start(highlightingTimeout); } void ContextBrowserPlugin::textDocumentCreated( KDevelop::IDocument* document ) { Q_ASSERT(document->textDocument()); connect( document->textDocument(), &KTextEditor::Document::viewCreated, this, &ContextBrowserPlugin::viewCreated ); foreach( View* view, document->textDocument()->views() ) viewCreated( document->textDocument(), view ); } void ContextBrowserPlugin::documentActivated( IDocument* doc ) { if (m_outlineLine) m_outlineLine->clear(); if (View* view = doc->activeTextView()) { cursorPositionChanged(view, view->cursorPosition()); } } void ContextBrowserPlugin::viewDestroyed( QObject* obj ) { m_highlightedRanges.remove(static_cast(obj)); m_updateViews.remove(static_cast(obj)); } void ContextBrowserPlugin::selectionChanged( View* view ) { clearMouseHover(); m_updateViews.insert(view); m_updateTimer->start(highlightingTimeout/2); // triggers updateViews() } void ContextBrowserPlugin::cursorPositionChanged( View* view, const KTextEditor::Cursor& newPosition ) { if(view->document() == m_lastInsertionDocument && newPosition == m_lastInsertionPos) { //Do not update the highlighting while typing m_lastInsertionDocument = 0; m_lastInsertionPos = KTextEditor::Cursor(); if(m_highlightedRanges.contains(view)) m_highlightedRanges[view].keep = true; }else{ if(m_highlightedRanges.contains(view)) m_highlightedRanges[view].keep = false; } clearMouseHover(); m_updateViews.insert(view); m_updateTimer->start(highlightingTimeout/2); // triggers updateViews() } void ContextBrowserPlugin::textInserted(KTextEditor::Document* doc, const KTextEditor::Cursor& cursor, const QString& text) { m_lastInsertionDocument = doc; m_lastInsertionPos = cursor + KTextEditor::Cursor(0, text.size()); } void ContextBrowserPlugin::viewCreated( KTextEditor::Document* , View* v ) { disconnect( v, &View::cursorPositionChanged, this, &ContextBrowserPlugin::cursorPositionChanged ); ///Just to make sure that multiple connections don't happen connect( v, &View::cursorPositionChanged, this, &ContextBrowserPlugin::cursorPositionChanged ); connect( v, &View::destroyed, this, &ContextBrowserPlugin::viewDestroyed ); disconnect( v->document(), &KTextEditor::Document::textInserted, this, &ContextBrowserPlugin::textInserted); connect(v->document(), &KTextEditor::Document::textInserted, this, &ContextBrowserPlugin::textInserted); disconnect(v, &View::selectionChanged, this, &ContextBrowserPlugin::selectionChanged); KTextEditor::TextHintInterface *iface = dynamic_cast(v); if( !iface ) return; iface->setTextHintDelay(highlightingTimeout); iface->registerTextHintProvider(new ContextBrowserHintProvider(this)); } void ContextBrowserPlugin::registerToolView(ContextBrowserView* view) { m_views << view; } void ContextBrowserPlugin::previousUseShortcut() { switchUse(false); } void ContextBrowserPlugin::nextUseShortcut() { switchUse(true); } KTextEditor::Range cursorToRange(KTextEditor::Cursor cursor) { return KTextEditor::Range(cursor, cursor); } void ContextBrowserPlugin::switchUse(bool forward) { View* view = core()->documentController()->activeTextDocumentView(); if(view) { KTextEditor::Document* doc = view->document(); KDevelop::DUChainReadLocker lock( DUChain::lock() ); KDevelop::TopDUContext* chosen = DUChainUtils::standardContextForUrl(doc->url()); if( chosen ) { KTextEditor::Cursor cCurrent(view->cursorPosition()); KDevelop::CursorInRevision c = chosen->transformToLocalRevision(cCurrent); Declaration* decl = 0; //If we have a locked declaration, use that for jumping foreach(ContextBrowserView* view, m_views) { decl = view->lockedDeclaration().data(); ///@todo Somehow match the correct context-browser view if there is multiple if(decl) break; } if(!decl) //Try finding a declaration under the cursor decl = DUChainUtils::itemUnderCursor(doc->url(), cCurrent); if (decl && decl->kind() == Declaration::Alias) { AliasDeclaration* alias = dynamic_cast(decl); Q_ASSERT(alias); DUChainReadLocker lock; decl = alias->aliasedDeclaration().declaration(); } if(decl) { Declaration* target = 0; if(forward) //Try jumping from definition to declaration target = DUChainUtils::declarationForDefinition(decl, chosen); else if(decl->url().toUrl() == doc->url() && decl->range().contains(c)) //Try jumping from declaration to definition target = FunctionDefinition::definition(decl); if(target && target != decl) { KTextEditor::Cursor jumpTo = target->rangeInCurrentRevision().start(); QUrl document = target->url().toUrl(); lock.unlock(); core()->documentController()->openDocument( document, cursorToRange(jumpTo) ); return; }else{ //Always work with the declaration instead of the definition decl = DUChainUtils::declarationForDefinition(decl, chosen); } } if(!decl) { //Pick the last use we have highlighted decl = m_lastHighlightedDeclaration.data(); } if(decl) { KDevVarLengthArray usingFiles = DUChain::uses()->uses(decl->id()); if(DUChainUtils::contextHasUse(decl->topContext(), decl) && usingFiles.indexOf(decl->topContext()) == -1) usingFiles.insert(0, decl->topContext()); if(decl->range().contains(c) && decl->url() == chosen->url()) { //The cursor is directly on the declaration. Jump to the first or last use. if(!usingFiles.isEmpty()) { TopDUContext* top = (forward ? usingFiles[0] : usingFiles.back()).data(); if(top) { QList useRanges = allUses(top, decl, true); std::sort(useRanges.begin(), useRanges.end()); if(!useRanges.isEmpty()) { QUrl url = top->url().toUrl(); KTextEditor::Range selectUse = chosen->transformFromLocalRevision(forward ? useRanges.first() : useRanges.back()); lock.unlock(); core()->documentController()->openDocument(url, cursorToRange(selectUse.start())); } } } return; } //Check whether we are within a use QList localUses = allUses(chosen, decl, true); std::sort(localUses.begin(), localUses.end()); for(int a = 0; a < localUses.size(); ++a) { int nextUse = (forward ? a+1 : a-1); bool pick = localUses[a].contains(c); if(!pick && forward && a+1 < localUses.size() && localUses[a].end <= c && localUses[a+1].start > c) { //Special case: We aren't on a use, but we are jumping forward, and are behind this and the next use pick = true; } if(!pick && !forward && a-1 >= 0 && c < localUses[a].start && c >= localUses[a-1].end) { //Special case: We aren't on a use, but we are jumping backward, and are in front of this use, but behind the previous one pick = true; } if(!pick && a == 0 && c < localUses[a].start) { if(!forward) { //Will automatically jump to previous file }else{ nextUse = 0; //We are before the first use, so jump to it. } pick = true; } if(!pick && a == localUses.size()-1 && c >= localUses[a].end) { if(forward) { //Will automatically jump to next file }else{ //We are behind the last use, but moving backward. So pick the last use. nextUse = a; } pick = true; } if(pick) { //Make sure we end up behind the use if(nextUse != a) while(forward && nextUse < localUses.size() && (localUses[nextUse].start <= localUses[a].end || localUses[nextUse].isEmpty())) ++nextUse; //Make sure we end up before the use if(nextUse != a) while(!forward && nextUse >= 0 && (localUses[nextUse].start >= localUses[a].start || localUses[nextUse].isEmpty())) --nextUse; //Jump to the next use qCDebug(PLUGIN_CONTEXTBROWSER) << "count of uses:" << localUses.size() << "nextUse" << nextUse; if(nextUse < 0 || nextUse == localUses.size()) { qCDebug(PLUGIN_CONTEXTBROWSER) << "jumping to next file"; //Jump to the first use in the next using top-context int indexInFiles = usingFiles.indexOf(chosen); if(indexInFiles != -1) { int nextFile = (forward ? indexInFiles+1 : indexInFiles-1); qCDebug(PLUGIN_CONTEXTBROWSER) << "current file" << indexInFiles << "nextFile" << nextFile; if(nextFile < 0 || nextFile >= usingFiles.size()) { //Open the declaration, or the definition if(nextFile >= usingFiles.size()) { Declaration* definition = FunctionDefinition::definition(decl); if(definition) decl = definition; } QUrl u = decl->url().toUrl(); KTextEditor::Range range = decl->rangeInCurrentRevision(); range.setEnd(range.start()); lock.unlock(); core()->documentController()->openDocument(u, range); return; }else{ TopDUContext* nextTop = usingFiles[nextFile].data(); QUrl u = nextTop->url().toUrl(); QList nextTopUses = allUses(nextTop, decl, true); std::sort(nextTopUses.begin(), nextTopUses.end()); if(!nextTopUses.isEmpty()) { KTextEditor::Range range = chosen->transformFromLocalRevision(forward ? nextTopUses.front() : nextTopUses.back()); range.setEnd(range.start()); lock.unlock(); core()->documentController()->openDocument(u, range); } return; } }else{ qCDebug(PLUGIN_CONTEXTBROWSER) << "not found own file in use list"; } }else{ QUrl url = chosen->url().toUrl(); KTextEditor::Range range = chosen->transformFromLocalRevision(localUses[nextUse]); range.setEnd(range.start()); lock.unlock(); core()->documentController()->openDocument(url, range); return; } } } } } } } void ContextBrowserPlugin::unRegisterToolView(ContextBrowserView* view) { m_views.removeAll(view); } // history browsing QWidget* ContextBrowserPlugin::toolbarWidgetForMainWindow( Sublime::MainWindow* window ) { //TODO: support multiple windows (if that ever gets revived) if (!m_toolbarWidget) { m_toolbarWidget = new QWidget(window); } return m_toolbarWidget; } void ContextBrowserPlugin::documentJumpPerformed( KDevelop::IDocument* newDocument, const KTextEditor::Cursor& newCursor, KDevelop::IDocument* previousDocument, const KTextEditor::Cursor& previousCursor) { DUChainReadLocker lock(DUChain::lock()); /*TODO: support multiple windows if that ever gets revived if(newDocument && newDocument->textDocument() && newDocument->textDocument()->activeView() && masterWidget(newDocument->textDocument()->activeView()) != masterWidget(this)) return; */ if(previousDocument && previousCursor.isValid()) { qCDebug(PLUGIN_CONTEXTBROWSER) << "updating jump source"; DUContext* context = getContextAt(previousDocument->url(), previousCursor); if(context) { updateHistory(context, KTextEditor::Cursor(previousCursor), true); }else{ //We just want this place in the history m_history.resize(m_nextHistoryIndex); // discard forward history m_history.append(HistoryEntry(DocumentCursor(IndexedString(previousDocument->url()), KTextEditor::Cursor(previousCursor)))); ++m_nextHistoryIndex; } } qCDebug(PLUGIN_CONTEXTBROWSER) << "new doc: " << newDocument << " new cursor: " << newCursor; if(newDocument && newCursor.isValid()) { qCDebug(PLUGIN_CONTEXTBROWSER) << "updating jump target"; DUContext* context = getContextAt(newDocument->url(), newCursor); if(context) { updateHistory(context, KTextEditor::Cursor(newCursor), true); }else{ //We just want this place in the history m_history.resize(m_nextHistoryIndex); // discard forward history m_history.append(HistoryEntry(DocumentCursor(IndexedString(newDocument->url()), KTextEditor::Cursor(newCursor)))); ++m_nextHistoryIndex; if (m_outlineLine) m_outlineLine->clear(); } } } void ContextBrowserPlugin::updateButtonState() { m_nextButton->setEnabled( m_nextHistoryIndex < m_history.size() ); m_previousButton->setEnabled( m_nextHistoryIndex >= 2 ); } void ContextBrowserPlugin::historyNext() { if(m_nextHistoryIndex >= m_history.size()) { return; } openDocument(m_nextHistoryIndex); // opening the document at given position // will update the widget for us ++m_nextHistoryIndex; updateButtonState(); } void ContextBrowserPlugin::openDocument(int historyIndex) { Q_ASSERT_X(historyIndex >= 0, "openDocument", "negative history index"); Q_ASSERT_X(historyIndex < m_history.size(), "openDocument", "history index out of range"); DocumentCursor c = m_history[historyIndex].computePosition(); if (c.isValid() && !c.document.str().isEmpty()) { disconnect(ICore::self()->documentController(), &IDocumentController::documentJumpPerformed, this, &ContextBrowserPlugin::documentJumpPerformed); ICore::self()->documentController()->openDocument(c.document.toUrl(), c); connect(ICore::self()->documentController(), &IDocumentController::documentJumpPerformed, this, &ContextBrowserPlugin::documentJumpPerformed); KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() ); updateDeclarationListBox(m_history[historyIndex].context.data()); } } void ContextBrowserPlugin::historyPrevious() { if(m_nextHistoryIndex < 2) { return; } --m_nextHistoryIndex; openDocument(m_nextHistoryIndex-1); // opening the document at given position // will update the widget for us updateButtonState(); } QString ContextBrowserPlugin::actionTextFor(int historyIndex) const { const HistoryEntry& entry = m_history.at(historyIndex); QString actionText = entry.context.data() ? entry.context.data()->scopeIdentifier(true).toString() : QString(); if(actionText.isEmpty()) actionText = entry.alternativeString; if(actionText.isEmpty()) actionText = ""; actionText += " @ "; QString fileName = entry.absoluteCursorPosition.document.toUrl().fileName(); actionText += QStringLiteral("%1:%2").arg(fileName).arg(entry.absoluteCursorPosition.line()+1); return actionText; } /* inline QDebug operator<<(QDebug debug, const ContextBrowserPlugin::HistoryEntry &he) { DocumentCursor c = he.computePosition(); debug << "\n\tHistoryEntry " << c.line << " " << c.document.str(); return debug; } */ void ContextBrowserPlugin::nextMenuAboutToShow() { QList indices; for(int a = m_nextHistoryIndex; a < m_history.size(); ++a) { indices << a; } fillHistoryPopup(m_nextMenu, indices); } void ContextBrowserPlugin::previousMenuAboutToShow() { QList indices; for(int a = m_nextHistoryIndex-2; a >= 0; --a) { indices << a; } fillHistoryPopup(m_previousMenu, indices); } void ContextBrowserPlugin::fillHistoryPopup(QMenu* menu, const QList& historyIndices) { menu->clear(); KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() ); foreach(int index, historyIndices) { QAction* action = new QAction(actionTextFor(index), menu); action->setData(index); menu->addAction(action); connect(action, &QAction::triggered, this, &ContextBrowserPlugin::actionTriggered); } } bool ContextBrowserPlugin::isPreviousEntry(KDevelop::DUContext* context, const KTextEditor::Cursor& /*position*/) const { if (m_nextHistoryIndex == 0) return false; Q_ASSERT(m_nextHistoryIndex <= m_history.count()); const HistoryEntry& he = m_history.at(m_nextHistoryIndex-1); KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() ); // is this necessary?? Q_ASSERT(context); return IndexedDUContext(context) == he.context; } void ContextBrowserPlugin::updateHistory(KDevelop::DUContext* context, const KTextEditor::Cursor& position, bool force) { qCDebug(PLUGIN_CONTEXTBROWSER) << "updating history"; if(m_outlineLine && m_outlineLine->isVisible()) updateDeclarationListBox(context); if(!context || (!context->owner() && !force)) { return; //Only add history-entries for contexts that have owners, which in practice should be functions and classes //This keeps the history cleaner } if (isPreviousEntry(context, position)) { if(m_nextHistoryIndex) { HistoryEntry& he = m_history[m_nextHistoryIndex-1]; he.setCursorPosition(position); } return; } else { // Append new history entry m_history.resize(m_nextHistoryIndex); // discard forward history m_history.append(HistoryEntry(IndexedDUContext(context), position)); ++m_nextHistoryIndex; updateButtonState(); if(m_history.size() > (maxHistoryLength + 5)) { m_history = m_history.mid(m_history.size() - maxHistoryLength); m_nextHistoryIndex = m_history.size(); } } } void ContextBrowserPlugin::setAllowBrowsing(bool allow) { m_browseButton->setChecked(allow); } void ContextBrowserPlugin::updateDeclarationListBox(DUContext* context) { if(!context || !context->owner()) { qCDebug(PLUGIN_CONTEXTBROWSER) << "not updating box"; m_listUrl = IndexedString(); ///@todo Compute the context in the document here if (m_outlineLine) m_outlineLine->clear(); return; } Declaration* decl = context->owner(); m_listUrl = context->url(); Declaration* specialDecl = SpecializationStore::self().applySpecialization(decl, decl->topContext()); FunctionType::Ptr function = specialDecl->type(); QString text = specialDecl->qualifiedIdentifier().toString(); if(function) text += function->partToString(KDevelop::FunctionType::SignatureArguments); if(m_outlineLine && !m_outlineLine->hasFocus()) { m_outlineLine->setText(text); m_outlineLine->setCursorPosition(0); } qCDebug(PLUGIN_CONTEXTBROWSER) << "updated" << text; } void ContextBrowserPlugin::actionTriggered() { QAction* action = qobject_cast(sender()); Q_ASSERT(action); Q_ASSERT(action->data().type() == QVariant::Int); int historyPosition = action->data().toInt(); // qCDebug(PLUGIN_CONTEXTBROWSER) << "history pos" << historyPosition << m_history.size() << m_history; if(historyPosition >= 0 && historyPosition < m_history.size()) { m_nextHistoryIndex = historyPosition + 1; openDocument(historyPosition); updateButtonState(); } } void ContextBrowserPlugin::doNavigate(NavigationActionType action) { KTextEditor::View* view = qobject_cast(sender()); if(!view) { qWarning() << "sender is not a view"; return; } KTextEditor::CodeCompletionInterface* iface = qobject_cast(view); if(!iface || iface->isCompletionActive()) return; // If code completion is active, the actions should be handled by the completion widget QWidget* widget = m_currentNavigationWidget.data(); if(!widget || !widget->isVisible()) { ContextBrowserView* contextView = browserViewForWidget(view); if(contextView) widget = contextView->navigationWidget(); } if(widget) { AbstractNavigationWidget* navWidget = qobject_cast(widget); if (navWidget) { switch(action) { case Accept: navWidget->accept(); break; case Back: navWidget->back(); break; case Left: navWidget->previous(); break; case Right: navWidget->next(); break; case Up: navWidget->up(); break; case Down: navWidget->down(); break; } } } } void ContextBrowserPlugin::navigateAccept() { doNavigate(Accept); } void ContextBrowserPlugin::navigateBack() { doNavigate(Back); } void ContextBrowserPlugin::navigateDown() { doNavigate(Down); } void ContextBrowserPlugin::navigateLeft() { doNavigate(Left); } void ContextBrowserPlugin::navigateRight() { doNavigate(Right); } void ContextBrowserPlugin::navigateUp() { doNavigate(Up); } //BEGIN HistoryEntry ContextBrowserPlugin::HistoryEntry::HistoryEntry(KDevelop::DocumentCursor pos) : absoluteCursorPosition(pos) { } ContextBrowserPlugin::HistoryEntry::HistoryEntry(IndexedDUContext ctx, const KTextEditor::Cursor& cursorPosition) : context(ctx) { //Use a position relative to the context setCursorPosition(cursorPosition); if(ctx.data()) alternativeString = ctx.data()->scopeIdentifier(true).toString(); if(!alternativeString.isEmpty()) alternativeString += i18n("(changed)"); //This is used when the context was deleted in between } DocumentCursor ContextBrowserPlugin::HistoryEntry::computePosition() const { KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() ); DocumentCursor ret; if(context.data()) { ret = DocumentCursor(context.data()->url(), relativeCursorPosition); ret.setLine(ret.line() + context.data()->range().start.line); }else{ ret = absoluteCursorPosition; } return ret; } void ContextBrowserPlugin::HistoryEntry::setCursorPosition(const KTextEditor::Cursor& cursorPosition) { KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() ); if(context.data()) { absoluteCursorPosition = DocumentCursor(context.data()->url(), cursorPosition); relativeCursorPosition = cursorPosition; relativeCursorPosition.setLine(relativeCursorPosition.line() - context.data()->range().start.line); } } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on #include "contextbrowser.moc" diff --git a/plugins/contextbrowser/contextbrowser.h b/plugins/contextbrowser/contextbrowser.h index 68dfaa55f6..7a7db04930 100644 --- a/plugins/contextbrowser/contextbrowser.h +++ b/plugins/contextbrowser/contextbrowser.h @@ -1,271 +1,271 @@ /* * This file is part of KDevelop * * Copyright 2007 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. */ #ifndef KDEVPLATFORM_PLUGIN_CONTEXTBROWSERPLUGIN_H #define KDEVPLATFORM_PLUGIN_CONTEXTBROWSERPLUGIN_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class QHBoxLayout; class QMenu; class QToolButton; namespace Sublime { class MainWindow; } namespace KDevelop { class IDocument; class ParseJob; class DUContext; class TopDUContext; class DUChainBase; class AbstractNavigationWidget; } namespace KTextEditor { class Document; class View; } class ContextBrowserViewFactory; class ContextBrowserView; class BrowseManager; QWidget* masterWidget(QWidget* w); struct ViewHighlights { ViewHighlights() : keep(false) { } // Whether the same highlighting should be kept highlighted (usually during typing) bool keep; // The declaration that is highlighted for this view KDevelop::IndexedDeclaration declaration; // Highlighted ranges. Those may also be contained by different views. QList highlights; }; class ContextBrowserPlugin : public KDevelop::IPlugin, public KDevelop::IContextBrowser { Q_OBJECT Q_INTERFACES( KDevelop::IContextBrowser ) public: explicit ContextBrowserPlugin(QObject *parent, const QVariantList & = QVariantList() ); - virtual ~ContextBrowserPlugin(); + ~ContextBrowserPlugin() override; - virtual void unload() override; + void unload() override; void registerToolView(ContextBrowserView* view); void unRegisterToolView(ContextBrowserView* view); - virtual KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context*) override; + KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context*) override; - virtual KXMLGUIClient* createGUIForMainWindow( Sublime::MainWindow* window ) override; + KXMLGUIClient* createGUIForMainWindow( Sublime::MainWindow* window ) override; ///duchain must be locked ///@param force When this is true, the history-entry is added, no matter whether the context is "interesting" or not void updateHistory(KDevelop::DUContext* context, const KTextEditor::Cursor& cursorPosition, bool force = false); void updateDeclarationListBox(KDevelop::DUContext* context); void setAllowBrowsing(bool allow); - virtual void showUses(const KDevelop::DeclarationPointer& declaration) override; + void showUses(const KDevelop::DeclarationPointer& declaration) override; public Q_SLOTS: void showUsesDelayed(const KDevelop::DeclarationPointer& declaration); void previousContextShortcut(); void nextContextShortcut(); void startDelayedBrowsing(KTextEditor::View* view); void stopDelayedBrowsing(); void previousUseShortcut(); void nextUseShortcut(); void declarationSelectedInUI(const KDevelop::DeclarationPointer& decl); void parseJobFinished(KDevelop::ParseJob* job); void textDocumentCreated( KDevelop::IDocument* document ); void documentActivated( KDevelop::IDocument* ); void viewDestroyed( QObject* obj ); void cursorPositionChanged( KTextEditor::View* view, const KTextEditor::Cursor& newPosition ); void viewCreated( KTextEditor::Document* , KTextEditor::View* ); void updateViews(); void hideToolTip(); void findUses(); void textInserted(KTextEditor::Document* doc, const KTextEditor::Cursor& cursor, const QString& text); void selectionChanged(KTextEditor::View*); void historyNext(); void historyPrevious(); private slots: // history browsing void documentJumpPerformed( KDevelop::IDocument* newDocument, const KTextEditor::Cursor& newCursor, KDevelop::IDocument* previousDocument, const KTextEditor::Cursor& previousCursor); void nextMenuAboutToShow(); void previousMenuAboutToShow(); void actionTriggered(); void navigateLeft(); void navigateRight(); void navigateUp(); void navigateDown(); void navigateAccept(); void navigateBack(); private: QWidget* toolbarWidgetForMainWindow(Sublime::MainWindow* window); - virtual void createActionsForMainWindow(Sublime::MainWindow* window, QString& xmlFile, + void createActionsForMainWindow(Sublime::MainWindow* window, QString& xmlFile, KActionCollection& actions) override; void switchUse(bool forward); void clearMouseHover(); void addHighlight( KTextEditor::View* view, KDevelop::Declaration* decl ); /** helper for updateBrowserView(). * Tries to find a 'specialLanguageObject' (eg macro) in @p view under cursor @c. * If found returns true and sets @p pickedLanguage to the language this object belongs to */ KDevelop::Declaration* findDeclaration(KTextEditor::View* view, const KTextEditor::Cursor&, bool mouseHighlight); void updateForView(KTextEditor::View* view); // history browsing bool isPreviousEntry(KDevelop::DUContext*, const KTextEditor::Cursor& cursor) const; QString actionTextFor(int historyIndex) const; void updateButtonState(); void openDocument(int historyIndex); void fillHistoryPopup(QMenu* menu, const QList& historyIndices); enum NavigationActionType { Accept, Back, Down, Up, Left, Right }; void doNavigate(NavigationActionType action); private: // Returns the currently active and visible context browser view that belongs // to the same context (mainwindow and area) as the given widget ContextBrowserView* browserViewForWidget(QWidget* widget); void showToolTip(KTextEditor::View* view, KTextEditor::Cursor position); QTimer* m_updateTimer; //Contains the range, the old attribute, and the attribute it was replaced with QSet m_updateViews; QMap m_highlightedRanges; //Holds a list of all active context browser tool views QList m_views; //Used to override the next declaration that will be highlighted KDevelop::IndexedDeclaration m_useDeclaration; KDevelop::IndexedDeclaration m_lastHighlightedDeclaration; QUrl m_mouseHoverDocument; KTextEditor::Cursor m_mouseHoverCursor; ContextBrowserViewFactory* m_viewFactory; QPointer m_currentToolTip; QPointer m_currentNavigationWidget; KDevelop::IndexedDeclaration m_currentToolTipDeclaration; QAction* m_findUses; QPointer m_lastInsertionDocument; KTextEditor::Cursor m_lastInsertionPos; // outline toolbar QPointer m_outlineLine; QPointer m_toolbarWidgetLayout; QPointer m_toolbarWidget; // history browsing struct HistoryEntry { //Duchain must be locked HistoryEntry(KDevelop::IndexedDUContext ctx = KDevelop::IndexedDUContext(), const KTextEditor::Cursor& cursorPosition = KTextEditor::Cursor()); HistoryEntry(KDevelop::DocumentCursor pos); //Duchain must be locked void setCursorPosition(const KTextEditor::Cursor& cursorPosition); //Duchain does not need to be locked KDevelop::DocumentCursor computePosition() const; KDevelop::IndexedDUContext context; KDevelop::DocumentCursor absoluteCursorPosition; KTextEditor::Cursor relativeCursorPosition; //Cursor position relative to the start line of the context QString alternativeString; }; QVector m_history; QPointer m_previousButton; QPointer m_nextButton; QPointer m_previousMenu, m_nextMenu; QPointer m_browseButton; QList m_listDeclarations; KDevelop::IndexedString m_listUrl; BrowseManager* m_browseManager; //Used to not record jumps triggered by the context-browser as history entries QPointer m_focusBackWidget; int m_nextHistoryIndex; friend class ContextBrowserHintProvider; }; class ContextBrowserHintProvider : public KTextEditor::TextHintProvider { public: explicit ContextBrowserHintProvider(ContextBrowserPlugin* plugin); - virtual QString textHint(KTextEditor::View* view, const KTextEditor::Cursor& position) override; + QString textHint(KTextEditor::View* view, const KTextEditor::Cursor& position) override; private: ContextBrowserPlugin* m_plugin; }; #endif // KDEVPLATFORM_PLUGIN_CONTEXTBROWSERPLUGIN_H // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/contextbrowser/contextbrowserview.h b/plugins/contextbrowser/contextbrowserview.h index 77556e42be..03a57c2870 100644 --- a/plugins/contextbrowser/contextbrowserview.h +++ b/plugins/contextbrowser/contextbrowserview.h @@ -1,114 +1,114 @@ /* * 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. */ #ifndef KDEVPLATFORM_PLUGIN_CONTEXTBROWSERVIEW_H #define KDEVPLATFORM_PLUGIN_CONTEXTBROWSERVIEW_H #include #include #include #include #include #include class ContextBrowserPlugin; class QVBoxLayout; class QHBoxLayout; class QToolButton; class QCheckBox; class QMenu; class KComboBox; namespace KDevelop { class IDocument; } class ContextBrowserView : public QWidget { Q_OBJECT public: ContextBrowserView( ContextBrowserPlugin*, QWidget* parent ); - ~ContextBrowserView(); + ~ContextBrowserView() override; //duchain must be locked void setContext(KDevelop::DUContext* context); void setDeclaration(KDevelop::Declaration* decl, KDevelop::TopDUContext* topContext, bool force = false); void setSpecialNavigationWidget(QWidget*); void updateMainWidget(QWidget*); /** Allows a single update of the view even if in locked state. * This is needed to browse while the locked button is checked. */ void allowLockedUpdate(); ///Returns the currently locked declaration, or invalid of none is locked atm. KDevelop::IndexedDeclaration lockedDeclaration() const; void setNavigationWidget(QWidget* widget); QWidget* navigationWidget() { return m_navigationWidget; } //duchain must be locked QWidget* createWidget(KDevelop::DUContext* context); //duchain must be locked QWidget* createWidget(KDevelop::Declaration* decl, KDevelop::TopDUContext* topContext); KDevelop::IndexedDeclaration declaration() const; ///Returns whether the view is currently locked bool isLocked() const; private Q_SLOTS: void updateLockIcon(bool); void declarationMenu(); void navigationContextChanged(bool wasInitial, bool isInitial); private: - virtual void showEvent(QShowEvent* event) override; - virtual bool event(QEvent* event) override; + void showEvent(QShowEvent* event) override; + bool event(QEvent* event) override; - virtual void focusInEvent(QFocusEvent* event) override; - virtual void focusOutEvent(QFocusEvent* event) override; + void focusInEvent(QFocusEvent* event) override; + void focusOutEvent(QFocusEvent* event) override; void resetWidget(); private: KDevelop::IndexedDeclaration m_declaration; ContextBrowserPlugin* m_plugin; QVBoxLayout* m_layout; QToolButton* m_lockButton; QToolButton* m_declarationMenuButton; QHBoxLayout* m_buttons; QPointer m_navigationWidget; KDevelop::DeclarationId m_navigationWidgetDeclaration; bool m_allowLockedUpdate; KDevelop::IndexedTopDUContext m_lastUsedTopContext; KDevelop::IndexedDUContext m_context; // Whether the lock-button was activated automatically due to user navigation bool m_autoLocked; }; #endif diff --git a/plugins/cvs/checkoutdialog.h b/plugins/cvs/checkoutdialog.h index c1bfeb1422..e49c397d61 100644 --- a/plugins/cvs/checkoutdialog.h +++ b/plugins/cvs/checkoutdialog.h @@ -1,42 +1,42 @@ /*************************************************************************** * Copyright 2007 Robert Gruber * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_CHECKOUTDIALOG_H #define KDEVPLATFORM_PLUGIN_CHECKOUTDIALOG_H #include #include #include #include "ui_checkoutdialog.h" class CvsPlugin; /** * Allows the user to define from where to checkout * @author Robert Gruber */ class CheckoutDialog : public QDialog, private Ui::CheckoutDialogBase { Q_OBJECT public: explicit CheckoutDialog(CvsPlugin* plugin, QWidget *parent=0); - virtual ~CheckoutDialog(); + ~CheckoutDialog() override; public slots: - virtual void accept() override; + void accept() override; void jobFinished(KJob* job); private: CvsPlugin* m_plugin; }; #endif diff --git a/plugins/cvs/commitdialog.h b/plugins/cvs/commitdialog.h index 5a47c36b28..d8d674c2c1 100644 --- a/plugins/cvs/commitdialog.h +++ b/plugins/cvs/commitdialog.h @@ -1,37 +1,37 @@ /*************************************************************************** * Copyright 2007 Robert Gruber * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_COMMITDIALOG_H #define KDEVPLATFORM_PLUGIN_COMMITDIALOG_H #include #include #include "ui_commitdialog.h" /** * Allows to enter text which can them be used as * parameter for @code cvs commit @endcode * @author Robert Gruber */ class CommitDialog : public QDialog, private Ui::CommitDialogBase { Q_OBJECT public: explicit CommitDialog(QDialog *parent = 0); - virtual ~CommitDialog(); + ~CommitDialog() override; /** * @return The text entered by the user */ QString message() { return textedit->toPlainText(); } }; #endif diff --git a/plugins/cvs/cvsannotatejob.h b/plugins/cvs/cvsannotatejob.h index 5f88c6c63c..751086b028 100644 --- a/plugins/cvs/cvsannotatejob.h +++ b/plugins/cvs/cvsannotatejob.h @@ -1,36 +1,36 @@ /*************************************************************************** * Copyright 2008 Robert Gruber * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_CVSANNOTATEJOB_H #define KDEVPLATFORM_PLUGIN_CVSANNOTATEJOB_H #include #include "cvsjob.h" /** * @author Robert Gruber */ class CvsAnnotateJob : public CvsJob { Q_OBJECT public: explicit CvsAnnotateJob(KDevelop::IPlugin* parent, KDevelop::OutputJob::OutputJobVerbosity verbosity = KDevelop::OutputJob::Verbose); - virtual ~CvsAnnotateJob(); + ~CvsAnnotateJob() override; // Begin: KDevelop::VcsJob - virtual QVariant fetchResults() override; + QVariant fetchResults() override; // End: KDevelop::VcsJob private: void parseOutput(const QString& jobOutput, const QString& workingDirectory, KDevelop::VcsAnnotation& annotateInfo); }; #endif diff --git a/plugins/cvs/cvsdiffjob.h b/plugins/cvs/cvsdiffjob.h index 1716e02459..158ce62e5d 100644 --- a/plugins/cvs/cvsdiffjob.h +++ b/plugins/cvs/cvsdiffjob.h @@ -1,38 +1,38 @@ /*************************************************************************** * Copyright 2008 Robert Gruber * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_CVSDIFFJOB_H #define KDEVPLATFORM_PLUGIN_CVSDIFFJOB_H #include "cvsjob.h" #include /** * @author Robert Gruber */ class CvsDiffJob : public CvsJob { Q_OBJECT public: explicit CvsDiffJob(KDevelop::IPlugin* parent, KDevelop::OutputJob::OutputJobVerbosity verbosity = KDevelop::OutputJob::Verbose); - virtual ~CvsDiffJob(); + ~CvsDiffJob() override; // Begin: KDevelop::VcsJob - virtual QVariant fetchResults() override; + QVariant fetchResults() override; // End: KDevelop::VcsJob private: // Begin: KDevelop::DVcsJob - virtual void slotProcessError(QProcess::ProcessError error) override; + void slotProcessError(QProcess::ProcessError error) override; // End: KDevelop::DVcsJob }; #endif diff --git a/plugins/cvs/cvsgenericoutputview.h b/plugins/cvs/cvsgenericoutputview.h index 2ae33456ba..435d9a9fa1 100644 --- a/plugins/cvs/cvsgenericoutputview.h +++ b/plugins/cvs/cvsgenericoutputview.h @@ -1,42 +1,42 @@ /*************************************************************************** * Copyright 2007 Robert Gruber * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_CVSGENERICOUTPUTVIEW_H #define KDEVPLATFORM_PLUGIN_CVSGENERICOUTPUTVIEW_H #include #include #include "ui_cvsgenericoutputview.h" class CvsPlugin; class CvsJob; /** * Shows plain text. * * Text can either be added directly by calling appendText(). * * Or by connecting a job's result() signal to slotJobFinished(). * * @author Robert Gruber */ class CvsGenericOutputView : public QWidget, private Ui::CvsGenericOutputViewBase { Q_OBJECT public: explicit CvsGenericOutputView(CvsJob* job = 0, QWidget* parent = 0); - virtual ~CvsGenericOutputView(); + ~CvsGenericOutputView() override; public slots: void appendText(const QString& text); void slotJobFinished(KJob* job); }; #endif diff --git a/plugins/cvs/cvsjob.h b/plugins/cvs/cvsjob.h index 5b34a01961..54a7755015 100644 --- a/plugins/cvs/cvsjob.h +++ b/plugins/cvs/cvsjob.h @@ -1,60 +1,60 @@ /*************************************************************************** * This file was partly taken from cervisia's cvsservice * * Copyright 2002-2003 Christian Loose * * * * Adapted for KDevelop * * Copyright 2007 Robert Gruber * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_CVSJOB_H #define KDEVPLATFORM_PLUGIN_CVSJOB_H #include #include #include /** * This class is capable of running our cvs commands * Connect to Kjob::result(KJob*) to be notified when the job finished. * @author Robert Gruber */ class CvsJob : public KDevelop::DVcsJob { Q_OBJECT public: explicit CvsJob(const QDir& workingDir, KDevelop::IPlugin* parent=0, KDevelop::OutputJob::OutputJobVerbosity verbosity = KDevelop::OutputJob::Verbose); explicit CvsJob(KDevelop::IPlugin* parent = 0, KDevelop::OutputJob::OutputJobVerbosity verbosity = KDevelop::OutputJob::Verbose); - virtual ~CvsJob(); + ~CvsJob() override; /** * @return The command that is executed when calling start() */ QString cvsCommand(); void clear(); void setDirectory(const QString& directory); QString getDirectory(); void setRSH(const QString& rsh); void setServer(const QString& server); /** * Call this method to start this job. * @note Default communication mode is KProcess::AllOutput. * @see Use setCommunicationMode() to override the default communication mode. */ - virtual void start() override; + void start() override; private: class CvsJobPrivate* const d; }; #endif diff --git a/plugins/cvs/cvslogjob.h b/plugins/cvs/cvslogjob.h index ecabb1cc95..8f587feb2a 100644 --- a/plugins/cvs/cvslogjob.h +++ b/plugins/cvs/cvslogjob.h @@ -1,34 +1,34 @@ /*************************************************************************** * Copyright 2008 Robert Gruber * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_CVSLOGJOB_H #define KDEVPLATFORM_PLUGIN_CVSLOGJOB_H #include "cvsjob.h" /** * @author Robert Gruber */ class CvsLogJob : public CvsJob { Q_OBJECT public: explicit CvsLogJob(KDevelop::IPlugin* parent, KDevelop::OutputJob::OutputJobVerbosity verbosity = KDevelop::OutputJob::Verbose); - virtual ~CvsLogJob(); + ~CvsLogJob() override; // Begin: KDevelop::VcsJob - virtual QVariant fetchResults() override; + QVariant fetchResults() override; // End: KDevelop::VcsJob private: void parseOutput(const QString& jobOutput, QList& events); }; #endif diff --git a/plugins/cvs/cvsmainview.h b/plugins/cvs/cvsmainview.h index 3c8817bca5..d4ac748d3c 100644 --- a/plugins/cvs/cvsmainview.h +++ b/plugins/cvs/cvsmainview.h @@ -1,67 +1,67 @@ /*************************************************************************** * Copyright 2007 Robert Gruber * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_CVSMAINVIEW_H #define KDEVPLATFORM_PLUGIN_CVSMAINVIEW_H #include #include #include #include "ui_cvsmainview.h" class CvsPlugin; class CvsGenericOutputView; /** * This class is the main output view of KDevelop's CVS plugin. * It only constists out of a QTabWidget. * * When created, a CvsGenericOutputView will be inserted. * * Inserting text into that default output view is possible via the * slotJobFinished() slot. * * Additional tabs can be added via slotAddTab(). * * @author Robert Gruber */ class CvsMainView : public QWidget, private Ui::CvsMainViewBase { Q_OBJECT public: CvsMainView(CvsPlugin *plugin, QWidget* parent); - virtual ~CvsMainView(); + ~CvsMainView() override; public slots: /** * Inserts @p tag into the QTabWidget and calls it @p label . * This slot gets connected to CvsPlugin::addNewTabToMainView(). */ void slotAddTab(QWidget* tab, const QString& label); /** * When this slot gets called, the output of the job will be written to * the default outputview of the QTabWidget. * This slot gets connected to CvsPlugin::jobFinished(). */ void slotJobFinished(KJob* job); /** * Closes the current active tab (if it's not the first tab) */ void slotTabClose(); private: CvsPlugin* m_plugin; CvsGenericOutputView* m_mainview; QToolButton* m_closeButton; }; #endif diff --git a/plugins/cvs/cvsplugin.cpp b/plugins/cvs/cvsplugin.cpp index 5e3b28d802..356eb85c17 100644 --- a/plugins/cvs/cvsplugin.cpp +++ b/plugins/cvs/cvsplugin.cpp @@ -1,489 +1,489 @@ /*************************************************************************** * Copyright 2007 Robert Gruber * * * * 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. * * * ***************************************************************************/ #include "cvsplugin.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cvsmainview.h" #include "cvsproxy.h" #include "cvsjob.h" #include "editorsview.h" #include "commitdialog.h" #include "cvsgenericoutputview.h" #include "checkoutdialog.h" #include "importdialog.h" #include "importmetadatawidget.h" #include "debug.h" #include #include #include Q_LOGGING_CATEGORY(PLUGIN_CVS, "kdevplatform.plugins.cvs") K_PLUGIN_FACTORY(KDevCvsFactory, registerPlugin();) // K_EXPORT_PLUGIN(KDevCvsFactory(KAboutData("kdevcvs", "kdevcvs", ki18n("CVS"), "0.1", ki18n("Support for CVS version control system"), KAboutData::License_GPL))) class KDevCvsViewFactory: public KDevelop::IToolViewFactory { public: KDevCvsViewFactory(CvsPlugin *plugin): m_plugin(plugin) {} - virtual QWidget* create(QWidget *parent = 0) override { + QWidget* create(QWidget *parent = 0) override { return new CvsMainView(m_plugin, parent); } - virtual Qt::DockWidgetArea defaultPosition() override { + Qt::DockWidgetArea defaultPosition() override { return Qt::BottomDockWidgetArea; } - virtual QString id() const override { + QString id() const override { return "org.kdevelop.CVSView"; } private: CvsPlugin *m_plugin; }; class CvsPluginPrivate { public: explicit CvsPluginPrivate(CvsPlugin *pThis) : m_factory(new KDevCvsViewFactory(pThis)) , m_proxy(new CvsProxy(pThis)) , m_common(new KDevelop::VcsPluginHelper(pThis, pThis)) {} KDevCvsViewFactory* m_factory; QPointer m_proxy; QScopedPointer m_common; }; CvsPlugin::CvsPlugin(QObject *parent, const QVariantList &) : KDevelop::IPlugin("kdevcvs", parent) , d(new CvsPluginPrivate(this)) { KDEV_USE_EXTENSION_INTERFACE(KDevelop::IBasicVersionControl) KDEV_USE_EXTENSION_INTERFACE(KDevelop::ICentralizedVersionControl) core()->uiController()->addToolView(i18n("CVS"), d->m_factory); setXMLFile("kdevcvs.rc"); setupActions(); } CvsPlugin::~CvsPlugin() { } void CvsPlugin::unload() { core()->uiController()->removeToolView( d->m_factory ); } CvsProxy* CvsPlugin::proxy() { return d->m_proxy; } void CvsPlugin::setupActions() { QAction *action; action = actionCollection()->addAction("cvs_import"); action->setText(i18n("Import Directory...")); connect(action, &QAction::triggered, this, &CvsPlugin::slotImport); action = actionCollection()->addAction("cvs_checkout"); action->setText(i18n("Checkout...")); connect(action, &QAction::triggered, this, &CvsPlugin::slotCheckout); action = actionCollection()->addAction("cvs_status"); action->setText(i18n("Status...")); connect(action, &QAction::triggered, this, &CvsPlugin::slotStatus); } const QUrl CvsPlugin::urlFocusedDocument() const { KParts::ReadOnlyPart *plugin = dynamic_cast(core()->partController()->activePart()); if (plugin) { if (plugin->url().isLocalFile()) { return plugin->url(); } } return QUrl(); } void CvsPlugin::slotImport() { QUrl url = urlFocusedDocument(); ImportDialog dlg(this, url); dlg.exec(); } void CvsPlugin::slotCheckout() { ///@todo don't use proxy directly; use interface instead CheckoutDialog dlg(this); dlg.exec(); } void CvsPlugin::slotStatus() { QUrl url = urlFocusedDocument(); QList urls; urls << url; KDevelop::VcsJob* j = status(urls, KDevelop::IBasicVersionControl::Recursive); CvsJob* job = dynamic_cast(j); if (job) { CvsGenericOutputView* view = new CvsGenericOutputView(job); emit addNewTabToMainView(view, i18n("Status")); KDevelop::ICore::self()->runController()->registerJob(job); } } KDevelop::ContextMenuExtension CvsPlugin::contextMenuExtension(KDevelop::Context* context) { d->m_common->setupFromContext(context); QList const & ctxUrlList = d->m_common->contextUrlList(); bool hasVersionControlledEntries = false; foreach(const QUrl &url, ctxUrlList) { if (d->m_proxy->isValidDirectory(url)) { hasVersionControlledEntries = true; break; } } qCDebug(PLUGIN_CVS) << "version controlled?" << hasVersionControlledEntries; if (!hasVersionControlledEntries) return IPlugin::contextMenuExtension(context); QMenu* menu = d->m_common->commonActions(); menu->addSeparator(); QAction *action; // Just add actions which are not covered by the cvscommon plugin action = new QAction(i18n("Edit"), this); connect(action, &QAction::triggered, this, &CvsPlugin::ctxEdit); menu->addAction(action); action = new QAction(i18n("Unedit"), this); connect(action, &QAction::triggered, this, &CvsPlugin::ctxUnEdit); menu->addAction(action); action = new QAction(i18n("Show Editors"), this); connect(action, &QAction::triggered, this, &CvsPlugin::ctxEditors); menu->addAction(action); KDevelop::ContextMenuExtension menuExt; menuExt.addAction(KDevelop::ContextMenuExtension::VcsGroup, menu->menuAction()); return menuExt; } void CvsPlugin::ctxEdit() { QList const & urls = d->m_common->contextUrlList(); Q_ASSERT(!urls.empty()); KDevelop::VcsJob* j = edit(urls.front()); CvsJob* job = dynamic_cast(j); if (job) { connect(job, &CvsJob::result, this, &CvsPlugin::jobFinished); KDevelop::ICore::self()->runController()->registerJob(job); } } void CvsPlugin::ctxUnEdit() { QList const & urls = d->m_common->contextUrlList(); Q_ASSERT(!urls.empty()); KDevelop::VcsJob* j = unedit(urls.front()); CvsJob* job = dynamic_cast(j); if (job) { connect(job, &CvsJob::result, this, &CvsPlugin::jobFinished); KDevelop::ICore::self()->runController()->registerJob(job); } } void CvsPlugin::ctxEditors() { QList const & urls = d->m_common->contextUrlList(); Q_ASSERT(!urls.empty()); CvsJob* job = d->m_proxy->editors(findWorkingDir(urls.front()), urls); if (job) { KDevelop::ICore::self()->runController()->registerJob(job); EditorsView* view = new EditorsView(job); emit addNewTabToMainView(view, i18n("Editors")); } } QString CvsPlugin::findWorkingDir(const QUrl& location) { QFileInfo fileInfo(location.toLocalFile()); // find out correct working directory if (fileInfo.isFile()) { return fileInfo.absolutePath(); } else { return fileInfo.absoluteFilePath(); } } // Begin: KDevelop::IBasicVersionControl bool CvsPlugin::isVersionControlled(const QUrl & localLocation) { return d->m_proxy->isVersionControlled(localLocation); } KDevelop::VcsJob * CvsPlugin::repositoryLocation(const QUrl & localLocation) { Q_UNUSED(localLocation); return NULL; } KDevelop::VcsJob * CvsPlugin::add(const QList & localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion) { CvsJob* job = d->m_proxy->add(findWorkingDir(localLocations[0]), localLocations, (recursion == KDevelop::IBasicVersionControl::Recursive) ? true : false); return job; } KDevelop::VcsJob * CvsPlugin::remove(const QList & localLocations) { CvsJob* job = d->m_proxy->remove(findWorkingDir(localLocations[0]), localLocations); return job; } KDevelop::VcsJob * CvsPlugin::localRevision(const QUrl & localLocation, KDevelop::VcsRevision::RevisionType) { Q_UNUSED(localLocation) return NULL; } KDevelop::VcsJob * CvsPlugin::status(const QList & localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion) { CvsJob* job = d->m_proxy->status(findWorkingDir(localLocations[0]), localLocations, (recursion == KDevelop::IBasicVersionControl::Recursive) ? true : false); return job; } KDevelop::VcsJob * CvsPlugin::unedit(const QUrl& localLocation) { CvsJob* job = d->m_proxy->unedit(findWorkingDir(localLocation), QList() << localLocation); return job; } KDevelop::VcsJob * CvsPlugin::edit(const QUrl& localLocation) { CvsJob* job = d->m_proxy->edit(findWorkingDir(localLocation), QList() << localLocation); return job; } KDevelop::VcsJob * CvsPlugin::copy(const QUrl & localLocationSrc, const QUrl & localLocationDstn) { bool ok = QFile::copy(localLocationSrc.toLocalFile(), localLocationDstn.path()); if (!ok) { return NULL; } QList listDstn; listDstn << localLocationDstn; CvsJob* job = d->m_proxy->add(findWorkingDir(localLocationDstn), listDstn, true); return job; } KDevelop::VcsJob * CvsPlugin::move(const QUrl &, const QUrl &) { return NULL; } KDevelop::VcsJob * CvsPlugin::revert(const QList & localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion) { KDevelop::VcsRevision rev; CvsJob* job = d->m_proxy->update(findWorkingDir(localLocations[0]), localLocations, rev, "-C", (recursion == KDevelop::IBasicVersionControl::Recursive) ? true : false, false, false); return job; } KDevelop::VcsJob * CvsPlugin::update(const QList & localLocations, const KDevelop::VcsRevision & rev, KDevelop::IBasicVersionControl::RecursionMode recursion) { CvsJob* job = d->m_proxy->update(findWorkingDir(localLocations[0]), localLocations, rev, "", (recursion == KDevelop::IBasicVersionControl::Recursive) ? true : false, false, false); return job; } KDevelop::VcsJob * CvsPlugin::commit(const QString & message, const QList & localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion) { Q_UNUSED(recursion); QString msg = message; if (msg.isEmpty()) { CommitDialog dlg; if (dlg.exec() == QDialog::Accepted) { msg = dlg.message(); } } CvsJob* job = d->m_proxy->commit(findWorkingDir(localLocations[0]), localLocations, msg); return job; } KDevelop::VcsJob * CvsPlugin::diff(const QUrl & fileOrDirectory, const KDevelop::VcsRevision & srcRevision, const KDevelop::VcsRevision & dstRevision, KDevelop::VcsDiff::Type, KDevelop::IBasicVersionControl::RecursionMode) { CvsJob* job = d->m_proxy->diff(fileOrDirectory, srcRevision, dstRevision, "-uN"/*always unified*/); return job; } KDevelop::VcsJob * CvsPlugin::log(const QUrl & localLocation, const KDevelop::VcsRevision & rev, unsigned long limit) { Q_UNUSED(limit) CvsJob* job = d->m_proxy->log(localLocation, rev); return job; } KDevelop::VcsJob * CvsPlugin::log(const QUrl & localLocation, const KDevelop::VcsRevision & rev, const KDevelop::VcsRevision & limit) { Q_UNUSED(limit) return log(localLocation, rev, 0); } KDevelop::VcsJob * CvsPlugin::annotate(const QUrl & localLocation, const KDevelop::VcsRevision & rev) { CvsJob* job = d->m_proxy->annotate(localLocation, rev); return job; } KDevelop::VcsJob * CvsPlugin::resolve(const QList & localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion) { Q_UNUSED(localLocations); Q_UNUSED(recursion); return NULL; } KDevelop::VcsJob * CvsPlugin::import(const QString& commitMessage, const QUrl& sourceDirectory, const KDevelop::VcsLocation& destinationRepository) { if (commitMessage.isEmpty() || !sourceDirectory.isLocalFile() || !destinationRepository.isValid() || destinationRepository.type() != KDevelop::VcsLocation::RepositoryLocation) { return 0; } qCDebug(PLUGIN_CVS) << "CVS Import requested " << "src:" << sourceDirectory.toLocalFile() << "srv:" << destinationRepository.repositoryServer() << "module:" << destinationRepository.repositoryModule(); CvsJob* job = d->m_proxy->import(sourceDirectory, destinationRepository.repositoryServer(), destinationRepository.repositoryModule(), destinationRepository.userData().toString(), destinationRepository.repositoryTag(), commitMessage); return job; } KDevelop::VcsJob * CvsPlugin::createWorkingCopy(const KDevelop::VcsLocation & sourceRepository, const QUrl & destinationDirectory, KDevelop::IBasicVersionControl::RecursionMode recursion) { Q_UNUSED(recursion); if (!destinationDirectory.isLocalFile() || !sourceRepository.isValid() || sourceRepository.type() != KDevelop::VcsLocation::RepositoryLocation) { return 0; } qCDebug(PLUGIN_CVS) << "CVS Checkout requested " << "dest:" << destinationDirectory.toLocalFile() << "srv:" << sourceRepository.repositoryServer() << "module:" << sourceRepository.repositoryModule() << "branch:" << sourceRepository.repositoryBranch() << endl; CvsJob* job = d->m_proxy->checkout(destinationDirectory, sourceRepository.repositoryServer(), sourceRepository.repositoryModule(), "", sourceRepository.repositoryBranch(), true, true); return job; } QString CvsPlugin::name() const { return i18n("CVS"); } KDevelop::VcsImportMetadataWidget* CvsPlugin::createImportMetadataWidget(QWidget* parent) { return new ImportMetadataWidget(parent); } KDevelop::VcsLocationWidget* CvsPlugin::vcsLocation(QWidget* parent) const { return new KDevelop::StandardVcsLocationWidget(parent); } // End: KDevelop::IBasicVersionControl #include "cvsplugin.moc" diff --git a/plugins/cvs/cvsplugin.h b/plugins/cvs/cvsplugin.h index f403dc798f..fc97ac5287 100644 --- a/plugins/cvs/cvsplugin.h +++ b/plugins/cvs/cvsplugin.h @@ -1,139 +1,139 @@ /*************************************************************************** * Copyright 2007 Robert Gruber * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_CVSPLUGIN_H #define KDEVPLATFORM_PLUGIN_CVSPLUGIN_H #include #include #include #include #include #include class CvsProxy; namespace KDevelop { class ContextMenuExtension; } class CvsPluginPrivate; /** * This is the main class of KDevelop's CVS plugin. * * It implements the IVersionControl interface. * * @author Robert Gruber */ class CvsPlugin : public KDevelop::IPlugin, public KDevelop::ICentralizedVersionControl { Q_OBJECT Q_INTERFACES(KDevelop::IBasicVersionControl KDevelop::ICentralizedVersionControl) friend class CvsProxy; public: explicit CvsPlugin(QObject *parent, const QVariantList & args = QVariantList()); - virtual ~CvsPlugin(); + ~CvsPlugin() override; - virtual void unload() override; + void unload() override; - virtual QString name() const override; - virtual KDevelop::VcsImportMetadataWidget* createImportMetadataWidget(QWidget* parent) override; + QString name() const override; + KDevelop::VcsImportMetadataWidget* createImportMetadataWidget(QWidget* parent) override; // From KDevelop::IPlugin KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context*) override; // Begin: KDevelop::IBasicVersionControl - virtual bool isVersionControlled(const QUrl& localLocation) override; - virtual KDevelop::VcsJob* repositoryLocation(const QUrl& localLocation) override; - virtual KDevelop::VcsJob* add(const QList& localLocations, + bool isVersionControlled(const QUrl& localLocation) override; + KDevelop::VcsJob* repositoryLocation(const QUrl& localLocation) override; + KDevelop::VcsJob* add(const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion) override; - virtual KDevelop::VcsJob* remove(const QList& localLocations) override; - virtual KDevelop::VcsJob* copy(const QUrl& localLocationSrc, + KDevelop::VcsJob* remove(const QList& localLocations) override; + KDevelop::VcsJob* copy(const QUrl& localLocationSrc, const QUrl& localLocationDstn) override; - virtual KDevelop::VcsJob* move(const QUrl& localLocationSrc, + KDevelop::VcsJob* move(const QUrl& localLocationSrc, const QUrl& localLocationDst) override; - virtual KDevelop::VcsJob* status(const QList& localLocations, + KDevelop::VcsJob* status(const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion) override; - virtual KDevelop::VcsJob* revert(const QList& localLocations, + KDevelop::VcsJob* revert(const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion) override; - virtual KDevelop::VcsJob* update(const QList& localLocations, + KDevelop::VcsJob* update(const QList& localLocations, const KDevelop::VcsRevision& rev, KDevelop::IBasicVersionControl::RecursionMode recursion) override; - virtual KDevelop::VcsJob* commit(const QString& message, + KDevelop::VcsJob* commit(const QString& message, const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion) override; - virtual KDevelop::VcsJob* diff(const QUrl& fileOrDirectory, + KDevelop::VcsJob* diff(const QUrl& fileOrDirectory, const KDevelop::VcsRevision& srcRevision, const KDevelop::VcsRevision& dstRevision, KDevelop::VcsDiff::Type, KDevelop::IBasicVersionControl::RecursionMode = KDevelop::IBasicVersionControl::Recursive) override; - virtual KDevelop::VcsJob* log(const QUrl& localLocation, + KDevelop::VcsJob* log(const QUrl& localLocation, const KDevelop::VcsRevision& rev, unsigned long limit) override; - virtual KDevelop::VcsJob* log(const QUrl& localLocation, + KDevelop::VcsJob* log(const QUrl& localLocation, const KDevelop::VcsRevision& rev, const KDevelop::VcsRevision& limit) override; - virtual KDevelop::VcsJob* annotate(const QUrl& localLocation, + KDevelop::VcsJob* annotate(const QUrl& localLocation, const KDevelop::VcsRevision& rev) override; - virtual KDevelop::VcsJob* resolve(const QList& localLocations, + KDevelop::VcsJob* resolve(const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion) override; - virtual KDevelop::VcsJob* createWorkingCopy(const KDevelop::VcsLocation & sourceRepository, const QUrl & destinationDirectory, KDevelop::IBasicVersionControl::RecursionMode recursion = KDevelop::IBasicVersionControl::Recursive) override; + KDevelop::VcsJob* createWorkingCopy(const KDevelop::VcsLocation & sourceRepository, const QUrl & destinationDirectory, KDevelop::IBasicVersionControl::RecursionMode recursion = KDevelop::IBasicVersionControl::Recursive) override; // End: KDevelop::IBasicVersionControl // Begin: KDevelop::ICentralizedVersionControl - virtual KDevelop::VcsJob* edit(const QUrl& localLocation) override; - virtual KDevelop::VcsJob* unedit(const QUrl& localLocation) override; - virtual KDevelop::VcsJob* localRevision(const QUrl& localLocation, + KDevelop::VcsJob* edit(const QUrl& localLocation) override; + KDevelop::VcsJob* unedit(const QUrl& localLocation) override; + KDevelop::VcsJob* localRevision(const QUrl& localLocation, KDevelop::VcsRevision::RevisionType) override; - virtual KDevelop::VcsJob* import(const QString& commitMessage, const QUrl& sourceDirectory, const KDevelop::VcsLocation& destinationRepository) override; + KDevelop::VcsJob* import(const QString& commitMessage, const QUrl& sourceDirectory, const KDevelop::VcsLocation& destinationRepository) override; // End: KDevelop::ICentralizedVersionControl CvsProxy* proxy(); const QUrl urlFocusedDocument() const; - virtual KDevelop::VcsLocationWidget* vcsLocation(QWidget* parent) const override; + KDevelop::VcsLocationWidget* vcsLocation(QWidget* parent) const override; public slots: // slots for context menu void ctxEdit(); void ctxUnEdit(); void ctxEditors(); // slots for menu void slotImport(); void slotCheckout(); void slotStatus(); signals: /** * Some actions like commit, add, remove... will connect the job's * result() signal to this signal. Anybody, like for instance the * CvsMainView class, that is interested in getting notified about * jobs that finished can connect to this signal. * @see class CvsMainView */ void jobFinished(KJob* job); /** * Gets emmited when a job like log, editors... was created. * CvsPlugin will connect the newly created view to the result() signal * of a job. So the new view will show the output of that job as * soon as it has finished. */ void addNewTabToMainView(QWidget* tab, QString label); private: void setupActions(); QScopedPointer d; QString findWorkingDir(const QUrl& location); }; #endif diff --git a/plugins/cvs/cvsproxy.h b/plugins/cvs/cvsproxy.h index 7844b82c0b..7792938e65 100644 --- a/plugins/cvs/cvsproxy.h +++ b/plugins/cvs/cvsproxy.h @@ -1,108 +1,108 @@ /*************************************************************************** * Copyright 2007 Robert Gruber * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_CVSPROXY_H #define KDEVPLATFORM_PLUGIN_CVSPROXY_H #include #include #include class CvsJob; namespace KDevelop { class IPlugin; } /** * This proxy acts as a single point of entry for most of the common cvs commands. * It is very easy to use, as the caller does not have to deal which the CvsJob class directly. * All the command line generation and job handling is done internally. The caller gets a CvsJob * object returned from the proxy and can then call it's start() method. * * Here is and example of how to user the proxy: * @code * CvsJob* job = proxy->editors( repo, urls ); * if ( job ) { * connect(job, SIGNAL( result(KJob*) ), * this, SIGNAL( jobFinished(KJob*) )); * job->start(); * } * @endcode * * @note All actions that take a QList also need an url to the repository which * must be a common base directory to all files from the QList. * Actions that just take a single QUrl don't need a repository, the cvs command will be * called directly in the directory of the given file * * @author Robert Gruber */ class CvsProxy : public QObject { Q_OBJECT public: explicit CvsProxy(KDevelop::IPlugin* parent = 0); - ~CvsProxy(); + ~CvsProxy() override; bool isValidDirectory(QUrl dirPath) const; bool isVersionControlled(QUrl filePath) const; CvsJob* import(const QUrl &directory, const QString & server, const QString& repositoryName, const QString& vendortag, const QString& releasetag, const QString& message); CvsJob* log(const QUrl &file, const KDevelop::VcsRevision& rev); CvsJob* diff(const QUrl &url, const KDevelop::VcsRevision& revA, const KDevelop::VcsRevision& revB, const QString& diffOptions=""); CvsJob* annotate(const QUrl &url, const KDevelop::VcsRevision& rev); CvsJob* edit(const QString& repo, const QList& files); CvsJob* unedit(const QString& repo, const QList& files); CvsJob* editors(const QString& repo, const QList& files); CvsJob* commit(const QString& repo, const QList& files, const QString& message); CvsJob* add(const QString& repo, const QList& files, bool recursiv = true, bool binary = false); CvsJob* remove(const QString& repo, const QList& files); CvsJob* update(const QString& repo, const QList& files, const KDevelop::VcsRevision& rev, const QString& updateOptions, bool resursive = true, bool pruneDirs = true, bool createDirs = true); CvsJob* checkout(const QUrl &targetDir, const QString & server, const QString& module, const QString& checkoutOptions="", const QString& revision="", bool recursive = true, bool pruneDirs = true); CvsJob* status(const QString & repo, const QList & files, bool recursive=false, bool taginfo=false); private: bool addFileList(CvsJob* job, const QString& repository, const QList& urls); QString convertVcsRevisionToString(const KDevelop::VcsRevision& rev); QString convertRevisionToPrevious(const KDevelop::VcsRevision& rev); enum RequestedOperation { NormalOperation, Import, CheckOut }; bool prepareJob(CvsJob* job, const QString& repository, enum RequestedOperation op = CvsProxy::NormalOperation); KDevelop::IPlugin* vcsplugin; }; #endif diff --git a/plugins/cvs/cvsstatusjob.h b/plugins/cvs/cvsstatusjob.h index b8d648bf08..89d4b227ee 100644 --- a/plugins/cvs/cvsstatusjob.h +++ b/plugins/cvs/cvsstatusjob.h @@ -1,41 +1,41 @@ /*************************************************************************** * Copyright 2008 Robert Gruber * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_CVSSTATUSJOB_H #define KDEVPLATFORM_PLUGIN_CVSSTATUSJOB_H #include "cvsjob.h" #include /** * @author Robert Gruber */ class CvsStatusJob : public CvsJob { Q_OBJECT public: explicit CvsStatusJob(KDevelop::IPlugin* parent, KDevelop::OutputJob::OutputJobVerbosity verbosity = KDevelop::OutputJob::Verbose); - virtual ~CvsStatusJob(); + ~CvsStatusJob() override; // Begin: KDevelop::VcsJob - virtual QVariant fetchResults() override; + QVariant fetchResults() override; // End: KDevelop::VcsJob private: void parseOutput(const QString& jobOutput, QList& infos); void addInfoToList(QList& infos, const QString& currentDir, const QString& filename, const QString& statusString); KDevelop::VcsStatusInfo::State String2EnumState(const QString& stateAsString); }; #endif diff --git a/plugins/cvs/editorsview.h b/plugins/cvs/editorsview.h index 2b9a43d9b8..56be9c0e70 100644 --- a/plugins/cvs/editorsview.h +++ b/plugins/cvs/editorsview.h @@ -1,77 +1,77 @@ /*************************************************************************** * Copyright 2007 Robert Gruber * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_EDITORSVIEW_H #define KDEVPLATFORM_PLUGIN_EDITORSVIEW_H #include #include #include #include "ui_editorsview.h" class CvsPlugin; class CvsJob; /** * This is a helper class for the EditorsView::parseOutput() method. * It holds information about a single locker of a file. * @see EditorsView::parseOutput() */ class CvsLocker { public: QString user; QString date; QString machine; QString localrepo; }; /** * Shows the output from @code cvs editors @endcode in a nice way. * Create a CvsJob by calling CvsProxy::editors() and connect the job's * result(KJob*) signal to EditorsView::slotJobFinished(KJob* job) * @author Robert Gruber */ class EditorsView : public QWidget, private Ui::EditorsViewBase { Q_OBJECT public: explicit EditorsView(CvsJob* job=0, QWidget *parent = 0); - virtual ~EditorsView(); + ~EditorsView() override; /** * Parses the output generated by a @code cvs editors @endcode command and * fills the given QMultiMap with all files and their lockers found in the output. * @param jobOutput Pass in the plain output of a @code cvs editors @endcode job * @param editorsInfo This QMultiMap will be filled with information about which files * are locked by whom. The key of the map is the filename. For each * filename a list of CvsLocker objects will be created, depending * on how many people are editing the file. * If editorsInfo.size() is zero, this means that no information was * found in the given @p jobOutput. */ static void parseOutput(const QString& jobOutput, QMultiMap& editorsInfo); private slots: /** * Connect a job's result() signal to this slot. When called, the output from the job * will be passed to the parseOutput() method and any found locker information will be * displayed. * @note If you pass a CvsJob object to the ctor, it's result() signal * will automatically be connected to this slot. */ void slotJobFinished(KJob* job); private: QString m_output; }; #endif diff --git a/plugins/cvs/importdialog.h b/plugins/cvs/importdialog.h index bab17144cb..83e2d7d44f 100644 --- a/plugins/cvs/importdialog.h +++ b/plugins/cvs/importdialog.h @@ -1,44 +1,44 @@ /*************************************************************************** * Copyright 2007 Robert Gruber * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_IMPORTDIALOG_H #define KDEVPLATFORM_PLUGIN_IMPORTDIALOG_H #include #include #include class ImportMetadataWidget; class CvsPlugin; /** * Asks the user for all options needed to import an existing directory into * a CVS repository * @author Robert Gruber */ class ImportDialog : public QDialog { Q_OBJECT public: ImportDialog(CvsPlugin *plugin, const QUrl &url, QWidget* parent=0); - virtual ~ImportDialog(); + ~ImportDialog() override; public slots: - virtual void accept() override; + void accept() override; void jobFinished(KJob* job); private: QUrl m_url; CvsPlugin* m_plugin; ImportMetadataWidget* m_widget; }; #endif diff --git a/plugins/cvs/importmetadatawidget.h b/plugins/cvs/importmetadatawidget.h index 1ebf2ebeb6..259b882e40 100644 --- a/plugins/cvs/importmetadatawidget.h +++ b/plugins/cvs/importmetadatawidget.h @@ -1,49 +1,49 @@ /*************************************************************************** * Copyright 2007 Robert Gruber * * Copyright 2007 Andreas Pakulat * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_IMPORTMETADATAWIDGET_H #define KDEVPLATFORM_PLUGIN_IMPORTMETADATAWIDGET_H #include #include "ui_importmetadatawidget.h" class CvsPlugin; namespace KDevelop { class VcsLocation; } /** * Asks the user for all options needed to import an existing directory into * a CVS repository * @author Robert Gruber */ class ImportMetadataWidget : public KDevelop::VcsImportMetadataWidget, private Ui::ImportMetadataWidget { Q_OBJECT public: explicit ImportMetadataWidget(QWidget* parent=0); - virtual ~ImportMetadataWidget(); - - virtual QUrl source() const override; - virtual KDevelop::VcsLocation destination() const override; - virtual QString message() const override; - virtual void setSourceLocation( const KDevelop::VcsLocation& ) override; - virtual void setSourceLocationEditable( bool ) override; - virtual bool hasValidData() const override; + ~ImportMetadataWidget() override; + + QUrl source() const override; + KDevelop::VcsLocation destination() const override; + QString message() const override; + void setSourceLocation( const KDevelop::VcsLocation& ) override; + void setSourceLocationEditable( bool ) override; + bool hasValidData() const override; private: Ui::ImportMetadataWidget* m_ui; }; #endif diff --git a/plugins/documentswitcher/documentswitcherplugin.h b/plugins/documentswitcher/documentswitcherplugin.h index 888b6b94a1..7f7e8af36d 100644 --- a/plugins/documentswitcher/documentswitcherplugin.h +++ b/plugins/documentswitcher/documentswitcherplugin.h @@ -1,81 +1,81 @@ /*************************************************************************** * Copyright 2009 Andreas Pakulat * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_DOCUMENTSWITCHERPLUGIN_H #define KDEVPLATFORM_PLUGIN_DOCUMENTSWITCHERPLUGIN_H #include #include #include Q_DECLARE_LOGGING_CATEGORY(PLUGIN_DOCUMENTSWITCHER) class QStandardItemModel; namespace Sublime { class View; class MainWindow; class AreaIndex; class Area; class MainWindow; } class QListView; class QModelIndex; class QStringListModel; class QEvent; class QAction; class DocumentSwitcherPlugin: public KDevelop::IPlugin { Q_OBJECT public: explicit DocumentSwitcherPlugin( QObject *parent, const QVariantList &args = QVariantList() ); - ~DocumentSwitcherPlugin(); + ~DocumentSwitcherPlugin() override; - virtual void unload() override; + void unload() override; public slots: void itemActivated( const QModelIndex& ); void switchToClicked(const QModelIndex& ); private slots: void addView( Sublime::View* ); void changeView( Sublime::View* ); void addMainWindow( Sublime::MainWindow* ); void changeArea( Sublime::Area* ); void removeView( Sublime::View* ); void removeMainWindow(QObject*); void walkForward(); void walkBackward(); protected: bool eventFilter( QObject*, QEvent* ) override; private: void setViewGeometry(Sublime::MainWindow* window); void storeAreaViewList( Sublime::MainWindow* mainwindow, Sublime::Area* area ); void enableActions(); void fillModel( Sublime::MainWindow* window ); void walk(const int from, const int to); // Need to use QObject here as we only have a QObject* in // the removeMainWindow method and cannot cast it to the mainwindow anymore QMap > > documentLists; QListView* view; QStandardItemModel* model; QAction* forwardAction; QAction* backwardAction; }; #endif diff --git a/plugins/documentview/kdevdocumentmodel.h b/plugins/documentview/kdevdocumentmodel.h index dea72266ae..510001f6fd 100644 --- a/plugins/documentview/kdevdocumentmodel.h +++ b/plugins/documentview/kdevdocumentmodel.h @@ -1,106 +1,106 @@ /* This file is part of KDevelop Copyright 2005 Adam Treat Copyright 2013 Sebastian Kügler 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 KDEVPLATFORM_PLUGIN_KDEVDOCUMENTMODEL_H #define KDEVPLATFORM_PLUGIN_KDEVDOCUMENTMODEL_H #include #include #include #include #include class KDevDocumentItem; class KDevCategoryItem; class KDevFileItem; class KDevDocumentItem: public QStandardItem { public: explicit KDevDocumentItem( const QString &name ); - virtual ~KDevDocumentItem(); + ~KDevDocumentItem() override; virtual KDevCategoryItem *categoryItem() const { return 0; } virtual KDevFileItem *fileItem() const { return 0; } QIcon icon() const; KDevelop::IDocument::DocumentState documentState() const; void setDocumentState( KDevelop::IDocument::DocumentState state ); const QUrl url() const; void setUrl(const QUrl &url); protected: QString m_fileIcon; private: QUrl m_url; KDevelop::IDocument::DocumentState m_documentState; }; class KDevCategoryItem: public KDevDocumentItem { public: explicit KDevCategoryItem( const QString &name ); - virtual ~KDevCategoryItem(); + ~KDevCategoryItem() override; - virtual KDevCategoryItem *categoryItem() const override + KDevCategoryItem *categoryItem() const override { return const_cast( this ); } QList fileList() const; KDevFileItem* file( const QUrl &url ) const; }; class KDevFileItem: public KDevDocumentItem { public: explicit KDevFileItem( const QUrl &url ); - virtual ~KDevFileItem(); + ~KDevFileItem() override; - virtual KDevFileItem *fileItem() const override + KDevFileItem *fileItem() const override { return const_cast( this ); } }; class KDevDocumentModel: public QStandardItemModel { Q_OBJECT public: explicit KDevDocumentModel( QObject *parent = 0 ); - virtual ~KDevDocumentModel(); + ~KDevDocumentModel() override; QList categoryList() const; KDevCategoryItem* category( const QString& category ) const; }; #endif // KDEVPLATFORM_PLUGIN_KDEVDOCUMENTMODEL_H diff --git a/plugins/documentview/kdevdocumentselection.h b/plugins/documentview/kdevdocumentselection.h index ea0f957934..c734e776be 100644 --- a/plugins/documentview/kdevdocumentselection.h +++ b/plugins/documentview/kdevdocumentselection.h @@ -1,40 +1,40 @@ /* This file is part of KDevelop Copyright 2005 Adam Treat 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 KDEVPLATFORM_PLUGIN_KDEVDOCUMENTSELECTION_H #define KDEVPLATFORM_PLUGIN_KDEVDOCUMENTSELECTION_H #include class KDevDocumentSelection: public QItemSelectionModel { Q_OBJECT public: explicit KDevDocumentSelection( QAbstractItemModel* model ); - virtual ~KDevDocumentSelection(); + ~KDevDocumentSelection() override; public slots: - virtual void select( const QModelIndex & index, + void select( const QModelIndex & index, QItemSelectionModel::SelectionFlags command ) override; - virtual void select( const QItemSelection & selection, + void select( const QItemSelection & selection, QItemSelectionModel::SelectionFlags command ) override; }; #endif // KDEVPLATFORM_PLUGIN_KDEVDOCUMENTSELECTION_H diff --git a/plugins/documentview/kdevdocumentview.h b/plugins/documentview/kdevdocumentview.h index f852f6ac80..da1ad8659b 100644 --- a/plugins/documentview/kdevdocumentview.h +++ b/plugins/documentview/kdevdocumentview.h @@ -1,98 +1,98 @@ /* This file is part of KDevelop Copyright 2005 Adam Treat Copyright 2013 Sebastian Kügler 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 KDEVPLATFORM_PLUGIN_KDEVDOCUMENTVIEW_H #define KDEVPLATFORM_PLUGIN_KDEVDOCUMENTVIEW_H #include #include class QSortFilterProxyModel; class QAction; class KDevDocumentViewPlugin; class KDevDocumentModel; class KDevDocumentViewDelegate; class KDevDocumentSelection; class KDevFileItem; namespace KDevelop { class IDocument; class IProject; } class KDevCategoryItem; class KDevDocumentModel; class KDevDocumentItem; class KDevDocumentView: public QTreeView { Q_OBJECT public: explicit KDevDocumentView( KDevDocumentViewPlugin *plugin, QWidget *parent ); - virtual ~KDevDocumentView(); + ~KDevDocumentView() override; KDevDocumentViewPlugin *plugin() const; signals: void activateURL( const QUrl &url ); public slots: void opened( KDevelop::IDocument* document ); private slots: void activated( KDevelop::IDocument* document ); void saved( KDevelop::IDocument* document ); void closed( KDevelop::IDocument* document ); void contentChanged( KDevelop::IDocument* document ); void stateChanged( KDevelop::IDocument* document ); void documentUrlChanged( KDevelop::IDocument* document ); void updateCategoryItem( KDevCategoryItem *item ); void updateProjectPaths(); void saveSelected(); void reloadSelected(); void closeSelected(); void closeUnselected(); protected: - virtual void mousePressEvent( QMouseEvent * event ) override; - virtual void contextMenuEvent( QContextMenuEvent * event ) override; + void mousePressEvent( QMouseEvent * event ) override; + void contextMenuEvent( QContextMenuEvent * event ) override; private: template void visitItems(F, bool selectedItems); bool selectedDocHasChanges(); void updateSelectedDocs(); void appendActions(QMenu* menu, const QList< QAction* >& actions); private: KDevDocumentViewPlugin *m_plugin; KDevDocumentModel *m_documentModel; KDevDocumentSelection* m_selectionModel; QSortFilterProxyModel* m_proxy; KDevDocumentViewDelegate* m_delegate; QHash< KDevelop::IDocument*, KDevFileItem* > m_doc2index; QList m_selectedDocs; // used for ctx menu QList m_unselectedDocs; // used for ctx menu friend class KDevDocumentViewPluginFactory; // to connect to the private slots stateChanged and documentUrlChanged }; #endif // KDEVPLATFORM_PLUGIN_KDEVDOCUMENTVIEW_H diff --git a/plugins/documentview/kdevdocumentviewdelegate.h b/plugins/documentview/kdevdocumentviewdelegate.h index c95235a192..575f71a617 100644 --- a/plugins/documentview/kdevdocumentviewdelegate.h +++ b/plugins/documentview/kdevdocumentviewdelegate.h @@ -1,36 +1,36 @@ /* This file is part of KDevelop Copyright 2005 Adam Treat 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 KDEVPLATFORM_PLUGIN_KDEVDOCUMENTVIEWDELEGATE_H #define KDEVPLATFORM_PLUGIN_KDEVDOCUMENTVIEWDELEGATE_H #include class QTreeView; class KDevDocumentViewDelegate: public QItemDelegate { Q_OBJECT public: explicit KDevDocumentViewDelegate( QObject *parent = 0 ); - virtual ~KDevDocumentViewDelegate(); + ~KDevDocumentViewDelegate() override; - virtual void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const override; + void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const override; }; #endif // KDEVPLATFORM_PLUGIN_KDEVCLASSVIEWDELEGATE_H diff --git a/plugins/documentview/kdevdocumentviewplugin.cpp b/plugins/documentview/kdevdocumentviewplugin.cpp index 07e418c9b3..fc1cf1a985 100644 --- a/plugins/documentview/kdevdocumentviewplugin.cpp +++ b/plugins/documentview/kdevdocumentviewplugin.cpp @@ -1,108 +1,108 @@ /* * This file is part of KDevelop * * Copyright 2006 Adam Treat * * 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 "kdevdocumentviewplugin.h" #include "kdevdocumentview.h" #include "kdevdocumentmodel.h" #include "kdevdocumentselection.h" #include #include #include #include #include #include using namespace KDevelop; K_PLUGIN_FACTORY_WITH_JSON(KDevDocumentViewFactory, "kdevdocumentview.json", registerPlugin();) class KDevDocumentViewPluginFactory: public KDevelop::IToolViewFactory { public: KDevDocumentViewPluginFactory( KDevDocumentViewPlugin *plugin ): m_plugin( plugin ) {} - virtual QWidget* create( QWidget *parent = 0 ) override + QWidget* create( QWidget *parent = 0 ) override { KDevDocumentView* view = new KDevDocumentView( m_plugin, parent ); KDevelop::IDocumentController* docController = m_plugin->core()->documentController(); foreach(KDevelop::IDocument* doc, docController->openDocuments()) { view->opened( doc ); } QObject::connect( docController, &IDocumentController::documentActivated, view, &KDevDocumentView::activated ); QObject::connect( docController, &IDocumentController::documentSaved, view, &KDevDocumentView::saved ); QObject::connect( docController, &IDocumentController::documentOpened, view, &KDevDocumentView::opened ); QObject::connect( docController, &IDocumentController::documentClosed, view, &KDevDocumentView::closed ); QObject::connect( docController, &IDocumentController::documentContentChanged, view, &KDevDocumentView::contentChanged ); QObject::connect( docController, &IDocumentController::documentStateChanged, view, &KDevDocumentView::stateChanged ); QObject::connect( docController, &IDocumentController::documentUrlChanged, view, &KDevDocumentView::documentUrlChanged ); return view; } - virtual Qt::DockWidgetArea defaultPosition() override + Qt::DockWidgetArea defaultPosition() override { return Qt::LeftDockWidgetArea; } - virtual QString id() const override + QString id() const override { return "org.kdevelop.DocumentsView"; } private: KDevDocumentViewPlugin* m_plugin; }; KDevDocumentViewPlugin::KDevDocumentViewPlugin( QObject *parent, const QVariantList& args ) : KDevelop::IPlugin( "kdevdocumentview", parent ) { Q_UNUSED( args ); factory = new KDevDocumentViewPluginFactory( this ); core()->uiController()->addToolView( i18n("Documents"), factory ); setXMLFile( "kdevdocumentview.rc" ); } KDevDocumentViewPlugin::~KDevDocumentViewPlugin() { } void KDevDocumentViewPlugin::unload() { core()->uiController()->removeToolView( factory ); } #include "kdevdocumentviewplugin.moc" diff --git a/plugins/documentview/kdevdocumentviewplugin.h b/plugins/documentview/kdevdocumentviewplugin.h index d8f51e5784..f513367329 100644 --- a/plugins/documentview/kdevdocumentviewplugin.h +++ b/plugins/documentview/kdevdocumentviewplugin.h @@ -1,49 +1,49 @@ /* This file is part of KDevelop Copyright 2005 Adam Treat 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 KDEVPLATFORM_PLUGIN_KDEVDOCUMENTVIEW_PART_H #define KDEVPLATFORM_PLUGIN_KDEVDOCUMENTVIEW_PART_H #include #include class KDevDocumentViewPluginFactory; class KDevDocumentViewPlugin: public KDevelop::IPlugin { Q_OBJECT public: enum RefreshPolicy { Refresh, NoRefresh, ForceRefresh }; public: KDevDocumentViewPlugin( QObject *parent, const QVariantList& args ); - virtual ~KDevDocumentViewPlugin(); - virtual void unload() override; + ~KDevDocumentViewPlugin() override; + void unload() override; private: KDevDocumentViewPluginFactory* factory; }; #endif diff --git a/plugins/execute/executeplugin.h b/plugins/execute/executeplugin.h index 6ffef35788..b49fea578c 100644 --- a/plugins/execute/executeplugin.h +++ b/plugins/execute/executeplugin.h @@ -1,73 +1,73 @@ /* * This file is part of KDevelop * * Copyright 2007 Hamish Rodda * * 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. */ #ifndef KDEVPLATFORM_PLUGIN_EXECUTEPLUGIN_H #define KDEVPLATFORM_PLUGIN_EXECUTEPLUGIN_H #include #include #include #include "iexecuteplugin.h" class QUrl; class KJob; class NativeAppConfigType; class ExecutePlugin : public KDevelop::IPlugin, public IExecutePlugin { Q_OBJECT Q_INTERFACES( IExecutePlugin ) public: explicit ExecutePlugin(QObject *parent, const QVariantList & = QVariantList() ); - virtual ~ExecutePlugin(); + ~ExecutePlugin() override; static QString _nativeAppConfigTypeId; static QString workingDirEntry; static QString executableEntry; static QString argumentsEntry; static QString isExecutableEntry; static QString dependencyEntry; static QString environmentGroupEntry; static QString useTerminalEntry; static QString terminalEntry; static QString userIdToRunEntry; static QString dependencyActionEntry; static QString projectTargetEntry; - virtual void unload() override; + void unload() override; QUrl executable( KDevelop::ILaunchConfiguration*, QString& err ) const override; QStringList arguments( KDevelop::ILaunchConfiguration*, QString& err ) const override; QUrl workingDirectory( KDevelop::ILaunchConfiguration* ) const override; KJob* dependencyJob( KDevelop::ILaunchConfiguration* ) const override; QString environmentGroup( KDevelop::ILaunchConfiguration* ) const override; bool useTerminal( KDevelop::ILaunchConfiguration* ) const override; QString terminal( KDevelop::ILaunchConfiguration* ) const override; QString nativeAppConfigTypeId() const override; NativeAppConfigType* m_configType; }; #endif // KDEVPLATFORM_PLUGIN_EXECUTEPLUGIN_H // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/execute/nativeappconfig.h b/plugins/execute/nativeappconfig.h index 0477ffcc6a..0f1bdef1c4 100644 --- a/plugins/execute/nativeappconfig.h +++ b/plugins/execute/nativeappconfig.h @@ -1,94 +1,94 @@ /* This file is part of KDevelop Copyright 2009 Andreas Pakulat 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 KDEVPLATFORM_PLUGIN_NATIVEAPPCONFIGTYPE_H #define KDEVPLATFORM_PLUGIN_NATIVEAPPCONFIGTYPE_H #include #include #include #include #include "ui_nativeappconfig.h" //TODO: Split the page into two, one concerning executable/arguments/behaviour the other for dependencies class NativeAppConfigPage : public KDevelop::LaunchConfigurationPage, Ui::NativeAppPage { Q_OBJECT public: explicit NativeAppConfigPage( QWidget* parent ); void loadFromConfiguration( const KConfigGroup& cfg, KDevelop::IProject* project = 0 ) override; void saveToConfiguration( KConfigGroup cfg, KDevelop::IProject* project = 0 ) const override; QString title() const override; QIcon icon() const override; private slots: void activateDeps( int ); }; class NativeAppLauncher : public KDevelop::ILauncher { public: NativeAppLauncher(); - virtual QList< KDevelop::LaunchConfigurationPageFactory* > configPages() const override; - virtual QString description() const override; - virtual QString id() override; - virtual QString name() const override; - virtual KJob* start(const QString& launchMode, KDevelop::ILaunchConfiguration* cfg) override; - virtual QStringList supportedModes() const override; + QList< KDevelop::LaunchConfigurationPageFactory* > configPages() const override; + QString description() const override; + QString id() override; + QString name() const override; + KJob* start(const QString& launchMode, KDevelop::ILaunchConfiguration* cfg) override; + QStringList supportedModes() const override; }; class NativeAppPageFactory : public KDevelop::LaunchConfigurationPageFactory { public: NativeAppPageFactory(); - virtual KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override; + KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override; }; /** * A specific configuration to start a launchable, this could be a native * compiled application, or some script file or byte-compiled file or something else * Provides access to the various configured informations, as well as its type and a name */ class NativeAppConfigType : public KDevelop::LaunchConfigurationType { Q_OBJECT public: NativeAppConfigType(); - virtual ~NativeAppConfigType(); + ~NativeAppConfigType() override; QString id() const override; QString name() const override; QList configPages() const override; QIcon icon() const override; bool canLaunch( KDevelop::ProjectBaseItem* item ) const override; bool canLaunch( const QUrl& file ) const override; void configureLaunchFromItem ( KConfigGroup cfg, KDevelop::ProjectBaseItem* item ) const override; void configureLaunchFromCmdLineArguments ( KConfigGroup cfg, const QStringList& args ) const override; QMenu* launcherSuggestions() override; private: QList factoryList; public slots: void suggestionTriggered(); }; #endif diff --git a/plugins/execute/nativeappjob.h b/plugins/execute/nativeappjob.h index 077021ab98..cd88cc58ed 100644 --- a/plugins/execute/nativeappjob.h +++ b/plugins/execute/nativeappjob.h @@ -1,56 +1,56 @@ /* This file is part of KDevelop Copyright 2009 Andreas Pakulat 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 KDEVPLATFORM_PLUGIN_NATIVEAPPJOB_H #define KDEVPLATFORM_PLUGIN_NATIVEAPPJOB_H #include #include namespace KDevelop { class ILaunchConfiguration; class ProcessLineMaker; class OutputModel; } class KProcess; class NativeAppJob : public KDevelop::OutputJob { Q_OBJECT public: NativeAppJob( QObject* parent, KDevelop::ILaunchConfiguration* cfg ); - virtual void start() override; - virtual bool doKill() override; + void start() override; + bool doKill() override; KDevelop::OutputModel* model(); private slots: void processError(QProcess::ProcessError); void processFinished(int,QProcess::ExitStatus); void outputDone(); private: void appendLine(const QString &l); KProcess* proc; KDevelop::ProcessLineMaker* lineMaker; QString m_cfgname; }; #endif diff --git a/plugins/execute/projecttargetscombobox.cpp b/plugins/execute/projecttargetscombobox.cpp index 215d2b6b25..a4d962c100 100644 --- a/plugins/execute/projecttargetscombobox.cpp +++ b/plugins/execute/projecttargetscombobox.cpp @@ -1,88 +1,88 @@ /* This file is part of KDevelop Copyright 2010 Aleix Pol Gonzalez 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 "projecttargetscombobox.h" #include #include #include #include #include #include using namespace KDevelop; ProjectTargetsComboBox::ProjectTargetsComboBox(QWidget* parent) : QComboBox(parent) { } class ExecutablePathsVisitor : public ProjectVisitor { public: ExecutablePathsVisitor(bool exec) : m_onlyExecutables(exec) {} using ProjectVisitor::visit; - virtual void visit(ProjectExecutableTargetItem* eit) override { + void visit(ProjectExecutableTargetItem* eit) override { if(!m_onlyExecutables || eit->type()==ProjectTargetItem::ExecutableTarget) m_paths += KDevelop::joinWithEscaping(eit->model()->pathFromIndex(eit->index()), '/', '\\'); } QStringList paths() const { return m_paths; } private: bool m_onlyExecutables; QStringList m_paths; }; void ProjectTargetsComboBox::setBaseItem(ProjectFolderItem* item, bool exec) { clear(); QList items; if(item) { items += item; } else { foreach(IProject* p, ICore::self()->projectController()->projects()) { items += p->projectItem(); } } ExecutablePathsVisitor walker(exec); foreach(ProjectFolderItem* item, items) { walker.visit(item); } foreach(const QString& item, walker.paths()) addItem(QIcon::fromTheme("system-run"), item); } QStringList ProjectTargetsComboBox::currentItemPath() const { return KDevelop::splitWithEscaping(currentText(), '/', '\\'); } void ProjectTargetsComboBox::setCurrentItemPath(const QStringList& str) { setCurrentIndex(str.isEmpty() && count() ? 0 : findText(KDevelop::joinWithEscaping(str, '/', '\\'))); } diff --git a/plugins/executescript/executescriptplugin.h b/plugins/executescript/executescriptplugin.h index 8baf58c046..0b80123d24 100644 --- a/plugins/executescript/executescriptplugin.h +++ b/plugins/executescript/executescriptplugin.h @@ -1,77 +1,77 @@ /* * This file is part of KDevelop * * Copyright 2007 Hamish Rodda * Copyright 2009 Niko Sams * * 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. */ #ifndef KDEVPLATFORM_PLUGIN_EXECUTESCRIPTPLUGIN_H #define KDEVPLATFORM_PLUGIN_EXECUTESCRIPTPLUGIN_H #include #include #include #include "iexecutescriptplugin.h" class ScriptAppConfigType; class QUrl; class KJob; class ExecuteScriptPlugin : public KDevelop::IPlugin, public IExecuteScriptPlugin { Q_OBJECT Q_INTERFACES( IExecuteScriptPlugin ) public: explicit ExecuteScriptPlugin(QObject *parent, const QVariantList & = QVariantList() ); - virtual ~ExecuteScriptPlugin(); + ~ExecuteScriptPlugin() override; static QString _scriptAppConfigTypeId; static QString interpreterEntry; static QString workingDirEntry; static QString executableEntry; static QString executeOnRemoteHostEntry; static QString remoteHostEntry; static QString runCurrentFileEntry; static QString argumentsEntry; static QString isExecutableEntry; static QString environmentGroupEntry; //static QString useTerminalEntry; static QString userIdToRunEntry; static QString projectTargetEntry; static QString outputFilteringEntry; - virtual void unload() override; + void unload() override; QString interpreter( KDevelop::ILaunchConfiguration*, QString& err ) const override; QUrl script( KDevelop::ILaunchConfiguration*, QString& err ) const override; QString remoteHost(KDevelop::ILaunchConfiguration* , QString& err) const override; QStringList arguments( KDevelop::ILaunchConfiguration*, QString& err ) const override; QUrl workingDirectory( KDevelop::ILaunchConfiguration* ) const override; QString environmentGroup( KDevelop::ILaunchConfiguration* ) const override; //bool useTerminal( KDevelop::ILaunchConfiguration* ) const; QString scriptAppConfigTypeId() const override; int outputFilterModeId( KDevelop::ILaunchConfiguration* ) const override; bool runCurrentFile(KDevelop::ILaunchConfiguration*) const override; ScriptAppConfigType* m_configType; }; #endif // KDEVPLATFORM_PLUGIN_EXECUTESCRIPTPLUGIN_H // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/executescript/scriptappconfig.h b/plugins/executescript/scriptappconfig.h index 05bcaba788..9a044fa6dd 100644 --- a/plugins/executescript/scriptappconfig.h +++ b/plugins/executescript/scriptappconfig.h @@ -1,89 +1,89 @@ /* 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 KDEVPLATFORM_PLUGIN_SCRIPTAPPCONFIGTYPE_H #define KDEVPLATFORM_PLUGIN_SCRIPTAPPCONFIGTYPE_H #include #include #include #include #include "ui_scriptappconfig.h" class ExecuteScriptPlugin; class ScriptAppConfigPage : public KDevelop::LaunchConfigurationPage, Ui::ScriptAppPage { Q_OBJECT public: explicit ScriptAppConfigPage( QWidget* parent ); void loadFromConfiguration( const KConfigGroup& cfg, KDevelop::IProject* project = 0 ) override; void saveToConfiguration( KConfigGroup cfg, KDevelop::IProject* project = 0 ) const override; QString title() const override; QIcon icon() const override; }; class ScriptAppLauncher : public KDevelop::ILauncher { public: explicit ScriptAppLauncher( ExecuteScriptPlugin* ); - virtual QList< KDevelop::LaunchConfigurationPageFactory* > configPages() const override; - virtual QString description() const override; - virtual QString id() override; - virtual QString name() const override; - virtual KJob* start(const QString& launchMode, KDevelop::ILaunchConfiguration* cfg) override; - virtual QStringList supportedModes() const override; + QList< KDevelop::LaunchConfigurationPageFactory* > configPages() const override; + QString description() const override; + QString id() override; + QString name() const override; + KJob* start(const QString& launchMode, KDevelop::ILaunchConfiguration* cfg) override; + QStringList supportedModes() const override; private: ExecuteScriptPlugin* m_plugin; }; class ScriptAppPageFactory : public KDevelop::LaunchConfigurationPageFactory { public: ScriptAppPageFactory(); - virtual KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override; + KDevelop::LaunchConfigurationPage* createWidget(QWidget* parent) override; }; /** * A specific configuration to start a launchable, this could be a native * compiled application, or some script file or byte-compiled file or something else * Provides access to the various configured informations, as well as its type and a name */ class ScriptAppConfigType : public KDevelop::LaunchConfigurationType { public: ScriptAppConfigType(); - virtual ~ScriptAppConfigType(); + ~ScriptAppConfigType() override; QString id() const override; QString name() const override; QList configPages() const override; QIcon icon() const override; - virtual bool canLaunch( const QUrl& file ) const override; - virtual bool canLaunch(KDevelop::ProjectBaseItem* item) const override; - virtual void configureLaunchFromItem(KConfigGroup config, KDevelop::ProjectBaseItem* item) const override; - virtual void configureLaunchFromCmdLineArguments(KConfigGroup config, const QStringList& args) const override; + bool canLaunch( const QUrl& file ) const override; + bool canLaunch(KDevelop::ProjectBaseItem* item) const override; + void configureLaunchFromItem(KConfigGroup config, KDevelop::ProjectBaseItem* item) const override; + void configureLaunchFromCmdLineArguments(KConfigGroup config, const QStringList& args) const override; private: QList factoryList; }; #endif diff --git a/plugins/executescript/scriptappjob.h b/plugins/executescript/scriptappjob.h index 0ffac17940..c82b3595a9 100644 --- a/plugins/executescript/scriptappjob.h +++ b/plugins/executescript/scriptappjob.h @@ -1,55 +1,55 @@ /* 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 KDEVPLATFORM_PLUGIN_SCRIPTAPPJOB_H #define KDEVPLATFORM_PLUGIN_SCRIPTAPPJOB_H #include #include class ExecuteScriptPlugin; namespace KDevelop { class ILaunchConfiguration; class ProcessLineMaker; class OutputModel; } class KProcess; class ScriptAppJob : public KDevelop::OutputJob { Q_OBJECT public: ScriptAppJob( ExecuteScriptPlugin* parent, KDevelop::ILaunchConfiguration* cfg ); - virtual void start() override; - virtual bool doKill() override; + void start() override; + bool doKill() override; KDevelop::OutputModel* model(); private slots: void processError(QProcess::ProcessError); void processFinished(int,QProcess::ExitStatus); private: void appendLine(const QString &l); KProcess* proc; KDevelop::ProcessLineMaker* lineMaker; }; #endif diff --git a/plugins/externalscript/editexternalscript.h b/plugins/externalscript/editexternalscript.h index f240c017e8..12329f244a 100644 --- a/plugins/externalscript/editexternalscript.h +++ b/plugins/externalscript/editexternalscript.h @@ -1,49 +1,49 @@ /* This plugin is part of KDevelop. Copyright (C) 2010 Milian Wolff 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) 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 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KDEVPLATFORM_PLUGIN_EDITEXTERNALSCRIPT_H #define KDEVPLATFORM_PLUGIN_EDITEXTERNALSCRIPT_H #include #include "ui_editexternalscript.h" class ExternalScriptItem; class EditExternalScript : public QDialog, private Ui::EditExternalScriptBase { Q_OBJECT public: explicit EditExternalScript( ExternalScriptItem* item, QWidget* parent = 0, Qt::WindowFlags flags = 0 ); - virtual ~EditExternalScript(); + ~EditExternalScript() override; private slots: void save(); void validate(); private: ExternalScriptItem* m_item; }; #endif // KDEVPLATFORM_PLUGIN_EDITEXTERNALSCRIPT_H // kate: indent-mode cstyle; space-indent on; indent-width 2; replace-tabs on; diff --git a/plugins/externalscript/externalscriptjob.h b/plugins/externalscript/externalscriptjob.h index 4604c79c13..adec6ec49b 100644 --- a/plugins/externalscript/externalscriptjob.h +++ b/plugins/externalscript/externalscriptjob.h @@ -1,87 +1,87 @@ /* This file is part of KDevelop Copyright 2009 Andreas Pakulat Copyright 2010 Milian Wolff 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 KDEVPLATFORM_PLUGIN_EXTERNALSCRIPTJOB_H #define KDEVPLATFORM_PLUGIN_EXTERNALSCRIPTJOB_H #include #include #include "externalscriptitem.h" #include #include namespace KDevelop { class ProcessLineMaker; class OutputModel; class Document; } namespace KTextEditor { class Document; } class KProcess; class ExternalScriptPlugin; class ExternalScriptJob : public KDevelop::OutputJob { Q_OBJECT public: ExternalScriptJob( ExternalScriptItem* item, const QUrl &url, ExternalScriptPlugin* parent ); - virtual void start() override; + void start() override; KDevelop::OutputModel* model(); protected: - virtual bool doKill() override; + bool doKill() override; private slots: void processError( QProcess::ProcessError ); void processFinished( int, QProcess::ExitStatus ); void receivedStdoutLines(const QStringList& lines); void receivedStderrLines(const QStringList& lines); private: void appendLine( const QString &l ); KProcess* m_proc; KDevelop::ProcessLineMaker* m_lineMaker; ExternalScriptItem::OutputMode m_outputMode; ExternalScriptItem::InputMode m_inputMode; ExternalScriptItem::ErrorMode m_errorMode; int m_filterMode; KTextEditor::Document* m_document; QUrl m_url; /// invalid when whole doc should be replaced KTextEditor::Range m_selectionRange; KTextEditor::Cursor m_cursorPosition; bool m_showOutput; QStringList m_stdout; QStringList m_stderr; }; #endif // KDEVPLATFORM_PLUGIN_EXTERNALSCRIPTJOB_H // kate: indent-mode cstyle; space-indent on; indent-width 2; replace-tabs on; diff --git a/plugins/externalscript/externalscriptplugin.cpp b/plugins/externalscript/externalscriptplugin.cpp index e48bd31c07..6838522f7c 100644 --- a/plugins/externalscript/externalscriptplugin.cpp +++ b/plugins/externalscript/externalscriptplugin.cpp @@ -1,368 +1,368 @@ /* This plugin is part of KDevelop. Copyright (C) 2010 Milian Wolff 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) 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 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "externalscriptplugin.h" #include "externalscriptview.h" #include "externalscriptitem.h" #include "externalscriptjob.h" #include "externalscriptdebug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include K_PLUGIN_FACTORY_WITH_JSON(ExternalScriptFactory, "kdevexternalscript.json", registerPlugin();) class ExternalScriptViewFactory: public KDevelop::IToolViewFactory { public: ExternalScriptViewFactory( ExternalScriptPlugin *plugin ): m_plugin( plugin ) {} - virtual QWidget* create( QWidget *parent = 0 ) override { + QWidget* create( QWidget *parent = 0 ) override { return new ExternalScriptView( m_plugin, parent ); } - virtual Qt::DockWidgetArea defaultPosition() override { + Qt::DockWidgetArea defaultPosition() override { return Qt::RightDockWidgetArea; } - virtual QString id() const override { + QString id() const override { return "org.kdevelop.ExternalScriptView"; } private: ExternalScriptPlugin *m_plugin; }; ExternalScriptPlugin* ExternalScriptPlugin::m_self = 0; ExternalScriptPlugin::ExternalScriptPlugin( QObject* parent, const QVariantList& /*args*/ ) : IPlugin( "kdevexternalscript", parent ), m_model( new QStandardItemModel( this ) ), m_factory( new ExternalScriptViewFactory( this ) ) { Q_ASSERT( !m_self ); m_self = this; QDBusConnection::sessionBus().registerObject( "/org/kdevelop/ExternalScriptPlugin", this, QDBusConnection::ExportScriptableSlots ); setXMLFile( "kdevexternalscript.rc" ); //BEGIN load config KConfigGroup config = getConfig(); foreach( const QString& group, config.groupList() ) { KConfigGroup script = config.group( group ); if ( script.hasKey( "name" ) && script.hasKey( "command" ) ) { ExternalScriptItem* item = new ExternalScriptItem; item->setText( script.readEntry( "name" ) ); item->setCommand( script.readEntry( "command" )); item->setInputMode( static_cast( script.readEntry( "inputMode", 0u ) ) ); item->setOutputMode( static_cast( script.readEntry( "outputMode", 0u ) ) ); item->setErrorMode( static_cast( script.readEntry( "errorMode", 0u ) ) ); item->setSaveMode( static_cast( script.readEntry( "saveMode", 0u ) ) ); item->setFilterMode( script.readEntry( "filterMode", 0u )); item->action()->setShortcut( QKeySequence( script.readEntry( "shortcuts" ) ) ); item->setShowOutput( script.readEntry( "showOutput", true ) ); m_model->appendRow( item ); } } //END load config core()->uiController()->addToolView( i18n( "External Scripts" ), m_factory ); connect( m_model, &QStandardItemModel::rowsRemoved, this, &ExternalScriptPlugin::rowsRemoved ); connect( m_model, &QStandardItemModel::rowsInserted, this, &ExternalScriptPlugin::rowsInserted ); const bool firstUse = config.readEntry( "firstUse", true ); if ( firstUse ) { // some example scripts ExternalScriptItem* item = new ExternalScriptItem; item->setText( i18n("Quick Compile") ); item->setCommand( "g++ -o %b %f && ./%b" ); m_model->appendRow( item ); item = new ExternalScriptItem; item->setText( i18n("Google Selection") ); item->setCommand( "xdg-open \"http://www.google.de/search?q=%s\"" ); item->setShowOutput( false ); m_model->appendRow( item ); item = new ExternalScriptItem; item->setText( i18n("Sort Selection") ); item->setCommand( "sort" ); item->setInputMode( ExternalScriptItem::InputSelectionOrDocument ); item->setOutputMode( ExternalScriptItem::OutputReplaceSelectionOrDocument ); item->setShowOutput( false ); m_model->appendRow( item ); config.writeEntry( "firstUse", false ); config.sync(); } } ExternalScriptPlugin* ExternalScriptPlugin::self() { return m_self; } ExternalScriptPlugin::~ExternalScriptPlugin() { m_self = 0; } KDevelop::ContextMenuExtension ExternalScriptPlugin::contextMenuExtension( KDevelop::Context* context ) { m_urls.clear(); int folderCount = 0; if ( context->type() == KDevelop::Context::FileContext ) { KDevelop::FileContext* filectx = dynamic_cast( context ); m_urls = filectx->urls(); } else if ( context->type() == KDevelop::Context::ProjectItemContext ) { KDevelop::ProjectItemContext* projctx = dynamic_cast( context ); foreach( KDevelop::ProjectBaseItem* item, projctx->items() ) { if ( item->file() ) { m_urls << item->file()->path().toUrl(); } else if ( item->folder() ) { m_urls << item->folder()->path().toUrl(); folderCount++; } } } else if ( context->type() == KDevelop::Context::EditorContext ) { KDevelop::EditorContext *econtext = dynamic_cast(context); m_urls << econtext->url(); } if ( !m_urls.isEmpty() ) { KDevelop::ContextMenuExtension ext; QMenu* menu = new QMenu(); menu->setTitle( i18n("External Scripts") ); for ( int row = 0; row < m_model->rowCount(); ++row ) { ExternalScriptItem* item = dynamic_cast( m_model->item( row ) ); Q_ASSERT( item ); if (context->type() != KDevelop::Context::EditorContext) { // filter scripts that depend on an opened document // if the context menu was not requested inside the editor if (item->performParameterReplacement() && item->command().contains("%s")) { continue; } else if (item->inputMode() == ExternalScriptItem::InputSelectionOrNone) { continue; } } if ( folderCount == m_urls.count() ) { // when only folders filter items that don't have %d parameter (or another parameter) if (item->performParameterReplacement() && (!item->command().contains("%d") || item->command().contains("%s") || item->command().contains("%u") || item->command().contains("%f") || item->command().contains("%b") || item->command().contains("%n") ) ) { continue; } } QAction* scriptAction = new QAction( item->text(), this ); scriptAction->setData( QVariant::fromValue( item )); connect( scriptAction, &QAction::triggered, this, &ExternalScriptPlugin::executeScriptFromContextMenu ); menu->addAction( scriptAction ); } ext.addAction( KDevelop::ContextMenuExtension::ExtensionGroup, menu->menuAction() ); return ext; } return KDevelop::IPlugin::contextMenuExtension( context ); } void ExternalScriptPlugin::unload() { core()->uiController()->removeToolView( m_factory ); KDevelop::IPlugin::unload(); } KConfigGroup ExternalScriptPlugin::getConfig() const { return KSharedConfig::openConfig()->group("External Scripts"); } QStandardItemModel* ExternalScriptPlugin::model() const { return m_model; } void ExternalScriptPlugin::execute( ExternalScriptItem* item, const QUrl& url ) const { ExternalScriptJob* job = new ExternalScriptJob( item, url, const_cast(this) ); KDevelop::ICore::self()->runController()->registerJob( job ); } void ExternalScriptPlugin::execute(ExternalScriptItem* item) const { auto document = KDevelop::ICore::self()->documentController()->activeDocument(); execute( item, document ? document->url() : QUrl() ); } bool ExternalScriptPlugin::executeCommand ( QString command, QString workingDirectory ) const { // We extend ExternalScriptJob so that it deletes the temporarily created item on destruction class ExternalScriptJobOwningItem : public ExternalScriptJob { public: ExternalScriptJobOwningItem( ExternalScriptItem* item, const QUrl &url, ExternalScriptPlugin* parent ) : ExternalScriptJob(item, url, parent), m_item(item) { } - ~ExternalScriptJobOwningItem() { + ~ExternalScriptJobOwningItem() override { delete m_item; } private: ExternalScriptItem* m_item; }; ExternalScriptItem* item = new ExternalScriptItem; item->setCommand(command); item->setWorkingDirectory(workingDirectory); item->setPerformParameterReplacement(false); qCDebug(PLUGIN_EXTERNALSCRIPT) << "executing command " << command << " in dir " << workingDirectory << " as external script"; ExternalScriptJobOwningItem* job = new ExternalScriptJobOwningItem( item, QUrl(), const_cast(this) ); // When a command is executed, for example through the terminal, we don't want the command output to be risen job->setVerbosity(KDevelop::OutputJob::Silent); KDevelop::ICore::self()->runController()->registerJob( job ); return true; } QString ExternalScriptPlugin::executeCommandSync ( QString command, QString workingDirectory ) const { qCDebug(PLUGIN_EXTERNALSCRIPT) << "executing command " << command << " in working-dir " << workingDirectory; KProcess process; process.setWorkingDirectory( workingDirectory ); process.setShellCommand( command ); process.setOutputChannelMode( KProcess::OnlyStdoutChannel ); process.execute(); return QString::fromLocal8Bit(process.readAll()); } void ExternalScriptPlugin::executeScriptFromActionData() const { QAction* action = dynamic_cast( sender() ); Q_ASSERT( action ); ExternalScriptItem* item = action->data().value(); Q_ASSERT( item ); execute( item ); } void ExternalScriptPlugin::executeScriptFromContextMenu() const { QAction* action = dynamic_cast( sender() ); Q_ASSERT( action ); ExternalScriptItem* item = action->data().value(); Q_ASSERT( item ); foreach( const QUrl& url, m_urls) { KDevelop::ICore::self()->documentController()->openDocument( url ); execute( item, url ); } } void ExternalScriptPlugin::rowsInserted( const QModelIndex& /*parent*/, int start, int end ) { for ( int i = start; i <= end; ++i ) { saveItemForRow( i ); } } void ExternalScriptPlugin::rowsRemoved( const QModelIndex& /*parent*/, int start, int end ) { KConfigGroup config = getConfig(); for ( int i = start; i <= end; ++i ) { KConfigGroup child = config.group( QStringLiteral("script %1").arg(i) ); qCDebug(PLUGIN_EXTERNALSCRIPT) << "removing config group:" << child.name(); child.deleteGroup(); } config.sync(); } void ExternalScriptPlugin::saveItem( const ExternalScriptItem* item ) { const QModelIndex index = m_model->indexFromItem( item ); Q_ASSERT( index.isValid() ); saveItemForRow( index.row() ); } void ExternalScriptPlugin::saveItemForRow( int row ) { const QModelIndex idx = m_model->index( row, 0 ); Q_ASSERT( idx.isValid() ); ExternalScriptItem* item = dynamic_cast( m_model->item( row ) ); Q_ASSERT( item ); qCDebug(PLUGIN_EXTERNALSCRIPT) << "save extern script:" << item << idx; KConfigGroup config = getConfig().group( QStringLiteral("script %1").arg( row ) ); config.writeEntry( "name", item->text() ); config.writeEntry( "command", item->command() ); config.writeEntry( "inputMode", (uint) item->inputMode() ); config.writeEntry( "outputMode", (uint) item->outputMode() ); config.writeEntry( "errorMode", (uint) item->errorMode() ); config.writeEntry( "saveMode", (uint) item->saveMode() ); config.writeEntry( "shortcuts", item->action()->shortcut().toString() ); config.writeEntry( "showOutput", item->showOutput() ); config.writeEntry( "filterMode", item->filterMode()); config.sync(); } #include "externalscriptplugin.moc" // kate: indent-mode cstyle; space-indent on; indent-width 2; replace-tabs on; diff --git a/plugins/externalscript/externalscriptplugin.h b/plugins/externalscript/externalscriptplugin.h index a4f04c433f..645a9c8b64 100644 --- a/plugins/externalscript/externalscriptplugin.h +++ b/plugins/externalscript/externalscriptplugin.h @@ -1,104 +1,104 @@ /* This plugin is part of KDevelop. Copyright (C) 2010 Milian Wolff 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) 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 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KDEVPLATFORM_PLUGIN_EXTERNALSCRIPTPLUGIN_H #define KDEVPLATFORM_PLUGIN_EXTERNALSCRIPTPLUGIN_H #include #include #include #include #include class ExternalScriptItem; class QStandardItem; class QStandardItemModel; class ExternalScriptPlugin : public KDevelop::IPlugin { Q_OBJECT Q_CLASSINFO( "D-Bus Interface", "org.kdevelop.ExternalScriptPlugin" ) public: explicit ExternalScriptPlugin( QObject *parent, const QVariantList &args = QVariantList() ); - virtual ~ExternalScriptPlugin(); - virtual void unload() override; - virtual KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; + ~ExternalScriptPlugin() override; + void unload() override; + KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; static ExternalScriptPlugin* self(); /** * @return The model storing all external scripts managed by this plugin. * @NOTE: always append() items, never insert in the middle! */ QStandardItemModel* model() const; /** * Executes @p script. */ void execute(ExternalScriptItem* item, const QUrl &url) const; /** * Executes @p script. */ void execute(ExternalScriptItem* item) const; /** * Returns config group to store all settings for this plugin in. */ KConfigGroup getConfig() const; void saveItem(const ExternalScriptItem* item); public slots: void executeScriptFromActionData() const; /** * Executes the command (Used by the shell-integration) * */ Q_SCRIPTABLE bool executeCommand(QString command, QString workingDirectory) const; /** * Executes the command synchronously and returns the output text (Used by the shell-integration) * */ Q_SCRIPTABLE QString executeCommandSync(QString command, QString workingDirectory) const; private slots: void rowsRemoved( const QModelIndex& parent, int start, int end ); void rowsInserted( const QModelIndex& parent, int start, int end ); void executeScriptFromContextMenu() const; private: /// @param item row in the model for the item to save void saveItemForRow( int row ); QStandardItemModel* m_model; QList m_urls; static ExternalScriptPlugin* m_self; class ExternalScriptViewFactory *m_factory; }; #endif // KDEVPLATFORM_PLUGIN_EXTERNALSCRIPTPLUGIN_H // kate: indent-mode cstyle; space-indent on; indent-width 2; replace-tabs on; diff --git a/plugins/externalscript/externalscriptview.h b/plugins/externalscript/externalscriptview.h index 56f45b50c1..6795ab4122 100644 --- a/plugins/externalscript/externalscriptview.h +++ b/plugins/externalscript/externalscriptview.h @@ -1,72 +1,72 @@ /* This plugin is part of KDevelop. Copyright (C) 2010 Milian Wolff 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) 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 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KDEVPLATFORM_PLUGIN_EXTERNALSCRIPTVIEW_H #define KDEVPLATFORM_PLUGIN_EXTERNALSCRIPTVIEW_H #include #include "ui_externalscriptview.h" class ExternalScriptItem; class QAction; class QSortFilterProxyModel; class ExternalScriptPlugin; class ExternalScriptView : public QWidget, Ui::ExternalScriptViewBase { Q_OBJECT public: explicit ExternalScriptView( ExternalScriptPlugin* plugin, QWidget* parent = 0 ); - virtual ~ExternalScriptView(); + ~ExternalScriptView() override; /// @return Currently selected script item. ExternalScriptItem* currentItem() const; /// @return Item for @p index. ExternalScriptItem* itemForIndex(const QModelIndex& index) const; private slots: void contextMenu ( const QPoint& pos ); void addScript(); void removeScript(); void editScript(); /// disables or enables available actions based on the currently selected item void validateActions(); protected: /// insert snippet on double click - virtual bool eventFilter( QObject* obj, QEvent* event ) override; + bool eventFilter( QObject* obj, QEvent* event ) override; private: ExternalScriptPlugin* m_plugin; QSortFilterProxyModel* m_model; QAction* m_addScriptAction; QAction* m_editScriptAction; QAction* m_removeScriptAction; }; #endif // KDEVPLATFORM_PLUGIN_EXTERNALSCRIPTVIEW_H // kate: indent-mode cstyle; space-indent on; indent-width 2; replace-tabs on; diff --git a/plugins/filemanager/bookmarkhandler.h b/plugins/filemanager/bookmarkhandler.h index d31e2d7abb..e9f552fa9b 100644 --- a/plugins/filemanager/bookmarkhandler.h +++ b/plugins/filemanager/bookmarkhandler.h @@ -1,61 +1,61 @@ /* This file is part of the KDE project Copyright (C) xxxx KFile Authors Copyright (C) 2002 Anders Lund Copyright (C) 2007 Mirko Stocker Copyright (C) 2009 Dominik Haumann Copyright (C) 2012 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 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. */ #ifndef KDEVPLATFORM_PLUGIN_BOOKMARKHANDLER_H #define KDEVPLATFORM_PLUGIN_BOOKMARKHANDLER_H #include #include #include class FileManager; class BookmarkHandler : public QObject, public KBookmarkOwner { Q_OBJECT public: explicit BookmarkHandler( FileManager *parent, QMenu *kpopupmenu = 0 ); - ~BookmarkHandler(); + ~BookmarkHandler() override; // KBookmarkOwner interface: - virtual QUrl currentUrl() const override; - virtual QString currentTitle() const override; + QUrl currentUrl() const override; + QString currentTitle() const override; QMenu *menu() const { return m_menu; } - virtual void openBookmark( const KBookmark &, Qt::MouseButtons, Qt::KeyboardModifiers ) override; + void openBookmark( const KBookmark &, Qt::MouseButtons, Qt::KeyboardModifiers ) override; Q_SIGNALS: void openUrl( const QUrl& url ); private: FileManager *m_parent; QMenu *m_menu; KBookmarkMenu *m_bookmarkMenu; }; #endif // KDEVPLATFORM_PLUGIN_BOOKMARKHANDLER_H diff --git a/plugins/filemanager/kdevfilemanagerplugin.cpp b/plugins/filemanager/kdevfilemanagerplugin.cpp index 207e342ffa..84507a60f8 100644 --- a/plugins/filemanager/kdevfilemanagerplugin.cpp +++ b/plugins/filemanager/kdevfilemanagerplugin.cpp @@ -1,94 +1,94 @@ /*************************************************************************** * Copyright 2006 Alexander Dymo * * Copyright 2007 Andreas Pakulat * * * * 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 Library 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 "kdevfilemanagerplugin.h" #include #include #include #include #include #include "filemanager.h" K_PLUGIN_FACTORY_WITH_JSON(KDevFileManagerFactory, "kdevfilemanager.json", registerPlugin();) class KDevFileManagerViewFactory: public KDevelop::IToolViewFactory{ public: KDevFileManagerViewFactory(KDevFileManagerPlugin *plugin): m_plugin(plugin) {} - virtual QWidget* create(QWidget *parent = 0) override + QWidget* create(QWidget *parent = 0) override { Q_UNUSED(parent) return new FileManager(m_plugin,parent); } QList toolBarActions( QWidget* w ) const override { FileManager* m = qobject_cast(w); if( m ) return m->toolBarActions(); return KDevelop::IToolViewFactory::toolBarActions( w ); } - virtual Qt::DockWidgetArea defaultPosition() override + Qt::DockWidgetArea defaultPosition() override { return Qt::LeftDockWidgetArea; } - virtual QString id() const override + QString id() const override { return "org.kdevelop.FileManagerView"; } - virtual bool allowMultiple() const override + bool allowMultiple() const override { return true; } private: KDevFileManagerPlugin *m_plugin; }; KDevFileManagerPlugin::KDevFileManagerPlugin(QObject *parent, const QVariantList &/*args*/) :KDevelop::IPlugin("kdevfilemanager", parent) { setXMLFile("kdevfilemanager.rc"); QMetaObject::invokeMethod(this, "init", Qt::QueuedConnection); } void KDevFileManagerPlugin::init() { m_factory = new KDevFileManagerViewFactory(this); core()->uiController()->addToolView(i18n("Filesystem"), m_factory); } KDevFileManagerPlugin::~KDevFileManagerPlugin() { } void KDevFileManagerPlugin::unload() { core()->uiController()->removeToolView(m_factory); } #include "kdevfilemanagerplugin.moc" diff --git a/plugins/filemanager/kdevfilemanagerplugin.h b/plugins/filemanager/kdevfilemanagerplugin.h index a22c95f272..9e93ac729b 100644 --- a/plugins/filemanager/kdevfilemanagerplugin.h +++ b/plugins/filemanager/kdevfilemanagerplugin.h @@ -1,43 +1,43 @@ /*************************************************************************** * Copyright 2006 Alexander Dymo * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_KDEVFILEMANAGERPLUGIN_H #define KDEVPLATFORM_PLUGIN_KDEVFILEMANAGERPLUGIN_H #include #include class FileManager; class KDevFileManagerPlugin: public KDevelop::IPlugin { Q_OBJECT public: explicit KDevFileManagerPlugin(QObject *parent, const QVariantList &args = QVariantList() ); - ~KDevFileManagerPlugin(); + ~KDevFileManagerPlugin() override; - virtual void unload() override; + void unload() override; private slots: void init(); private: class KDevFileManagerViewFactory *m_factory; }; #endif diff --git a/plugins/filetemplates/classidentifierpage.h b/plugins/filetemplates/classidentifierpage.h index a52459f8fe..2a5266e84c 100644 --- a/plugins/filetemplates/classidentifierpage.h +++ b/plugins/filetemplates/classidentifierpage.h @@ -1,74 +1,74 @@ /* This file is part of KDevelop Copyright 2008 Hamish Rodda 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. */ #ifndef KDEVPLATFORM_PLUGIN_CLASSIDENTIFIERPAGE_H #define KDEVPLATFORM_PLUGIN_CLASSIDENTIFIERPAGE_H #include /** * Assistant dialog page for setting the identifier and inheritances of a new class */ class ClassIdentifierPage : public QWidget { Q_OBJECT Q_PROPERTY(QStringList inheritance READ inheritanceList) public: explicit ClassIdentifierPage(QWidget* parent); - virtual ~ClassIdentifierPage(); + ~ClassIdentifierPage() override; /** * @return The full identifier of the new class, with namespaces, * as entered by the user. */ QString identifier() const; /** * @return A list of inheritances for the new class. * * Each list elements contains both inheritance type and the base class name, * such as "public QObject" or "implements Serializable" */ QStringList inheritanceList() const; /** * Sets the contents of the inheritance list to @p list * * @param list list of inheritance descriptions. */ void setInheritanceList(const QStringList& list); Q_SIGNALS: void inheritanceChanged(); /** * Emitted whenever the content of the page changes. * * @param valid @c true if the content is valid and the user can procede to * the next page, @c false otherwise. */ void isValid(bool valid); private Q_SLOTS: void checkIdentifier(); private: struct ClassIdentifierPagePrivate* const d; }; #endif // KDEVPLATFORM_PLUGIN_CLASSIDENTIFIERPAGE_H diff --git a/plugins/filetemplates/classmemberspage.h b/plugins/filetemplates/classmemberspage.h index 1ddeac1839..8262b908a8 100644 --- a/plugins/filetemplates/classmemberspage.h +++ b/plugins/filetemplates/classmemberspage.h @@ -1,53 +1,53 @@ /* This file is part of KDevelop Copyright 2012 Miha Čančula 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 KDEVPLATFORM_PLUGIN_CLASSMEMBERSPAGE_H #define KDEVPLATFORM_PLUGIN_CLASSMEMBERSPAGE_H #include #include /** * Assistant dialog page for declaring data members of a new class * */ class ClassMembersPage : public QWidget { Q_OBJECT Q_PROPERTY(KDevelop::VariableDescriptionList members READ members WRITE setMembers) public: explicit ClassMembersPage(QWidget* parent); - virtual ~ClassMembersPage(); + ~ClassMembersPage() override; /** * @return The list of data members, as entered by the user. */ KDevelop::VariableDescriptionList members() const; /** * Set the list of data members to @p members. */ void setMembers(const KDevelop::VariableDescriptionList& members); private: class ClassMembersPagePrivate* const d; }; #endif // KDEVPLATFORM_PLUGIN_CLASSMEMBERSPAGE_H diff --git a/plugins/filetemplates/filetemplatesplugin.cpp b/plugins/filetemplates/filetemplatesplugin.cpp index bc51c19971..4c734b1644 100644 --- a/plugins/filetemplates/filetemplatesplugin.cpp +++ b/plugins/filetemplates/filetemplatesplugin.cpp @@ -1,289 +1,289 @@ #include "filetemplatesplugin.h" #include "templateclassassistant.h" #include "templatepreviewtoolview.h" #include "debug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace KDevelop; K_PLUGIN_FACTORY_WITH_JSON(FileTemplatesFactory, "kdevfiletemplates.json", registerPlugin();) class TemplatePreviewFactory : public KDevelop::IToolViewFactory { public: TemplatePreviewFactory(FileTemplatesPlugin* plugin) : KDevelop::IToolViewFactory() , m_plugin(plugin) { } - virtual QWidget* create(QWidget* parent = 0) override + QWidget* create(QWidget* parent = 0) override { return new TemplatePreviewToolView(m_plugin, parent); } - virtual QString id() const override + QString id() const override { return "org.kdevelop.TemplateFilePreview"; } - virtual Qt::DockWidgetArea defaultPosition() override + Qt::DockWidgetArea defaultPosition() override { return Qt::RightDockWidgetArea; } private: FileTemplatesPlugin* m_plugin; }; FileTemplatesPlugin::FileTemplatesPlugin(QObject* parent, const QVariantList& args) : IPlugin("kdevfiletemplates", parent) , m_model(0) { Q_UNUSED(args); KDEV_USE_EXTENSION_INTERFACE(ITemplateProvider) setXMLFile("kdevfiletemplates.rc"); QAction* action = actionCollection()->addAction("new_from_template"); action->setText( i18n( "New From Template" ) ); action->setIcon( QIcon::fromTheme( "code-class" ) ); action->setWhatsThis( i18n( "Allows you to create new source code files, such as classes or unit tests, using templates." ) ); action->setStatusTip( i18n( "Create new files from a template" ) ); connect (action, &QAction::triggered, this, &FileTemplatesPlugin::createFromTemplate); m_toolView = new TemplatePreviewFactory(this); core()->uiController()->addToolView(i18n("Template Preview"), m_toolView); } FileTemplatesPlugin::~FileTemplatesPlugin() { } void FileTemplatesPlugin::unload() { core()->uiController()->removeToolView(m_toolView); } ContextMenuExtension FileTemplatesPlugin::contextMenuExtension (Context* context) { ContextMenuExtension ext; QUrl fileUrl; if (context->type() == Context::ProjectItemContext) { ProjectItemContext* projectContext = dynamic_cast(context); QList items = projectContext->items(); if (items.size() != 1) { return ext; } QUrl url; ProjectBaseItem* item = items.first(); if (item->folder()) { url = item->path().toUrl(); } else if (item->target()) { url = item->parent()->path().toUrl(); } if (url.isValid()) { QAction* action = new QAction(i18n("Create From Template"), this); action->setIcon(QIcon::fromTheme("code-class")); action->setData(url); connect(action, &QAction::triggered, this, &FileTemplatesPlugin::createFromTemplate); ext.addAction(ContextMenuExtension::FileGroup, action); } if (item->file()) { fileUrl = item->path().toUrl(); } } else if (context->type() == Context::EditorContext) { KDevelop::EditorContext* editorContext = dynamic_cast(context); fileUrl = editorContext->url(); } if (fileUrl.isValid() && determineTemplateType(fileUrl) != NoTemplate) { QAction* action = new QAction(i18n("Show Template Preview"), this); action->setIcon(QIcon::fromTheme("document-preview")); action->setData(fileUrl); connect(action, &QAction::triggered, this, &FileTemplatesPlugin::previewTemplate); ext.addAction(ContextMenuExtension::ExtensionGroup, action); } return ext; } QString FileTemplatesPlugin::name() const { return i18n("File Templates"); } QIcon FileTemplatesPlugin::icon() const { return QIcon::fromTheme("code-class"); } QAbstractItemModel* FileTemplatesPlugin::templatesModel() { if(!m_model) { m_model = new TemplatesModel("kdevfiletemplates", this); } return m_model; } QString FileTemplatesPlugin::knsConfigurationFile() const { return "kdevfiletemplates.knsrc"; } QStringList FileTemplatesPlugin::supportedMimeTypes() const { QStringList types; types << "application/x-desktop"; types << "application/x-bzip-compressed-tar"; types << "application/zip"; return types; } void FileTemplatesPlugin::reload() { templatesModel(); m_model->refresh(); } void FileTemplatesPlugin::loadTemplate(const QString& fileName) { templatesModel(); m_model->loadTemplateFile(fileName); } void FileTemplatesPlugin::createFromTemplate() { QUrl baseUrl; if (QAction* action = qobject_cast(sender())) { baseUrl = action->data().value(); } if (!baseUrl.isValid()) { // fall-back to currently active document's parent directory IDocument* doc = ICore::self()->documentController()->activeDocument(); if (doc && doc->url().isValid()) { baseUrl = doc->url().adjusted(QUrl::RemoveFilename); } } TemplateClassAssistant* assistant = new TemplateClassAssistant(QApplication::activeWindow(), baseUrl); assistant->setAttribute(Qt::WA_DeleteOnClose); assistant->show(); } FileTemplatesPlugin::TemplateType FileTemplatesPlugin::determineTemplateType(const QUrl& url) { QDir dir(url.toLocalFile()); /* * Search for a description file in the url's directory. * If it is not found there, try cascading up a maximum of 5 directories. */ int level = 0; while (dir.cdUp() && level < 5) { QStringList filters; filters << "*.kdevtemplate" << "*.desktop"; foreach (const QString& entry, dir.entryList(filters)) { qCDebug(PLUGIN_FILETEMPLATES) << "Trying entry" << entry; /* * This logic is not perfect, but it works for most cases. * * Project template description files usually have the suffix * ".kdevtemplate", so those are easy to find. For project templates, * all the files in the directory are template files. * * On the other hand, file templates use the generic suffix ".desktop". * Fortunately, those explicitly list input and output files, so we * only match the explicitly listed files */ if (entry.endsWith(".kdevtemplate")) { return ProjectTemplate; } KConfig* config = new KConfig(dir.absoluteFilePath(entry), KConfig::SimpleConfig); KConfigGroup group = config->group("General"); qCDebug(PLUGIN_FILETEMPLATES) << "General group keys:" << group.keyList(); if (!group.hasKey("Name") || !group.hasKey("Category")) { continue; } if (group.hasKey("Files")) { qCDebug(PLUGIN_FILETEMPLATES) << "Group has files " << group.readEntry("Files", QStringList()); foreach (const QString& outputFile, group.readEntry("Files", QStringList())) { if (dir.absoluteFilePath(config->group(outputFile).readEntry("File")) == url.toLocalFile()) { return FileTemplate; } } } if (group.hasKey("ShowFilesAfterGeneration")) { return ProjectTemplate; } } ++level; } return NoTemplate; } void FileTemplatesPlugin::previewTemplate() { QAction* action = qobject_cast(sender()); if (!action || !action->data().value().isValid()) { return; } TemplatePreviewToolView* preview = qobject_cast(core()->uiController()->findToolView(i18n("Template Preview"), m_toolView)); if (!preview) { return; } core()->documentController()->activateDocument(core()->documentController()->openDocument(action->data().value())); } #include "filetemplatesplugin.moc" diff --git a/plugins/filetemplates/filetemplatesplugin.h b/plugins/filetemplates/filetemplatesplugin.h index 14566ab892..702cb33355 100644 --- a/plugins/filetemplates/filetemplatesplugin.h +++ b/plugins/filetemplates/filetemplatesplugin.h @@ -1,55 +1,55 @@ #ifndef KDEVPLATFORM_PLUGIN_FILETEMPLATESPLUGIN_H #define KDEVPLATFORM_PLUGIN_FILETEMPLATESPLUGIN_H #include #include #include class QUrl; namespace KDevelop { class TemplatesModel; class IToolViewFactory; } class FileTemplatesPlugin : public KDevelop::IPlugin, public KDevelop::ITemplateProvider { Q_OBJECT Q_INTERFACES(KDevelop::ITemplateProvider) public: enum TemplateType { NoTemplate, FileTemplate, ProjectTemplate }; FileTemplatesPlugin(QObject* parent, const QVariantList& args); - virtual ~FileTemplatesPlugin(); - virtual void unload() override; + ~FileTemplatesPlugin() override; + void unload() override; - virtual KDevelop::ContextMenuExtension contextMenuExtension (KDevelop::Context* context) override; + KDevelop::ContextMenuExtension contextMenuExtension (KDevelop::Context* context) override; - virtual QString name() const override; - virtual QIcon icon() const override; - virtual QAbstractItemModel* templatesModel() override; - virtual QString knsConfigurationFile() const override; - virtual QStringList supportedMimeTypes() const override; + QString name() const override; + QIcon icon() const override; + QAbstractItemModel* templatesModel() override; + QString knsConfigurationFile() const override; + QStringList supportedMimeTypes() const override; - virtual void reload() override; - virtual void loadTemplate(const QString& fileName) override; + void reload() override; + void loadTemplate(const QString& fileName) override; TemplateType determineTemplateType(const QUrl& url); private: KDevelop::TemplatesModel* m_model; KDevelop::IToolViewFactory* m_toolView; public slots: void createFromTemplate(); void previewTemplate(); }; #endif // KDEVPLATFORM_PLUGIN_FILETEMPLATESPLUGIN_H diff --git a/plugins/filetemplates/licensepage.h b/plugins/filetemplates/licensepage.h index 59b3ee3f7f..9d0ac25713 100644 --- a/plugins/filetemplates/licensepage.h +++ b/plugins/filetemplates/licensepage.h @@ -1,55 +1,55 @@ /* This file is part of KDevelop Copyright 2008 Hamish Rodda 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. */ #ifndef KDEVPLATFORM_PLUGIN_LICENSEPAGE_H #define KDEVPLATFORM_PLUGIN_LICENSEPAGE_H #include namespace KDevelop { /** * Assistant dialog page for choosing the license of new source files * * @todo Add the name of the Author at the top of the license */ class LicensePage : public QWidget { Q_OBJECT public: explicit LicensePage(QWidget* parent); - virtual ~LicensePage(); + ~LicensePage() override; /** * @return the full license header, which might either be a pre-defined * or user-supplied one. */ QString license() const; private: // data struct LicensePagePrivate* const d; Q_PRIVATE_SLOT(d, void licenseComboChanged(int license)) }; } #endif // KDEVPLATFORM_PLUGIN_LICENSEPAGE_H diff --git a/plugins/filetemplates/outputpage.h b/plugins/filetemplates/outputpage.h index 501a3beafd..b79ad11367 100644 --- a/plugins/filetemplates/outputpage.h +++ b/plugins/filetemplates/outputpage.h @@ -1,95 +1,95 @@ /* This file is part of KDevelop Copyright 2008 Hamish Rodda 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. */ #ifndef KDEVPLATFORM_PLUGIN_OUTPUTPAGE_H #define KDEVPLATFORM_PLUGIN_OUTPUTPAGE_H #include #include #include namespace KDevelop { class TemplateRenderer; class SourceFileTemplate; class CreateClassAssistant; /** * Assistant page for setting the output location of generated source code */ class OutputPage : public QWidget { Q_OBJECT public: explicit OutputPage(QWidget* parent); - virtual ~OutputPage(); + ~OutputPage() override; /** * Creates form widgets according to the number of output files of the template @p fileTemplate. * File identifiers and labels are read from @p fileTemplate, but not the actual URLs. * * This function is useful to prevent UI flickering that occurs when adding widgets while the page is visible. * It can be called immediately after the template is selected, before the user specified anything for the generated code. */ void prepareForm(const KDevelop::SourceFileTemplate& fileTemplate); /** * Loads file URLs from the template @p fileTemplate. * This function only sets URLs and file positions to widgets created by prepareForm(), * so be sure to call prepareForm() before calling this function. * * @param fileTemplate the template archive with the generated files * @param baseUrl the directory where the files are to be generated * @param renderer used to render any variables in output URLs */ void loadFileTemplate(const KDevelop::SourceFileTemplate& fileTemplate, const QUrl& baseUrl, KDevelop::TemplateRenderer* renderer); /** * Returns the file URLs, as specified by the user. */ QHash fileUrls() const; /** * Returns the positions within files where code is to be generated. */ QHash filePositions() const; Q_SIGNALS: /** * @copydoc ClassIdentifierPage::isValid */ void isValid(bool valid); private: friend struct OutputPagePrivate; struct OutputPagePrivate* const d; Q_PRIVATE_SLOT(d, void updateFileNames()); /** * This implementation simply enables the position widgets on a file that exists. * Derived classes should overload to set the ranges where class generation should be allowed * * @param field the name of the file to be generated (Header, Implementation, etc) */ Q_PRIVATE_SLOT(d, void updateFileRange(const QString& field)); }; } #endif // KDEVPLATFORM_PLUGIN_OUTPUTPAGE_H diff --git a/plugins/filetemplates/overridespage.h b/plugins/filetemplates/overridespage.h index 76b48eb943..0b044a81bc 100644 --- a/plugins/filetemplates/overridespage.h +++ b/plugins/filetemplates/overridespage.h @@ -1,98 +1,98 @@ /* Copyright 2008 Hamish Rodda 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. */ #ifndef KDEVPLATFORM_PLUGIN_OVERRIDESPAGE_H #define KDEVPLATFORM_PLUGIN_OVERRIDESPAGE_H #include #include "language/duchain/declaration.h" class QTreeWidget; class QTreeWidgetItem; namespace KDevelop { /** * Assistant page for choosing class functions, overridden from base classes. */ class OverridesPage : public QWidget { Q_OBJECT public: explicit OverridesPage(QWidget* parent); - virtual ~OverridesPage(); + ~OverridesPage() override; /** * Default implementation populates the tree with all virtual functions in the base classes. * Calls @c addPotentialOverride() on each function, where more filtering can be applied. * * @param directBases Declarations of base classes from which the new class inherits directly. * @param allBases Declarations of all base classes from which functions can be overridden */ virtual void addBaseClasses(const QList& directBases, const QList& allBases); /** * Add @p childDeclaration as potential override. * * Don't call @c KDevelop::OverridesPage::addPotentialOverride() in overloaded * class to filter a declaration. * * @p classItem The parent class from which @p childDeclaration stems from. * Should be used as parent for the override item. * @p childDeclaration The overridable function. */ virtual void addPotentialOverride(QTreeWidgetItem* classItem, const DeclarationPointer& childDeclaration); /** * Add @p declarations as potential overrides under the category @p category. * * The DUChain must be locked for reading before calling this function * * @param category the user-visible category name * @param declarations a list of declarations that can be overridden or implemented in the new class */ void addCustomDeclarations(const QString& category, const QList< KDevelop::DeclarationPointer >& declarations); QList selectedOverrides() const; void clear(); QTreeWidget* overrideTree() const; QWidget* extraFunctionsContainer() const; public Q_SLOTS: /** * Selects all functions for overriding */ virtual void selectAll(); /** * Deselects all potential overrides */ virtual void deselectAll(); private: struct OverridesPagePrivate* const d; }; } #endif // KDEVPLATFORM_PLUGIN_OVERRIDESPAGE_H diff --git a/plugins/filetemplates/templateclassassistant.h b/plugins/filetemplates/templateclassassistant.h index c62c39c99c..1852c8dd7b 100644 --- a/plugins/filetemplates/templateclassassistant.h +++ b/plugins/filetemplates/templateclassassistant.h @@ -1,99 +1,99 @@ /* This file is part of KDevelop Copyright 2012 Miha Čančula 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 KDEVPLATFORM_PLUGIN_TEMPLATECLASSASSISTANT_H #define KDEVPLATFORM_PLUGIN_TEMPLATECLASSASSISTANT_H #include #include namespace KDevelop { /** * @brief An assistant for creating new source code files using Grantlee templates. * * This assistant guides the user through generating source code from templates. * Currently, class and unit test templates are supported. * * Depending on the selected template type (@c Class or @c Test, see SourceFileTemplate::type()), * The assistant creates appropriate pages for setting the required options. * * When creating a new class, an ICreateClassHelper is used for the language-specific features. * If no such helper exists for the chosen template, a generic implementation is used. * The actual generation of classes is done using a TemplateClassGenerator. **/ class TemplateClassAssistant : public KAssistantDialog { Q_OBJECT public: /** * Creates a new assistant * * @param parent parent widget * @param baseUrl the directory where the new class should be created **/ explicit TemplateClassAssistant(QWidget* parent, const QUrl& baseUrl = QUrl()); /** * Destroys the assistant **/ - virtual ~TemplateClassAssistant(); + ~TemplateClassAssistant() override; /** * Sets up the template selection page */ void setup(); /** * @return The url from where the assistant was started. * * If the assistant was started from the context menu of a project item, * this function returns that item's URL. Otherwise, this returns an invalid URL. */ QUrl baseUrl() const; /** * Called when the user selected a template in the first page of the assistant. * * This function creates all the other pages, depending on the type of the selected template. * * @param templateDescription template description file of the selected template */ void templateChosen(const QString& templateDescription); public Q_SLOTS: - virtual void next() override; - virtual void back() override; - virtual void accept() override; + void next() override; + void back() override; + void accept() override; /** * Sets whether the current page is valid or not. * If the page is valid, the "Next" or "Finish" button will be displayed. * * @param valid true if the user-provided information on the current page is valid, false otherwise */ void setCurrentPageValid(bool valid); private: class TemplateClassAssistantPrivate* const d; }; } #endif // KDEVPLATFORM_PLUGIN_TEMPLATECLASSASSISTANT_H diff --git a/plugins/filetemplates/templateoptionspage.h b/plugins/filetemplates/templateoptionspage.h index 54ed596f00..84939a3e0f 100644 --- a/plugins/filetemplates/templateoptionspage.h +++ b/plugins/filetemplates/templateoptionspage.h @@ -1,83 +1,83 @@ /* This file is part of KDevelop Copyright 2012 Miha Čančula 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 KDEVPLATFORM_PLUGIN_TEMPLATEOPTIONSPAGE_H #define KDEVPLATFORM_PLUGIN_TEMPLATEOPTIONSPAGE_H #include #include namespace KDevelop { class TemplateRenderer; class SourceFileTemplate; class TemplateClassAssistant; /** * @brief Shows a page for configuring options specified by a class template * * Templates can include a file that specify configuration options. * These can be set by the user before creating the class and are passed to the template. * * @sa SourceFileTemplate::customOptions() **/ class TemplateOptionsPage : public QWidget { Q_OBJECT Q_PROPERTY(QVariantHash templateOptions READ templateOptions) public: /** * @brief Create a new template options page * * @param parent the parent template class assistant * @param f window flags, passed to QWidget **/ explicit TemplateOptionsPage(QWidget* parent, Qt::WindowFlags f = 0); /** * Destructor **/ - virtual ~TemplateOptionsPage(); + ~TemplateOptionsPage() override; /** * Parses the XML-formatted .kcfg file contents and creates the UI for setting template options. * * @param contents the file contents **/ void load(const SourceFileTemplate& fileTemplate, TemplateRenderer* renderer); /** * @property templateOptions * * The user-set options. Keys are the options' names, and values are their values. * **/ QVariantHash templateOptions() const; private: class TemplateOptionsPagePrivate* const d; }; } #endif // KDEVPLATFORM_PLUGIN_TEMPLATEOPTIONSPAGE_H diff --git a/plugins/filetemplates/templatepreview.h b/plugins/filetemplates/templatepreview.h index 579f756615..80f53aab62 100644 --- a/plugins/filetemplates/templatepreview.h +++ b/plugins/filetemplates/templatepreview.h @@ -1,79 +1,79 @@ /* * This file is part of KDevelop * Copyright 2012 Milian Wolff * * 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_PLUGIN_TEMPLATEPREVIEW_H #define KDEVPLATFORM_PLUGIN_TEMPLATEPREVIEW_H #include #include #include namespace KTextEditor { class Document; class View; } /** * A renderer that adds some common variables for previewing purposes. */ class TemplatePreviewRenderer : public KDevelop::TemplateRenderer { public: TemplatePreviewRenderer(); - virtual ~TemplatePreviewRenderer(); + ~TemplatePreviewRenderer() override; }; /** * A KTextEditor::View wrapper to show a preview of a template. */ class TemplatePreview : public QWidget { Q_OBJECT public: explicit TemplatePreview(QWidget* parent, Qt::WindowFlags f = 0); - virtual ~TemplatePreview(); + ~TemplatePreview() override; /** * Set the template contents which will be rendered. * * @p text the template contents * @p isProject set to true if the contents resemble a project template * @return an error message, or an empty string if everything worked */ QString setText(const QString& text, bool isProject = false, KDevelop::TemplateRenderer::EmptyLinesPolicy policy = KDevelop::TemplateRenderer::TrimEmptyLines); /** * @return The read-only document. */ KTextEditor::Document* document() const; private: Q_DISABLE_COPY(TemplatePreview) QHash m_variables; QScopedPointer m_preview; KTextEditor::View* m_view; }; #endif // KDEVPLATFORM_PLUGIN_TEMPLATEPREVIEW_H diff --git a/plugins/filetemplates/templatepreviewtoolview.h b/plugins/filetemplates/templatepreviewtoolview.h index c64b39512a..576e0e38aa 100644 --- a/plugins/filetemplates/templatepreviewtoolview.h +++ b/plugins/filetemplates/templatepreviewtoolview.h @@ -1,72 +1,72 @@ /* * This file is part of KDevelop * Copyright 2012 Miha Čančula * * 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 KDEVPLATFORM_PLUGIN_TEMPLATEPREVIEWTOOLVIEW_H #define KDEVPLATFORM_PLUGIN_TEMPLATEPREVIEWTOOLVIEW_H #include #include namespace KTextEditor { class Document; } namespace KDevelop { class IDocument; } namespace Ui { class TemplatePreviewToolView; } class FileTemplatesPlugin; class TemplatePreview; class TemplatePreviewToolView : public QWidget { Q_OBJECT public: explicit TemplatePreviewToolView(FileTemplatesPlugin* plugin, QWidget* parent, Qt::WindowFlags f = 0); - virtual ~TemplatePreviewToolView(); + ~TemplatePreviewToolView() override; private: Ui::TemplatePreviewToolView* ui; KTextEditor::Document* m_original; FileTemplatesPlugin* m_plugin; KDevelop::TemplateRenderer::EmptyLinesPolicy m_policy; private slots: void sourceTextChanged(const QString& text); protected: - virtual void showEvent(QShowEvent*) override; + void showEvent(QShowEvent*) override; public slots: void documentActivated(KDevelop::IDocument* document); void documentChanged(KTextEditor::Document* textDocument); void documentClosed(KDevelop::IDocument* document); void selectedRendererChanged(); }; #endif // KDEVPLATFORM_PLUGIN_TEMPLATEPREVIEWTOOLVIEW_H diff --git a/plugins/filetemplates/templateselectionpage.h b/plugins/filetemplates/templateselectionpage.h index a49faa40c5..e5eba22dab 100644 --- a/plugins/filetemplates/templateselectionpage.h +++ b/plugins/filetemplates/templateselectionpage.h @@ -1,73 +1,73 @@ /* This file is part of KDevelop Copyright 2012 Miha Čančula 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 KDEVPLATFORM_PLUGIN_TEMPLATESELECTIONPAGE_H #define KDEVPLATFORM_PLUGIN_TEMPLATESELECTIONPAGE_H #include class QModelIndex; namespace KDevelop { class TemplateClassAssistant; /** * An assistant page for selecting a class template **/ class TemplateSelectionPage : public QWidget { Q_OBJECT Q_PROPERTY(QString selectedTemplate READ selectedTemplate) public: explicit TemplateSelectionPage (TemplateClassAssistant* parent, Qt::WindowFlags f = 0); - virtual ~TemplateSelectionPage(); + ~TemplateSelectionPage() override; /** * @property selectedTemplate * * The class template, selected by the user. * This property stores the full path to the template description (.desktop) file **/ QString selectedTemplate() const; - virtual QSize minimumSizeHint() const override; + QSize minimumSizeHint() const override; public Q_SLOTS: /** * Saves the selected template setting into the current project's configuration. * * If the assistant's base URL does not point to any project, this function does nothing. */ void saveConfig(); private: class TemplateSelectionPagePrivate* const d; Q_PRIVATE_SLOT(d, void currentTemplateChanged(const QModelIndex& index)) Q_PRIVATE_SLOT(d, void getMoreClicked()) Q_PRIVATE_SLOT(d, void loadFileClicked()) }; } #endif // KDEVPLATFORM_PLUGIN_TEMPLATESELECTIONPAGE_H diff --git a/plugins/filetemplates/testcasespage.h b/plugins/filetemplates/testcasespage.h index 4be8dfb769..22ce8cc7fc 100644 --- a/plugins/filetemplates/testcasespage.h +++ b/plugins/filetemplates/testcasespage.h @@ -1,72 +1,72 @@ /* * This file is part of KDevelop * Copyright 2012 Miha Čančula * * 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. */ #ifndef KDEVPLATFORM_PLUGIN_TESTCASESWIDGET_H #define KDEVPLATFORM_PLUGIN_TESTCASESWIDGET_H #include class KEditListWidget; namespace KDevelop { /** * Assistant page for specifying the list of test cases * */ class TestCasesPage : public QWidget { Q_OBJECT Q_PROPERTY(QStringList testCases READ testCases WRITE setTestCases) public: explicit TestCasesPage(QWidget* parent = 0, Qt::WindowFlags f = 0); - virtual ~TestCasesPage(); + ~TestCasesPage() override; /** * The name of the new test, as set by the user */ QString name() const; /** * Returns the list of test case names */ QStringList testCases() const; /** * Sets the current list of test case names to @p testCases */ void setTestCases(const QStringList& testCases); Q_SIGNALS: void isValid(bool valid); private: class TestCasesPagePrivate* const d; private Q_SLOTS: void identifierChanged(const QString& identifier); }; } #endif // KDEVPLATFORM_PLUGIN_TESTCASESWIDGET_H diff --git a/plugins/git/gitmessagehighlighter.h b/plugins/git/gitmessagehighlighter.h index aa87268760..1ce98c23f4 100644 --- a/plugins/git/gitmessagehighlighter.h +++ b/plugins/git/gitmessagehighlighter.h @@ -1,47 +1,47 @@ /*************************************************************************** * Copyright 2011 Sergey Vidyuk * * Copyright 2012 Aleix Pol Gonzalez * * * * 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_PLUGIN_GITMESSAGEHIGHLIGHTER_H #define KDEVPLATFORM_PLUGIN_GITMESSAGEHIGHLIGHTER_H #include class GitMessageHighlighter : public Sonnet::Highlighter { Q_OBJECT public: explicit GitMessageHighlighter(QTextEdit* parent); - virtual ~GitMessageHighlighter(); + ~GitMessageHighlighter() override; protected: - virtual void highlightBlock(const QString& text) override; + void highlightBlock(const QString& text) override; private: void applyErrorFormat(GitMessageHighlighter* text, bool warning, const QString& tooltip, int startPos, int endPos); enum BlockState { NoState = -1, Summary, SummarySeparator, DetailedMessage }; }; #endif // KDEVPLATFORM_PLUGIN_GITMESSAGEHIGHLIGHTER_H diff --git a/plugins/git/gitplugin.cpp b/plugins/git/gitplugin.cpp index 9395f95a48..d1f87a4be1 100644 --- a/plugins/git/gitplugin.cpp +++ b/plugins/git/gitplugin.cpp @@ -1,1462 +1,1462 @@ /*************************************************************************** * Copyright 2008 Evgeniy Ivanov * * Copyright 2009 Hugo Parente Lima * * Copyright 2010 Aleix Pol Gonzalez * * * * 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 "gitplugin.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gitclonejob.h" #include #include #include "stashmanagerdialog.h" #include #include #include #include #include #include #include "gitjob.h" #include "gitmessagehighlighter.h" #include "gitplugincheckinrepositoryjob.h" #include "debug.h" Q_LOGGING_CATEGORY(PLUGIN_GIT, "kdevplatform.plugins.git") using namespace KDevelop; QVariant runSynchronously(KDevelop::VcsJob* job) { QVariant ret; if(job->exec() && job->status()==KDevelop::VcsJob::JobSucceeded) { ret = job->fetchResults(); } delete job; return ret; } namespace { QDir dotGitDirectory(const QUrl& dirPath) { const QFileInfo finfo(dirPath.toLocalFile()); QDir dir = finfo.isDir() ? QDir(finfo.filePath()): finfo.absoluteDir(); static const QString gitDir = QStringLiteral(".git"); while (!dir.exists(gitDir) && dir.cdUp()) {} // cdUp, until there is a sub-directory called .git if (dir.isRoot()) { qCWarning(PLUGIN_GIT) << "couldn't find the git root for" << dirPath; } return dir; } /** * Whenever a directory is provided, change it for all the files in it but not inner directories, * that way we make sure we won't get into recursion, */ static QList preventRecursion(const QList& urls) { QList ret; foreach(const QUrl& url, urls) { QDir d(url.toLocalFile()); if(d.exists()) { QStringList entries = d.entryList(QDir::Files | QDir::NoDotAndDotDot); foreach(const QString& entry, entries) { QUrl entryUrl = QUrl::fromLocalFile(d.absoluteFilePath(entry)); ret += entryUrl; } } else ret += url; } return ret; } QString toRevisionName(const KDevelop::VcsRevision& rev, QString currentRevision=QString()) { switch(rev.revisionType()) { case VcsRevision::Special: switch(rev.revisionValue().value()) { case VcsRevision::Head: return "^HEAD"; case VcsRevision::Base: return ""; case VcsRevision::Working: return ""; case VcsRevision::Previous: Q_ASSERT(!currentRevision.isEmpty()); return currentRevision + "^1"; case VcsRevision::Start: return ""; case VcsRevision::UserSpecialType: //Not used Q_ASSERT(false && "i don't know how to do that"); } break; case VcsRevision::GlobalNumber: return rev.revisionValue().toString(); case VcsRevision::Date: case VcsRevision::FileNumber: case VcsRevision::Invalid: case VcsRevision::UserSpecialType: Q_ASSERT(false); } return QString(); } QString revisionInterval(const KDevelop::VcsRevision& rev, const KDevelop::VcsRevision& limit) { QString ret; if(rev.revisionType()==VcsRevision::Special && rev.revisionValue().value()==VcsRevision::Start) //if we want it to the beginning just put the revisionInterval ret = toRevisionName(limit, QString()); else { QString dst = toRevisionName(limit); if(dst.isEmpty()) ret = dst; else { QString src = toRevisionName(rev, dst); if(src.isEmpty()) ret = src; else ret = src+".."+dst; } } return ret; } QDir urlDir(const QUrl& url) { QFileInfo f(url.toLocalFile()); if(f.isDir()) return QDir(url.toLocalFile()); else return f.absoluteDir(); } QDir urlDir(const QList& urls) { return urlDir(urls.first()); } //TODO: could be improved } GitPlugin::GitPlugin( QObject *parent, const QVariantList & ) : DistributedVersionControlPlugin(parent, "kdevgit"), m_oldVersion(false), m_usePrefix(true) { if (QStandardPaths::findExecutable("git").isEmpty()) { m_hasError = true; m_errorDescription = i18n("git is not installed"); return; } KDEV_USE_EXTENSION_INTERFACE( KDevelop::IBasicVersionControl ) KDEV_USE_EXTENSION_INTERFACE( KDevelop::IDistributedVersionControl ) KDEV_USE_EXTENSION_INTERFACE( KDevelop::IBranchingVersionControl ) m_hasError = false; setObjectName("Git"); DVcsJob* versionJob = new DVcsJob(QDir::tempPath(), this, KDevelop::OutputJob::Silent); *versionJob << "git" << "--version"; connect(versionJob, &DVcsJob::readyForParsing, this, &GitPlugin::parseGitVersionOutput); ICore::self()->runController()->registerJob(versionJob); m_watcher = new KDirWatch(this); connect(m_watcher, &KDirWatch::dirty, this, &GitPlugin::fileChanged); connect(m_watcher, &KDirWatch::created, this, &GitPlugin::fileChanged); } GitPlugin::~GitPlugin() {} bool emptyOutput(DVcsJob* job) { QScopedPointer _job(job); if(job->exec() && job->status()==VcsJob::JobSucceeded) return job->rawOutput().trimmed().isEmpty(); return false; } bool GitPlugin::hasStashes(const QDir& repository) { return !emptyOutput(gitStash(repository, QStringList("list"), KDevelop::OutputJob::Silent)); } bool GitPlugin::hasModifications(const QDir& d) { return !emptyOutput(lsFiles(d, QStringList("-m"), OutputJob::Silent)); } bool GitPlugin::hasModifications(const QDir& repo, const QUrl& file) { return !emptyOutput(lsFiles(repo, QStringList() << "-m" << file.path(), OutputJob::Silent)); } void GitPlugin::additionalMenuEntries(QMenu* menu, const QList& urls) { m_urls = urls; QDir dir=urlDir(urls); bool hasSt = hasStashes(dir); menu->addSeparator()->setText(i18n("Git Stashes")); menu->addAction(i18n("Stash Manager"), this, SLOT(ctxStashManager()))->setEnabled(hasSt); menu->addAction(i18n("Push Stash"), this, SLOT(ctxPushStash())); menu->addAction(i18n("Pop Stash"), this, SLOT(ctxPopStash()))->setEnabled(hasSt); } void GitPlugin::ctxPushStash() { VcsJob* job = gitStash(urlDir(m_urls), QStringList(), KDevelop::OutputJob::Verbose); ICore::self()->runController()->registerJob(job); } void GitPlugin::ctxPopStash() { VcsJob* job = gitStash(urlDir(m_urls), QStringList("pop"), KDevelop::OutputJob::Verbose); ICore::self()->runController()->registerJob(job); } void GitPlugin::ctxStashManager() { QPointer d = new StashManagerDialog(urlDir(m_urls), this, 0); d->exec(); delete d; } DVcsJob* GitPlugin::errorsFound(const QString& error, KDevelop::OutputJob::OutputJobVerbosity verbosity=OutputJob::Verbose) { DVcsJob* j = new DVcsJob(QDir::temp(), this, verbosity); *j << "echo" << i18n("error: %1", error) << "-n"; return j; } QString GitPlugin::name() const { return QLatin1String("Git"); } QUrl GitPlugin::repositoryRoot(const QUrl& path) { return QUrl::fromLocalFile(dotGitDirectory(path).absolutePath()); } bool GitPlugin::isValidDirectory(const QUrl & dirPath) { QDir dir=dotGitDirectory(dirPath); return dir.cd(".git") && dir.exists("HEAD"); } bool GitPlugin::isVersionControlled(const QUrl &path) { QFileInfo fsObject(path.toLocalFile()); if (!fsObject.exists()) { return false; } if (fsObject.isDir()) { return isValidDirectory(path); } QString filename = fsObject.fileName(); QStringList otherFiles = getLsFiles(fsObject.dir(), QStringList("--") << filename, KDevelop::OutputJob::Silent); return !otherFiles.empty(); } VcsJob* GitPlugin::init(const QUrl &directory) { DVcsJob* job = new DVcsJob(urlDir(directory), this); job->setType(VcsJob::Import); *job << "git" << "init"; return job; } VcsJob* GitPlugin::createWorkingCopy(const KDevelop::VcsLocation & source, const QUrl& dest, KDevelop::IBasicVersionControl::RecursionMode) { DVcsJob* job = new GitCloneJob(urlDir(dest), this); job->setType(VcsJob::Import); *job << "git" << "clone" << "--progress" << "--" << source.localUrl().url() << dest; return job; } VcsJob* GitPlugin::add(const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion) { if (localLocations.empty()) return errorsFound(i18n("Did not specify the list of files"), OutputJob::Verbose); DVcsJob* job = new GitJob(dotGitDirectory(localLocations.front()), this); job->setType(VcsJob::Add); *job << "git" << "add" << "--" << (recursion == IBasicVersionControl::Recursive ? localLocations : preventRecursion(localLocations)); return job; } KDevelop::VcsJob* GitPlugin::status(const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion) { if (localLocations.empty()) return errorsFound(i18n("Did not specify the list of files"), OutputJob::Verbose); DVcsJob* job = new GitJob(urlDir(localLocations), this, OutputJob::Silent); job->setType(VcsJob::Status); if(m_oldVersion) { *job << "git" << "ls-files" << "-t" << "-m" << "-c" << "-o" << "-d" << "-k" << "--directory"; connect(job, &DVcsJob::readyForParsing, this, &GitPlugin::parseGitStatusOutput_old); } else { *job << "git" << "status" << "--porcelain"; job->setIgnoreError(true); connect(job, &DVcsJob::readyForParsing, this, &GitPlugin::parseGitStatusOutput); } *job << "--" << (recursion == IBasicVersionControl::Recursive ? localLocations : preventRecursion(localLocations)); return job; } VcsJob* GitPlugin::diff(const QUrl& fileOrDirectory, const KDevelop::VcsRevision& srcRevision, const KDevelop::VcsRevision& dstRevision, VcsDiff::Type /*type*/, IBasicVersionControl::RecursionMode recursion) { //TODO: control different types DVcsJob* job = new GitJob(dotGitDirectory(fileOrDirectory), this, KDevelop::OutputJob::Silent); job->setType(VcsJob::Diff); *job << "git" << "diff" << "--no-color" << "--no-ext-diff"; if (!usePrefix()) { // KDE's ReviewBoard now requires p1 patchfiles, so `git diff --no-prefix` to generate p0 patches // has become optional. *job << "--no-prefix"; } if(srcRevision.revisionType()==VcsRevision::Special && dstRevision.revisionType()==VcsRevision::Special && srcRevision.specialType()==VcsRevision::Base && dstRevision.specialType()==VcsRevision::Working) *job << "HEAD"; else { QString revstr = revisionInterval(srcRevision, dstRevision); if(!revstr.isEmpty()) *job << revstr; } *job << "--"; if (recursion == IBasicVersionControl::Recursive) { *job << fileOrDirectory; } else { *job << preventRecursion(QList() << fileOrDirectory); } connect(job, &DVcsJob::readyForParsing, this, &GitPlugin::parseGitDiffOutput); return job; } VcsJob* GitPlugin::revert(const QList& localLocations, IBasicVersionControl::RecursionMode recursion) { if(localLocations.isEmpty() ) return errorsFound(i18n("Could not revert changes"), OutputJob::Verbose); QDir repo = urlDir(repositoryRoot(localLocations.first())); QString modified; for (const auto& file: localLocations) { if (hasModifications(repo, file)) { modified.append(file.toDisplayString(QUrl::PreferLocalFile) + "
"); } } if (!modified.isEmpty()) { auto res = KMessageBox::questionYesNo(nullptr, i18n("The following files have uncommited changes, " "which will be lost. Continue?") + "

" + modified); if (res != KMessageBox::Yes) { return errorsFound(QString(), OutputJob::Silent); } } DVcsJob* job = new GitJob(dotGitDirectory(localLocations.front()), this); job->setType(VcsJob::Revert); *job << "git" << "checkout" << "--"; *job << (recursion == IBasicVersionControl::Recursive ? localLocations : preventRecursion(localLocations)); return job; } //TODO: git doesn't like empty messages, but "KDevelop didn't provide any message, it may be a bug" looks ugly... //If no files specified then commit already added files VcsJob* GitPlugin::commit(const QString& message, const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion) { if (localLocations.empty() || message.isEmpty()) return errorsFound(i18n("No files or message specified")); QDir dir = dotGitDirectory(localLocations.front()); DVcsJob* job = new DVcsJob(dir, this); job->setType(VcsJob::Commit); QList files = (recursion == IBasicVersionControl::Recursive ? localLocations : preventRecursion(localLocations)); addNotVersionedFiles(dir, files); *job << "git" << "commit" << "-m" << message; *job << "--" << files; return job; } void GitPlugin::addNotVersionedFiles(const QDir& dir, const QList& files) { QStringList otherStr = getLsFiles(dir, QStringList() << "--others", KDevelop::OutputJob::Silent); QList toadd, otherFiles; foreach(const QString& file, otherStr) { QUrl v = QUrl::fromLocalFile(dir.absoluteFilePath(file)); otherFiles += v; } //We add the files that are not versioned foreach(const QUrl& file, files) { if(otherFiles.contains(file) && QFileInfo(file.toLocalFile()).isFile()) toadd += file; } if(!toadd.isEmpty()) { VcsJob* job = add(toadd); job->exec(); } } bool isEmptyDirStructure(const QDir &dir) { foreach (const QFileInfo &i, dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot)) { if (i.isDir()) { if (!isEmptyDirStructure(QDir(i.filePath()))) return false; } else if (i.isFile()) { return false; } } return true; } VcsJob* GitPlugin::remove(const QList& files) { if (files.isEmpty()) return errorsFound(i18n("No files to remove")); QDir dotGitDir = dotGitDirectory(files.front()); QList files_(files); QMutableListIterator i(files_); while (i.hasNext()) { QUrl file = i.next(); QFileInfo fileInfo(file.toLocalFile()); QStringList otherStr = getLsFiles(dotGitDir, QStringList() << "--others" << "--" << file.toLocalFile(), KDevelop::OutputJob::Silent); if(!otherStr.isEmpty()) { //remove files not under version control QList otherFiles; foreach(const QString &f, otherStr) { otherFiles << QUrl::fromLocalFile(dotGitDir.path()+'/'+f); } if (fileInfo.isFile()) { //if it's an unversioned file we are done, don't use git rm on it i.remove(); } auto trashJob = KIO::trash(otherFiles); trashJob->exec(); qCDebug(PLUGIN_GIT) << "other files" << otherFiles; } if (fileInfo.isDir()) { if (isEmptyDirStructure(QDir(file.toLocalFile()))) { //remove empty folders, git doesn't do that auto trashJob = KIO::trash(file); trashJob->exec(); qCDebug(PLUGIN_GIT) << "empty folder, removing" << file; //we already deleted it, don't use git rm on it i.remove(); } } } if (files_.isEmpty()) return 0; DVcsJob* job = new GitJob(dotGitDir, this); job->setType(VcsJob::Remove); // git refuses to delete files with local modifications // use --force to overcome this *job << "git" << "rm" << "-r" << "--force"; *job << "--" << files_; return job; } VcsJob* GitPlugin::log(const QUrl& localLocation, const KDevelop::VcsRevision& src, const KDevelop::VcsRevision& dst) { DVcsJob* job = new GitJob(dotGitDirectory(localLocation), this, KDevelop::OutputJob::Silent); job->setType(VcsJob::Log); *job << "git" << "log" << "--date=raw" << "--name-status" << "-M80%" << "--follow"; QString rev = revisionInterval(dst, src); if(!rev.isEmpty()) *job << rev; *job << "--" << localLocation; connect(job, &DVcsJob::readyForParsing, this, &GitPlugin::parseGitLogOutput); return job; } VcsJob* GitPlugin::log(const QUrl& localLocation, const KDevelop::VcsRevision& rev, unsigned long int limit) { DVcsJob* job = new GitJob(dotGitDirectory(localLocation), this, KDevelop::OutputJob::Silent); job->setType(VcsJob::Log); *job << "git" << "log" << "--date=raw" << "--name-status" << "-M80%" << "--follow"; QString revStr = toRevisionName(rev, QString()); if(!revStr.isEmpty()) *job << revStr; if(limit>0) *job << QStringLiteral("-%1").arg(limit); *job << "--" << localLocation; connect(job, &DVcsJob::readyForParsing, this, &GitPlugin::parseGitLogOutput); return job; } KDevelop::VcsJob* GitPlugin::annotate(const QUrl &localLocation, const KDevelop::VcsRevision&) { DVcsJob* job = new GitJob(dotGitDirectory(localLocation), this, KDevelop::OutputJob::Silent); job->setType(VcsJob::Annotate); *job << "git" << "blame" << "--porcelain" << "-w"; *job << "--" << localLocation; connect(job, &DVcsJob::readyForParsing, this, &GitPlugin::parseGitBlameOutput); return job; } void GitPlugin::parseGitBlameOutput(DVcsJob *job) { QVariantList results; VcsAnnotationLine* annotation = 0; QStringList lines = job->output().split('\n'); bool skipNext=false; QMap definedRevisions; for(QStringList::const_iterator it=lines.constBegin(), itEnd=lines.constEnd(); it!=itEnd; ++it) { if(skipNext) { skipNext=false; results += qVariantFromValue(*annotation); continue; } if(it->isEmpty()) continue; QString name = it->left(it->indexOf(' ')); QString value = it->right(it->size()-name.size()-1); if(name=="author") annotation->setAuthor(value); else if(name=="author-mail") {} //TODO: do smth with the e-mail? else if(name=="author-tz") {} //TODO: does it really matter? else if(name=="author-time") annotation->setDate(QDateTime::fromTime_t(value.toUInt())); else if(name=="summary") annotation->setCommitMessage(value); else if(name.startsWith("committer")) {} //We will just store the authors else if(name=="previous") {} //We don't need that either else if(name=="filename") { skipNext=true; } else if(name=="boundary") { definedRevisions.insert("boundary", VcsAnnotationLine()); } else { QStringList values = value.split(' '); VcsRevision rev; rev.setRevisionValue(name.left(8), KDevelop::VcsRevision::GlobalNumber); skipNext = definedRevisions.contains(name); if(!skipNext) definedRevisions.insert(name, VcsAnnotationLine()); annotation = &definedRevisions[name]; annotation->setLineNumber(values[1].toInt() - 1); annotation->setRevision(rev); } } job->setResults(results); } DVcsJob* GitPlugin::lsFiles(const QDir &repository, const QStringList &args, OutputJob::OutputJobVerbosity verbosity) { DVcsJob* job = new DVcsJob(repository, this, verbosity); *job << "git" << "ls-files" << args; return job; } DVcsJob* GitPlugin::gitStash(const QDir& repository, const QStringList& args, OutputJob::OutputJobVerbosity verbosity) { DVcsJob* job = new DVcsJob(repository, this, verbosity); *job << "git" << "stash" << args; return job; } VcsJob* GitPlugin::tag(const QUrl& repository, const QString& commitMessage, const VcsRevision& rev, const QString& tagName) { DVcsJob* job = new DVcsJob(urlDir(repository), this); *job << "git" << "tag" << "-m" << commitMessage << tagName; if(rev.revisionValue().isValid()) *job << rev.revisionValue().toString(); return job; } VcsJob* GitPlugin::switchBranch(const QUrl &repository, const QString &branch) { QDir d=urlDir(repository); if(hasModifications(d) && KMessageBox::questionYesNo(0, i18n("There are pending changes, do you want to stash them first?"))==KMessageBox::Yes) { QScopedPointer stash(gitStash(d, QStringList(), KDevelop::OutputJob::Verbose)); stash->exec(); } DVcsJob* job = new DVcsJob(d, this); *job << "git" << "checkout" << branch; return job; } VcsJob* GitPlugin::branch(const QUrl& repository, const KDevelop::VcsRevision& rev, const QString& branchName) { Q_ASSERT(!branchName.isEmpty()); DVcsJob* job = new DVcsJob(urlDir(repository), this); *job << "git" << "branch" << "--" << branchName; if(!rev.prettyValue().isEmpty()) *job << rev.revisionValue().toString(); return job; } VcsJob* GitPlugin::deleteBranch(const QUrl& repository, const QString& branchName) { DVcsJob* job = new DVcsJob(urlDir(repository), this, OutputJob::Silent); *job << "git" << "branch" << "-D" << branchName; connect(job, &DVcsJob::readyForParsing, this, &GitPlugin::parseGitCurrentBranch); return job; } VcsJob* GitPlugin::renameBranch(const QUrl& repository, const QString& oldBranchName, const QString& newBranchName) { DVcsJob* job = new DVcsJob(urlDir(repository), this, OutputJob::Silent); *job << "git" << "branch" << "-m" << newBranchName << oldBranchName; connect(job, &DVcsJob::readyForParsing, this, &GitPlugin::parseGitCurrentBranch); return job; } VcsJob* GitPlugin::currentBranch(const QUrl& repository) { DVcsJob* job = new DVcsJob(urlDir(repository), this, OutputJob::Silent); job->setIgnoreError(true); *job << "git" << "symbolic-ref" << "-q" << "--short" << "HEAD"; connect(job, &DVcsJob::readyForParsing, this, &GitPlugin::parseGitCurrentBranch); return job; } void GitPlugin::parseGitCurrentBranch(DVcsJob* job) { QString out = job->output().trimmed(); job->setResults(out); } VcsJob* GitPlugin::branches(const QUrl &repository) { DVcsJob* job=new DVcsJob(urlDir(repository)); *job << "git" << "branch" << "-a"; connect(job, &DVcsJob::readyForParsing, this, &GitPlugin::parseGitBranchOutput); return job; } void GitPlugin::parseGitBranchOutput(DVcsJob* job) { QStringList branchListDirty = job->output().split('\n', QString::SkipEmptyParts); QStringList branchList; foreach(QString branch, branchListDirty) { // Skip pointers to another branches (one example of this is "origin/HEAD -> origin/master"); // "git rev-list" chokes on these entries and we do not need duplicate branches altogether. if (branch.contains("->")) continue; // Skip entries such as '(no branch)' if (branch.contains("(no branch)")) continue; if (branch.startsWith('*')) branch = branch.right(branch.size()-2); branchList<setResults(branchList); } /* Few words about how this hardcore works: 1. get all commits (with --paretns) 2. select master (root) branch and get all unicial commits for branches (git-rev-list br2 ^master ^br3) 3. parse allCommits. While parsing set mask (columns state for every row) for BRANCH, INITIAL, CROSS, MERGE and INITIAL are also set in DVCScommit::setParents (depending on parents count) another setType(INITIAL) is used for "bottom/root/first" commits of branches 4. find and set merges, HEADS. It's an ittaration through all commits. - first we check if parent is from the same branch, if no then we go through all commits searching parent's index and set CROSS/HCROSS for rows (in 3 rows are set EMPTY after commit with parent from another tree met) - then we check branchesShas[i][0] to mark heads 4 can be a seporate function. TODO: All this porn require refactoring (rewriting is better)! It's a very dirty implementation. FIXME: 1. HEAD which is head has extra line to connect it with further commit 2. If you menrge branch2 to master, only new commits of branch2 will be visible (it's fine, but there will be extra merge rectangle in master. If there are no extra commits in branch2, but there are another branches, then the place for branch2 will be empty (instead of be used for branch3). 3. Commits that have additional commit-data (not only history merging, but changes to fix conflicts) are shown incorrectly */ QList GitPlugin::getAllCommits(const QString &repo) { initBranchHash(repo); QStringList args; args << "--all" << "--pretty" << "--parents"; QScopedPointer job(gitRevList(repo, args)); bool ret = job->exec(); Q_ASSERT(ret && job->status()==VcsJob::JobSucceeded && "TODO: provide a fall back in case of failing"); Q_UNUSED(ret); QStringList commits = job->output().split('\n', QString::SkipEmptyParts); static QRegExp rx_com("commit \\w{40,40}"); QListcommitList; DVcsEvent item; //used to keep where we have empty/cross/branch entry //true if it's an active branch (then cross or branch) and false if not QVector additionalFlags(branchesShas.count()); additionalFlags.fill(false); //parse output for(int i = 0; i < commits.count(); ++i) { if (commits[i].contains(rx_com)) { qCDebug(PLUGIN_GIT) << "commit found in " << commits[i]; item.setCommit(commits[i].section(' ', 1, 1).trimmed()); // qCDebug(PLUGIN_GIT) << "commit is: " << commits[i].section(' ', 1); QStringList parents; QString parent = commits[i].section(' ', 2); int section = 2; while (!parent.isEmpty()) { /* qCDebug(PLUGIN_GIT) << "Parent is: " << parent;*/ parents.append(parent.trimmed()); section++; parent = commits[i].section(' ', section); } item.setParents(parents); //Avoid Merge string while (!commits[i].contains("Author: ")) ++i; item.setAuthor(commits[i].section("Author: ", 1).trimmed()); // qCDebug(PLUGIN_GIT) << "author is: " << commits[i].section("Author: ", 1); item.setDate(commits[++i].section("Date: ", 1).trimmed()); // qCDebug(PLUGIN_GIT) << "date is: " << commits[i].section("Date: ", 1); QString log; i++; //next line! while (i < commits.count() && !commits[i].contains(rx_com)) log += commits[i++]; --i; //while took commit line item.setLog(log.trimmed()); // qCDebug(PLUGIN_GIT) << "log is: " << log; //mask is used in CommitViewDelegate to understand what we should draw for each branch QList mask; //set mask (properties for each graph column in row) for(int i = 0; i < branchesShas.count(); ++i) { qCDebug(PLUGIN_GIT)<<"commit: " << item.getCommit(); if (branchesShas[i].contains(item.getCommit())) { mask.append(item.getType()); //we set type in setParents //check if parent from the same branch, if not then we have found a root of the branch //and will use empty column for all futher (from top to bottom) revisions //FIXME: we should set CROSS between parent and child (and do it when find merge point) additionalFlags[i] = false; foreach(const QString &sha, item.getParents()) { if (branchesShas[i].contains(sha)) additionalFlags[i] = true; } if (additionalFlags[i] == false) item.setType(DVcsEvent::INITIAL); //hasn't parents from the same branch, used in drawing } else { if (additionalFlags[i] == false) mask.append(DVcsEvent::EMPTY); else mask.append(DVcsEvent::CROSS); } qCDebug(PLUGIN_GIT) << "mask " << i << "is " << mask[i]; } item.setProperties(mask); commitList.append(item); } } //find and set merges, HEADS, require refactoring! for(QList::iterator iter = commitList.begin(); iter != commitList.end(); ++iter) { QStringList parents = iter->getParents(); //we need only only child branches if (parents.count() != 1) break; QString parent = parents[0]; QString commit = iter->getCommit(); bool parent_checked = false; int heads_checked = 0; for(int i = 0; i < branchesShas.count(); ++i) { //check parent if (branchesShas[i].contains(commit)) { if (!branchesShas[i].contains(parent)) { //parent and child are not in same branch //since it is list, than parent has i+1 index //set CROSS and HCROSS for(QList::iterator f_iter = iter; f_iter != commitList.end(); ++f_iter) { if (parent == f_iter->getCommit()) { for(int j = 0; j < i; ++j) { if(branchesShas[j].contains(parent)) f_iter->setPropetry(j, DVcsEvent::MERGE); else f_iter->setPropetry(j, DVcsEvent::HCROSS); } f_iter->setType(DVcsEvent::MERGE); f_iter->setPropetry(i, DVcsEvent::MERGE_RIGHT); qCDebug(PLUGIN_GIT) << parent << " is parent of " << commit; qCDebug(PLUGIN_GIT) << f_iter->getCommit() << " is merge"; parent_checked = true; break; } else f_iter->setPropetry(i, DVcsEvent::CROSS); } } } //mark HEADs if (!branchesShas[i].empty() && commit == branchesShas[i][0]) { iter->setType(DVcsEvent::HEAD); iter->setPropetry(i, DVcsEvent::HEAD); heads_checked++; qCDebug(PLUGIN_GIT) << "HEAD found"; } //some optimization if (heads_checked == branchesShas.count() && parent_checked) break; } } return commitList; } void GitPlugin::initBranchHash(const QString &repo) { const QUrl repoUrl = QUrl::fromLocalFile(repo); QStringList gitBranches = runSynchronously(branches(repoUrl)).toStringList(); qCDebug(PLUGIN_GIT) << "BRANCHES: " << gitBranches; //Now root branch is the current branch. In future it should be the longest branch //other commitLists are got with git-rev-lits branch ^br1 ^ br2 QString root = runSynchronously(currentBranch(repoUrl)).toString(); QScopedPointer job(gitRevList(repo, QStringList(root))); bool ret = job->exec(); Q_ASSERT(ret && job->status()==VcsJob::JobSucceeded && "TODO: provide a fall back in case of failing"); Q_UNUSED(ret); QStringList commits = job->output().split('\n', QString::SkipEmptyParts); // qCDebug(PLUGIN_GIT) << "\n\n\n commits" << commits << "\n\n\n"; branchesShas.append(commits); foreach(const QString &branch, gitBranches) { if (branch == root) continue; QStringList args(branch); foreach(const QString &branch_arg, gitBranches) { if (branch_arg != branch) //man gitRevList for '^' args<<'^' + branch_arg; } QScopedPointer job(gitRevList(repo, args)); bool ret = job->exec(); Q_ASSERT(ret && job->status()==VcsJob::JobSucceeded && "TODO: provide a fall back in case of failing"); Q_UNUSED(ret); QStringList commits = job->output().split('\n', QString::SkipEmptyParts); // qCDebug(PLUGIN_GIT) << "\n\n\n commits" << commits << "\n\n\n"; branchesShas.append(commits); } } //Actually we can just copy the output without parsing. So it's a kind of draft for future void GitPlugin::parseLogOutput(const DVcsJob * job, QList& commits) const { // static QRegExp rx_sep( "[-=]+" ); // static QRegExp rx_date( "date:\\s+([^;]*);\\s+author:\\s+([^;]*).*" ); static QRegExp rx_com( "commit \\w{1,40}" ); QStringList lines = job->output().split('\n', QString::SkipEmptyParts); DVcsEvent item; QString commitLog; for (int i=0; i commits; QString contents = job->output(); // check if git-log returned anything if (contents.isEmpty()) { job->setResults(commits); // empty list return; } // start parsing the output QTextStream s(&contents); VcsEvent item; QString message; bool pushCommit = false; while (!s.atEnd()) { QString line = s.readLine(); if (commitRegex.exactMatch(line)) { if (pushCommit) { item.setMessage(message.trimmed()); commits.append(QVariant::fromValue(item)); item.setItems(QList()); } else { pushCommit = true; } VcsRevision rev; rev.setRevisionValue(commitRegex.cap(1), KDevelop::VcsRevision::GlobalNumber); item.setRevision(rev); message.clear(); } else if (infoRegex.exactMatch(line)) { QString cap1 = infoRegex.cap(1); if (cap1 == "Author") { item.setAuthor(infoRegex.cap(2).trimmed()); } else if (cap1 == "Date") { item.setDate(QDateTime::fromTime_t(infoRegex.cap(2).trimmed().split(' ')[0].toUInt())); } } else if (modificationsRegex.exactMatch(line)) { VcsItemEvent::Actions a = actionsFromString(modificationsRegex.cap(1)[0].toLatin1()); QString filenameA = modificationsRegex.cap(2); VcsItemEvent itemEvent; itemEvent.setActions(a); itemEvent.setRepositoryLocation(filenameA); if(a==VcsItemEvent::Replaced) { QString filenameB = modificationsRegex.cap(3); itemEvent.setRepositoryCopySourceLocation(filenameB); } item.addItem(itemEvent); } else if (line.startsWith(" ")) { message += line.remove(0, 4); message += '\n'; } } item.setMessage(message.trimmed()); commits.append(QVariant::fromValue(item)); job->setResults(commits); } void GitPlugin::parseGitDiffOutput(DVcsJob* job) { VcsDiff diff; diff.setDiff(job->output()); diff.setBaseDiff(repositoryRoot(QUrl::fromLocalFile(job->directory().absolutePath()))); diff.setDepth(usePrefix()? 1 : 0); job->setResults(qVariantFromValue(diff)); } static VcsStatusInfo::State lsfilesToState(char id) { switch(id) { case 'H': return VcsStatusInfo::ItemUpToDate; //Cached case 'S': return VcsStatusInfo::ItemUpToDate; //Skip work tree case 'M': return VcsStatusInfo::ItemHasConflicts; //unmerged case 'R': return VcsStatusInfo::ItemDeleted; //removed/deleted case 'C': return VcsStatusInfo::ItemModified; //modified/changed case 'K': return VcsStatusInfo::ItemDeleted; //to be killed case '?': return VcsStatusInfo::ItemUnknown; //other } Q_ASSERT(false); return VcsStatusInfo::ItemUnknown; } void GitPlugin::parseGitStatusOutput_old(DVcsJob* job) { QStringList outputLines = job->output().split('\n', QString::SkipEmptyParts); QDir dir = job->directory(); QMap allStatus; foreach(const QString& line, outputLines) { VcsStatusInfo::State status = lsfilesToState(line[0].toLatin1()); QUrl url = QUrl::fromLocalFile(dir.absoluteFilePath(line.right(line.size()-2))); allStatus[url] = status; } QVariantList statuses; QMap< QUrl, VcsStatusInfo::State >::const_iterator it = allStatus.constBegin(), itEnd=allStatus.constEnd(); for(; it!=itEnd; ++it) { VcsStatusInfo status; status.setUrl(it.key()); status.setState(it.value()); statuses.append(qVariantFromValue(status)); } job->setResults(statuses); } void GitPlugin::parseGitStatusOutput(DVcsJob* job) { QStringList outputLines = job->output().split('\n', QString::SkipEmptyParts); QDir workingDir = job->directory(); QDir dotGit = dotGitDirectory(QUrl::fromLocalFile(workingDir.absolutePath())); QVariantList statuses; QList processedFiles; foreach(const QString& line, outputLines) { //every line is 2 chars for the status, 1 space then the file desc QString curr=line.right(line.size()-3); QString state = line.left(2); int arrow = curr.indexOf(" -> "); if(arrow>=0) { VcsStatusInfo status; status.setUrl(QUrl::fromLocalFile(dotGit.absoluteFilePath(curr.left(arrow)))); status.setState(VcsStatusInfo::ItemDeleted); statuses.append(qVariantFromValue(status)); processedFiles += status.url(); curr = curr.mid(arrow+4); } if(curr.startsWith('\"') && curr.endsWith('\"')) { //if the path is quoted, unquote curr = curr.mid(1, curr.size()-2); } VcsStatusInfo status; status.setUrl(QUrl::fromLocalFile(dotGit.absoluteFilePath(curr))); status.setState(messageToState(state)); processedFiles.append(status.url()); qCDebug(PLUGIN_GIT) << "Checking git status for " << line << curr << messageToState(state); statuses.append(qVariantFromValue(status)); } QStringList paths; QStringList oldcmd=job->dvcsCommand(); QStringList::const_iterator it=oldcmd.constBegin()+oldcmd.indexOf("--")+1, itEnd=oldcmd.constEnd(); for(; it!=itEnd; ++it) paths += *it; //here we add the already up to date files QStringList files = getLsFiles(job->directory(), QStringList() << "-c" << "--" << paths, OutputJob::Silent); foreach(const QString& file, files) { QUrl fileUrl = QUrl::fromLocalFile(workingDir.absoluteFilePath(file)); if(!processedFiles.contains(fileUrl)) { VcsStatusInfo status; status.setUrl(fileUrl); status.setState(VcsStatusInfo::ItemUpToDate); statuses.append(qVariantFromValue(status)); } } job->setResults(statuses); } void GitPlugin::parseGitVersionOutput(DVcsJob* job) { QStringList versionString = job->output().trimmed().split(' ').last().split('.'); static const QList minimumVersion = QList() << 1 << 7; qCDebug(PLUGIN_GIT) << "checking git version" << versionString << "against" << minimumVersion; m_oldVersion = false; if (versionString.size() < minimumVersion.size()) { m_oldVersion = true; qCWarning(PLUGIN_GIT) << "invalid git version string:" << job->output().trimmed(); return; } foreach(int num, minimumVersion) { QString curr = versionString.takeFirst(); int valcurr = curr.toInt(); if (valcurr < num) { m_oldVersion = true; break; } if (valcurr > num) { m_oldVersion = false; break; } } qCDebug(PLUGIN_GIT) << "the current git version is old: " << m_oldVersion; } QStringList GitPlugin::getLsFiles(const QDir &directory, const QStringList &args, KDevelop::OutputJob::OutputJobVerbosity verbosity) { QScopedPointer job(lsFiles(directory, args, verbosity)); if (job->exec() && job->status() == KDevelop::VcsJob::JobSucceeded) return job->output().split('\n', QString::SkipEmptyParts); return QStringList(); } DVcsJob* GitPlugin::gitRevParse(const QString &repository, const QStringList &args, KDevelop::OutputJob::OutputJobVerbosity verbosity) { DVcsJob* job = new DVcsJob(QDir(repository), this, verbosity); *job << "git" << "rev-parse" << args; return job; } DVcsJob* GitPlugin::gitRevList(const QString& directory, const QStringList& args) { DVcsJob* job = new DVcsJob(urlDir(QUrl::fromLocalFile(directory)), this, KDevelop::OutputJob::Silent); { *job << "git" << "rev-list" << args; return job; } } VcsStatusInfo::State GitPlugin::messageToState(const QString& msg) { Q_ASSERT(msg.size()==1 || msg.size()==2); VcsStatusInfo::State ret = VcsStatusInfo::ItemUnknown; if(msg.contains('U') || msg == "AA" || msg == "DD") ret = VcsStatusInfo::ItemHasConflicts; else switch(msg[0].toLatin1()) { case 'M': ret = VcsStatusInfo::ItemModified; break; case 'A': ret = VcsStatusInfo::ItemAdded; break; case 'R': ret = VcsStatusInfo::ItemModified; break; case 'C': ret = VcsStatusInfo::ItemHasConflicts; break; case ' ': ret = msg[1] == 'M' ? VcsStatusInfo::ItemModified : VcsStatusInfo::ItemDeleted; break; case 'D': ret = VcsStatusInfo::ItemDeleted; break; case '?': ret = VcsStatusInfo::ItemUnknown; break; default: qCDebug(PLUGIN_GIT) << "Git status not identified:" << msg; break; } return ret; } StandardJob::StandardJob(IPlugin* parent, KJob* job, OutputJob::OutputJobVerbosity verbosity) : VcsJob(parent, verbosity) , m_job(job) , m_plugin(parent) , m_status(JobNotStarted) {} void StandardJob::start() { connect(m_job, &KJob::result, this, &StandardJob::result); m_job->start(); m_status=JobRunning; } void StandardJob::result(KJob* job) { m_status=job->error() == 0? JobSucceeded : JobFailed; emitResult(); } VcsJob* GitPlugin::copy(const QUrl& localLocationSrc, const QUrl& localLocationDstn) { //TODO: Probably we should "git add" after return new StandardJob(this, KIO::copy(localLocationSrc, localLocationDstn), KDevelop::OutputJob::Silent); } VcsJob* GitPlugin::move(const QUrl& source, const QUrl& destination) { QDir dir = urlDir(source); QFileInfo fileInfo(source.toLocalFile()); if (fileInfo.isDir()) { if (isEmptyDirStructure(QDir(source.toLocalFile()))) { //move empty folder, git doesn't do that qCDebug(PLUGIN_GIT) << "empty folder" << source; return new StandardJob(this, KIO::move(source, destination), KDevelop::OutputJob::Silent); } } QStringList otherStr = getLsFiles(dir, QStringList() << "--others" << "--" << source.toLocalFile(), KDevelop::OutputJob::Silent); if(otherStr.isEmpty()) { DVcsJob* job = new DVcsJob(dir, this, KDevelop::OutputJob::Verbose); *job << "git" << "mv" << source.toLocalFile() << destination.toLocalFile(); return job; } else { return new StandardJob(this, KIO::move(source, destination), KDevelop::OutputJob::Silent); } } void GitPlugin::parseGitRepoLocationOutput(DVcsJob* job) { job->setResults(QVariant::fromValue(QUrl::fromLocalFile(job->output()))); } VcsJob* GitPlugin::repositoryLocation(const QUrl& localLocation) { DVcsJob* job = new DVcsJob(urlDir(localLocation), this); //Probably we should check first if origin is the proper remote we have to use but as a first attempt it works *job << "git" << "config" << "remote.origin.url"; connect(job, &DVcsJob::readyForParsing, this, &GitPlugin::parseGitRepoLocationOutput); return job; } VcsJob* GitPlugin::pull(const KDevelop::VcsLocation& localOrRepoLocationSrc, const QUrl& localRepositoryLocation) { DVcsJob* job = new DVcsJob(urlDir(localRepositoryLocation), this); job->setCommunicationMode(KProcess::MergedChannels); *job << "git" << "-c" << "color.diff=false" << "pull"; if(!localOrRepoLocationSrc.localUrl().isEmpty()) *job << localOrRepoLocationSrc.localUrl().url(); return job; } VcsJob* GitPlugin::push(const QUrl& localRepositoryLocation, const KDevelop::VcsLocation& localOrRepoLocationDst) { DVcsJob* job = new DVcsJob(urlDir(localRepositoryLocation), this); job->setCommunicationMode(KProcess::MergedChannels); *job << "git" << "push"; if(!localOrRepoLocationDst.localUrl().isEmpty()) *job << localOrRepoLocationDst.localUrl().url(); return job; } VcsJob* GitPlugin::resolve(const QList& localLocations, IBasicVersionControl::RecursionMode recursion) { return add(localLocations, recursion); } VcsJob* GitPlugin::update(const QList& localLocations, const KDevelop::VcsRevision& rev, IBasicVersionControl::RecursionMode recursion) { if(rev.revisionType()==VcsRevision::Special && rev.revisionValue().value()==VcsRevision::Head) { return pull(VcsLocation(), localLocations.first()); } else { DVcsJob* job = new DVcsJob(urlDir(localLocations.first()), this); { //Probably we should check first if origin is the proper remote we have to use but as a first attempt it works *job << "git" << "checkout" << rev.revisionValue().toString() << "--"; *job << (recursion == IBasicVersionControl::Recursive ? localLocations : preventRecursion(localLocations)); return job; } } } void GitPlugin::setupCommitMessageEditor(const QUrl& localLocation, KTextEdit* editor) const { new GitMessageHighlighter(editor); QFile mergeMsgFile(dotGitDirectory(localLocation).filePath(".git/MERGE_MSG")); // Some limit on the file size should be set since whole content is going to be read into // the memory. 1Mb seems to be good value since it's rather strange to have so huge commit // message. static const qint64 maxMergeMsgFileSize = 1024*1024; if (mergeMsgFile.size() > maxMergeMsgFileSize || !mergeMsgFile.open(QIODevice::ReadOnly)) return; QString mergeMsg = QString::fromLocal8Bit(mergeMsgFile.read(maxMergeMsgFileSize)); editor->setPlainText(mergeMsg); } class GitVcsLocationWidget : public KDevelop::StandardVcsLocationWidget { public: GitVcsLocationWidget(QWidget* parent = 0, Qt::WindowFlags f = 0) : StandardVcsLocationWidget(parent, f) {} - virtual bool isCorrect() const override + bool isCorrect() const override { return !url().isEmpty(); } }; KDevelop::VcsLocationWidget* GitPlugin::vcsLocation(QWidget* parent) const { 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); QString headFile = dir.absoluteFilePath(".git/HEAD"); m_watcher->addFile(headFile); } void GitPlugin::fileChanged(const QString& file) { Q_ASSERT(file.endsWith("HEAD")); //SMTH/.git/HEAD -> SMTH/ const QUrl fileUrl = Path(file).parent().parent().toUrl(); //We need to delay the emitted signal, otherwise the branch hasn't change yet //and the repository is not functional m_branchesChange.append(fileUrl); QTimer::singleShot(1000, this, SLOT(delayedBranchChanged())); } void GitPlugin::delayedBranchChanged() { emit repositoryBranchChanged(m_branchesChange.takeFirst()); } CheckInRepositoryJob* GitPlugin::isInRepository(KTextEditor::Document* document) { CheckInRepositoryJob* job = new GitPluginCheckInRepositoryJob(document, repositoryRoot(document->url()).path()); job->start(); return job; } DVcsJob* GitPlugin::setConfigOption(const QUrl& repository, const QString& key, const QString& value) { auto job = new DVcsJob(urlDir(repository), this); *job << "git" << "config" << key << value; return job; } diff --git a/plugins/git/gitplugin.h b/plugins/git/gitplugin.h index ad3c6cca0a..eaf9d19325 100644 --- a/plugins/git/gitplugin.h +++ b/plugins/git/gitplugin.h @@ -1,225 +1,225 @@ /*************************************************************************** * Copyright 2008 Evgeniy Ivanov * * Copyright 2009 Hugo Parente Lima * * * * 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_PLUGIN_GIT_PLUGIN_H #define KDEVPLATFORM_PLUGIN_GIT_PLUGIN_H #include #include #include #include #include #include #include #include class KDirWatch; class QDir; namespace KDevelop { class VcsJob; class VcsRevision; } class StandardJob : public KDevelop::VcsJob { Q_OBJECT public: StandardJob(KDevelop::IPlugin* parent, KJob* job, OutputJobVerbosity verbosity); - virtual QVariant fetchResults() override { return QVariant(); } - virtual void start() override; - virtual JobStatus status() const override { return m_status; } - virtual KDevelop::IPlugin* vcsPlugin() const override { return m_plugin; } + QVariant fetchResults() override { return QVariant(); } + void start() override; + JobStatus status() const override { return m_status; } + KDevelop::IPlugin* vcsPlugin() const override { return m_plugin; } public slots: void result(KJob*); private: KJob* m_job; KDevelop::IPlugin* m_plugin; JobStatus m_status; }; /** * This is the main class of KDevelop's Git plugin. * * It implements the DVCS dependent things not implemented in KDevelop::DistributedVersionControlPlugin * @author Evgeniy Ivanov */ class GitPlugin: public KDevelop::DistributedVersionControlPlugin, public KDevelop::IContentAwareVersionControl { Q_OBJECT Q_INTERFACES(KDevelop::IBasicVersionControl KDevelop::IDistributedVersionControl KDevelop::IContentAwareVersionControl) friend class GitInitTest; public: explicit GitPlugin(QObject *parent, const QVariantList & args = QVariantList() ); - ~GitPlugin(); + ~GitPlugin() override; QString name() const override; bool isVersionControlled(const QUrl &path) override; - virtual KDevelop::VcsJob* copy(const QUrl& localLocationSrc, const QUrl& localLocationDstn) override; - virtual KDevelop::VcsJob* move(const QUrl& localLocationSrc, const QUrl& localLocationDst) override; + KDevelop::VcsJob* copy(const QUrl& localLocationSrc, const QUrl& localLocationDstn) override; + KDevelop::VcsJob* move(const QUrl& localLocationSrc, const QUrl& localLocationDst) override; //TODO - virtual KDevelop::VcsJob* pull(const KDevelop::VcsLocation& localOrRepoLocationSrc, const QUrl& localRepositoryLocation) override; - virtual KDevelop::VcsJob* push(const QUrl& localRepositoryLocation, const KDevelop::VcsLocation& localOrRepoLocationDst) override; - virtual KDevelop::VcsJob* repositoryLocation(const QUrl& localLocation) override; - virtual KDevelop::VcsJob* resolve(const QList& localLocations, RecursionMode recursion) override; - virtual KDevelop::VcsJob* update(const QList& localLocations, const KDevelop::VcsRevision& rev, RecursionMode recursion) override; + KDevelop::VcsJob* pull(const KDevelop::VcsLocation& localOrRepoLocationSrc, const QUrl& localRepositoryLocation) override; + KDevelop::VcsJob* push(const QUrl& localRepositoryLocation, const KDevelop::VcsLocation& localOrRepoLocationDst) override; + KDevelop::VcsJob* repositoryLocation(const QUrl& localLocation) override; + KDevelop::VcsJob* resolve(const QList& localLocations, RecursionMode recursion) override; + KDevelop::VcsJob* update(const QList& localLocations, const KDevelop::VcsRevision& rev, RecursionMode recursion) override; KDevelop::VcsLocationWidget* vcsLocation(QWidget* parent) const override; - virtual void setupCommitMessageEditor(const QUrl& localLocation, KTextEdit* editor) const override; + void setupCommitMessageEditor(const QUrl& localLocation, KTextEdit* editor) const override; //End of KDevelop::VcsJob* add(const QList& localLocations, KDevelop::IBasicVersionControl::RecursionMode recursion = KDevelop::IBasicVersionControl::Recursive) override; KDevelop::VcsJob* createWorkingCopy(const KDevelop::VcsLocation & localOrRepoLocationSrc, const QUrl& localRepositoryRoot, KDevelop::IBasicVersionControl::RecursionMode) override; KDevelop::VcsJob* remove(const QList& files) override; KDevelop::VcsJob* status(const QList& localLocations, 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; - virtual KDevelop::VcsJob* diff(const QUrl& fileOrDirectory, const KDevelop::VcsRevision& srcRevision, const KDevelop::VcsRevision& dstRevision, + KDevelop::VcsJob* diff(const QUrl& fileOrDirectory, const KDevelop::VcsRevision& srcRevision, const KDevelop::VcsRevision& dstRevision, KDevelop::VcsDiff::Type, RecursionMode recursion) override; - virtual KDevelop::VcsJob* log( const QUrl& localLocation, const KDevelop::VcsRevision& rev, unsigned long limit) override; - virtual KDevelop::VcsJob* log(const QUrl& localLocation, const KDevelop::VcsRevision& rev, const KDevelop::VcsRevision& limit) override; + KDevelop::VcsJob* log( const QUrl& localLocation, const KDevelop::VcsRevision& rev, unsigned long limit) override; + KDevelop::VcsJob* log(const QUrl& localLocation, const KDevelop::VcsRevision& rev, const KDevelop::VcsRevision& limit) override; KDevelop::VcsJob* annotate(const QUrl &localLocation, const KDevelop::VcsRevision &rev) override; KDevelop::VcsJob* revert(const QList& localLocations, RecursionMode recursion) override; // Begin: KDevelop::IDistributedVersionControl KDevelop::VcsJob* init(const QUrl & directory) override; // Branch management KDevelop::VcsJob* tag(const QUrl& repository, const QString& commitMessage, const KDevelop::VcsRevision& rev, const QString& tagName) override; KDevelop::VcsJob* branch(const QUrl& repository, const KDevelop::VcsRevision& rev, const QString& branchName) override; KDevelop::VcsJob* branches(const QUrl& repository) override; KDevelop::VcsJob* currentBranch(const QUrl& repository) override; KDevelop::VcsJob* deleteBranch(const QUrl& repository, const QString& branchName) override; KDevelop::VcsJob* switchBranch(const QUrl& repository, const QString& branchName) override; KDevelop::VcsJob* renameBranch(const QUrl& repository, const QString& oldBranchName, const QString& newBranchName) override; //graph helpers QList getAllCommits(const QString &repo) override; //used in log void parseLogOutput(const KDevelop::DVcsJob * job, QList& commits) const override; - virtual void additionalMenuEntries(QMenu* menu, const QList& urls) override; + void additionalMenuEntries(QMenu* menu, const QList& urls) override; KDevelop::DVcsJob* gitStash(const QDir& repository, const QStringList& args, KDevelop::OutputJob::OutputJobVerbosity verbosity); bool hasStashes(const QDir& repository); bool hasModifications(const QDir& repository); bool hasModifications(const QDir& repo, const QUrl& file); - virtual bool hasError() const override; - virtual QString errorDescription() const override; - virtual void registerRepositoryForCurrentBranchChanges(const QUrl& repository) override; + bool hasError() const override; + QString errorDescription() const override; + void registerRepositoryForCurrentBranchChanges(const QUrl& repository) override; KDevelop::CheckInRepositoryJob* isInRepository(KTextEditor::Document* document) override; KDevelop::DVcsJob* setConfigOption(const QUrl& repository, const QString& key, const QString& value); // this indicates whether the diff() function will generate a diff (patch) which // includes the working copy directory name or not (in which case git diff is called // with --no-prefix). bool usePrefix() const { return m_usePrefix; } void setUsePrefix(bool p) { m_usePrefix = p; } protected: QUrl repositoryRoot(const QUrl& path); bool isValidDirectory(const QUrl &dirPath) override; KDevelop::DVcsJob* lsFiles(const QDir &repository, const QStringList &args, KDevelop::OutputJob::OutputJobVerbosity verbosity = KDevelop::OutputJob::Verbose); KDevelop::DVcsJob* gitRevList(const QString &directory, const QStringList &args); KDevelop::DVcsJob* gitRevParse(const QString &repository, const QStringList &args, KDevelop::OutputJob::OutputJobVerbosity verbosity = KDevelop::OutputJob::Silent); private slots: void parseGitBlameOutput(KDevelop::DVcsJob *job); void parseGitLogOutput(KDevelop::DVcsJob *job); void parseGitDiffOutput(KDevelop::DVcsJob* job); void parseGitRepoLocationOutput(KDevelop::DVcsJob* job); void parseGitStatusOutput(KDevelop::DVcsJob* job); void parseGitStatusOutput_old(KDevelop::DVcsJob* job); void parseGitVersionOutput(KDevelop::DVcsJob* job); void parseGitBranchOutput(KDevelop::DVcsJob* job); void parseGitCurrentBranch(KDevelop::DVcsJob* job); void ctxPushStash(); void ctxPopStash(); void ctxStashManager(); void fileChanged(const QString& file); void delayedBranchChanged(); signals: void repositoryBranchChanged(const QUrl& repository); private: void addNotVersionedFiles(const QDir& dir, const QList& files); //commit dialog "main" helper QStringList getLsFiles(const QDir &directory, const QStringList &args, KDevelop::OutputJob::OutputJobVerbosity verbosity); KDevelop::DVcsJob* errorsFound(const QString& error, KDevelop::OutputJob::OutputJobVerbosity verbosity); void initBranchHash(const QString &repo); static KDevelop::VcsStatusInfo::State messageToState(const QString& ch); QList branchesShas; QList m_urls; /** 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; }; QVariant runSynchronously(KDevelop::VcsJob* job); #endif diff --git a/plugins/git/gitplugincheckinrepositoryjob.h b/plugins/git/gitplugincheckinrepositoryjob.h index 34370be202..b5f8f11d60 100644 --- a/plugins/git/gitplugincheckinrepositoryjob.h +++ b/plugins/git/gitplugincheckinrepositoryjob.h @@ -1,45 +1,45 @@ /*************************************************************************** * Copyright 2014 Sven Brauch * * * * 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 GITPLUGINCHECKINREPOSITORYJOB_H #define GITPLUGINCHECKINREPOSITORYJOB_H #include #include class GitPluginCheckInRepositoryJob : public KDevelop::CheckInRepositoryJob { Q_OBJECT public: GitPluginCheckInRepositoryJob(KTextEditor::Document* document, const QString& rootDirectory); - virtual ~GitPluginCheckInRepositoryJob(); - virtual void start() override; + ~GitPluginCheckInRepositoryJob() override; + void start() override; private slots: void repositoryQueryFinished(int); void processFailed(QProcess::ProcessError); private: QProcess* m_hashjob; QProcess* m_findjob; QString m_rootDirectory; }; #endif // GITPLUGINCHECKINREPOSITORYJOB_H diff --git a/plugins/git/stashmanagerdialog.h b/plugins/git/stashmanagerdialog.h index 1d39c60977..7aaa8c9b95 100644 --- a/plugins/git/stashmanagerdialog.h +++ b/plugins/git/stashmanagerdialog.h @@ -1,68 +1,68 @@ /* * This file is part of KDevelop * Copyright 2010 Aleix Pol Gonzalez * * 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. */ #ifndef KDEVPLATFORM_PLUGIN_STASHMANAGERDIALOG_H #define KDEVPLATFORM_PLUGIN_STASHMANAGERDIALOG_H #include #include #include class KJob; namespace Ui { class StashManager; } class GitPlugin; class StashManagerDialog : public QDialog { Q_OBJECT public: explicit StashManagerDialog(const QDir& stashed, GitPlugin* plugin, QWidget* parent); - virtual ~StashManagerDialog(); + ~StashManagerDialog() override; public slots: void showStash(); void applyClicked(); void branchClicked(); void popClicked(); void dropClicked(); void stashesFound(); private: QString selection() const; void runStash(const QStringList& arguments); Ui::StashManager* m_ui; QWidget* m_mainWidget; GitPlugin* m_plugin; QDir m_dir; }; class StashModel : public QStandardItemModel { Q_OBJECT public: explicit StashModel(const QDir& dir, GitPlugin* git, QObject* parent = 0); private slots: void stashListReady(KJob*); }; #endif // KDEVPLATFORM_PLUGIN_STASHMANAGERDIALOG_H diff --git a/plugins/git/stashpatchsource.h b/plugins/git/stashpatchsource.h index e0a2ccf556..5e8ac87650 100644 --- a/plugins/git/stashpatchsource.h +++ b/plugins/git/stashpatchsource.h @@ -1,60 +1,60 @@ /* * * Copyright (C) 2013 David E. Narvaez * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #ifndef STASHPATCHSOURCE_H #define STASHPATCHSOURCE_H #include #include namespace KDevelop { class VcsJob; } class GitPlugin; class StashPatchSource : public KDevelop::IPatchSource { Q_OBJECT public: StashPatchSource(const QString & stashName, GitPlugin * patch, const QDir & baseDir); - virtual ~StashPatchSource(); - virtual QUrl baseDir() const override; - virtual QUrl file() const override; - virtual void update() override; - virtual bool isAlreadyApplied() const override; - virtual QString name() const override; - virtual bool canSelectFiles() const override { return true; }; - virtual uint depth() const override { return 1; } + ~StashPatchSource() override; + QUrl baseDir() const override; + QUrl file() const override; + void update() override; + bool isAlreadyApplied() const override; + QString name() const override; + bool canSelectFiles() const override { return true; }; + uint depth() const override { return 1; } private slots: void updatePatchFile(KDevelop::VcsJob* job); private: QString m_stashName; GitPlugin * m_plugin; QDir m_baseDir; QUrl m_patchFile; }; #endif // STASHPATCHSOURCE_H diff --git a/plugins/grepview/grepdialog.h b/plugins/grepview/grepdialog.h index 9a8a89419d..741146ba23 100644 --- a/plugins/grepview/grepdialog.h +++ b/plugins/grepview/grepdialog.h @@ -1,80 +1,80 @@ /*************************************************************************** * Copyright 1999-2001 by Bernd Gehrmann and the KDevelop Team * * bernd@kdevelop.org * * Copyright 2007 Dukju Ahn * * Copyright 2010 Julien Desgats * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_GREPDIALOG_H #define KDEVPLATFORM_PLUGIN_GREPDIALOG_H #include #include #include "ui_grepwidget.h" class KConfig; class KUrlRequester; class GrepViewPlugin; class QLineEdit; class GrepDialog : public QDialog, private Ui::GrepWidget { Q_OBJECT public: explicit GrepDialog( GrepViewPlugin * plugin, QWidget *parent=0 ); - ~GrepDialog(); + ~GrepDialog() override; void setPattern(const QString &pattern); void setEnableProjectBox(bool enable); QString patternString() const; QString templateString() const; QString replacementTemplateString() const; QString filesString() const; QString excludeString() const; bool useProjectFilesFlag() const; bool regexpFlag() const; bool caseSensitiveFlag() const; int depthValue() const; public Q_SLOTS: void startSearch(); ///Sets directory(ies)/files to search in. Also it can be semicolon separated list of directories/files or one of special strings: allOpenFilesString, allOpenProjectsString void setSearchLocations(const QString &dir); private Q_SLOTS: void templateTypeComboActivated(int); void patternComboEditTextChanged( const QString& ); void directoryChanged(const QString &dir); QMenu* createSyncButtonMenu(); void addUrlToMenu(QMenu* ret, const QUrl& url); void addStringToMenu(QMenu* ret, QString string); void synchronizeDirActionTriggered(bool); ///Opens the dialog to select a directory to search in, and inserts it into Location(s) field. void selectDirectoryDialog(); private: // Returns the chosen directories or files (only the top directories, not subfiles) QList< QUrl > getDirectoryChoice() const; // Returns whether the given url is a subfile/subdirectory of one of the chosen directories/files // This is slow, so don't call it too often bool isPartOfChoice(QUrl url) const; GrepViewPlugin * m_plugin; }; #endif diff --git a/plugins/grepview/grepjob.h b/plugins/grepview/grepjob.h index 9bae807421..7a12eb4264 100644 --- a/plugins/grepview/grepjob.h +++ b/plugins/grepview/grepjob.h @@ -1,123 +1,123 @@ /*************************************************************************** * Copyright 1999-2001 by Bernd Gehrmann * * bernd@kdevelop.org * * Copyright 2008 by Hamish Rodda * * rodda@kde.org * * Copyright 2010 Silvère Lestang * * Copyright 2010 Julien Desgats * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_GREPJOB_H #define KDEVPLATFORM_PLUGIN_GREPJOB_H #include #include #include #include #include "grepfindthread.h" #include "grepoutputmodel.h" namespace KDevelop { class IProject; class ProcessLineMaker; } class QRegExp; class GrepViewPlugin; class FindReplaceTest; //FIXME: this is useful only for tests class GrepJob : public KJob, public KDevelop::IStatus { Q_OBJECT Q_INTERFACES( KDevelop::IStatus ) friend class GrepViewPlugin; friend class FindReplaceTest; private: ///Job can only be instanciated by plugin explicit GrepJob( QObject *parent = 0 ); public: void setOutputModel(GrepOutputModel * model); void setPatternString(const QString& patternString); void setTemplateString(const QString &templateString); void setReplacementTemplateString(const QString &replTmplString); void setFilesString(const QString &filesString); void setExcludeString(const QString &excludeString); void setDirectoryChoice(const QList &choice); void setDepth(int depth); void setRegexpFlag(bool regexpFlag); void setCaseSensitive(bool caseSensitive); void setProjectFilesFlag(bool projectFilesFlag); - virtual void start() override; + void start() override; - virtual QString statusName() const override; + QString statusName() const override; protected: - virtual bool doKill() override; + bool doKill() override; // GrepOutputModel* model() const; private Q_SLOTS: void slotFindFinished(); void testFinishState(KJob *job); Q_SIGNALS: void clearMessage( KDevelop::IStatus* ) override; void showMessage( KDevelop::IStatus*, const QString & message, int timeout = 0) override; void showErrorMessage(const QString & message, int timeout = 0) override; void hideProgress( KDevelop::IStatus* ) override; void showProgress( KDevelop::IStatus*, int minimum, int maximum, int value) override; void foundMatches( const QString& filename, const GrepOutputItem::List& matches); private: Q_INVOKABLE void slotWork(); QString m_patternString; QRegExp m_regExp; QString m_regExpSimple; GrepOutputModel *m_outputModel; enum { WorkCollectFiles, WorkGrep, WorkIdle, WorkCancelled } m_workState; QList m_fileList; int m_fileIndex; QPointer m_findThread; QString m_errorMessage; QString m_templateString; QString m_replacementTemplateString; QString m_filesString; QString m_excludeString; QList m_directoryChoice; bool m_useProjectFilesFlag; bool m_regexpFlag; bool m_caseSensitiveFlag; int m_depthValue; bool m_findSomething; }; //FIXME: this function is used externally only for tests, find a way to keep it // static for a regular compilation GrepOutputItem::List grepFile(const QString &filename, const QRegExp &re); #endif diff --git a/plugins/grepview/grepoutputmodel.h b/plugins/grepview/grepoutputmodel.h index e699f79220..46450a33e2 100644 --- a/plugins/grepview/grepoutputmodel.h +++ b/plugins/grepview/grepoutputmodel.h @@ -1,112 +1,112 @@ /*************************************************************************** * Copyright 1999-2001 Bernd Gehrmann and the KDevelop Team * * bernd@kdevelop.org * * Copyright 2007 Dukju Ahn * * Copyright 2010 Silvère Lestang * * Copyright 2010 Julien Desgats * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_GREPOUTPUTMODEL_H #define KDEVPLATFORM_PLUGIN_GREPOUTPUTMODEL_H #include #include #include class QModelIndex; class QRegExp; namespace KDevelop { class IStatus; } class GrepOutputItem : public QStandardItem { public: typedef QList List; GrepOutputItem(KDevelop::DocumentChangePointer change, const QString& text, bool checkable); GrepOutputItem(const QString &filename, const QString &text, bool checkable); - ~GrepOutputItem(); + ~GrepOutputItem() override; QString filename() const ; int lineNumber() const ; KDevelop::DocumentChangePointer change() const ; bool isText() const ; /// Recursively apply check state to children void propagateState() ; /// Check children to determine current state void refreshState() ; - virtual QVariant data ( int role = Qt::UserRole + 1 ) const override; + QVariant data ( int role = Qt::UserRole + 1 ) const override; private: KDevelop::DocumentChangePointer m_change; }; Q_DECLARE_METATYPE(GrepOutputItem::List) class GrepOutputModel : public QStandardItemModel { Q_OBJECT public: explicit GrepOutputModel( QObject *parent = 0 ); - ~GrepOutputModel(); + ~GrepOutputModel() override; void setRegExp(const QRegExp& re); void setReplacementTemplate(const QString &tmpl); /// applies replacement on given text QString replacementFor(const QString &text); void clear(); // resets file & match counts bool hasResults(); QModelIndex previousItemIndex(const QModelIndex ¤tIdx) const; QModelIndex nextItemIndex(const QModelIndex ¤tIdx) const; const GrepOutputItem *getRootItem() const; void makeItemsCheckable(bool checkable); bool itemsCheckable() const; public Q_SLOTS: void appendOutputs( const QString &filename, const GrepOutputItem::List &lines ); void activate( const QModelIndex &idx ); void doReplacements(); void setReplacement(const QString &repl); //receive status message from GrepJob, and store it void showMessageSlot( KDevelop::IStatus*, const QString& message ); //emit stored message as signal 'showMessage' to GrepOutputView. //called when user selects a search with the combobox void showMessageEmit(); Q_SIGNALS: void showMessage( KDevelop::IStatus*, const QString& message ); void showErrorMessage(const QString & message, int timeout = 0); private: void makeItemsCheckable(bool checkable, GrepOutputItem* item); QRegExp m_regExp; QString m_replacement; QString m_replacementTemplate; QString m_finalReplacement; bool m_finalUpToDate; /// says if m_finalReplacement is up to date or must be regenerated GrepOutputItem *m_rootItem; int m_fileCount; int m_matchCount; QString m_savedMessage; KDevelop::IStatus *m_savedIStatus; bool m_itemsCheckable; private slots: void updateCheckState(QStandardItem*); }; #endif diff --git a/plugins/grepview/grepoutputview.h b/plugins/grepview/grepoutputview.h index 5e8995a469..9b7d4fca50 100644 --- a/plugins/grepview/grepoutputview.h +++ b/plugins/grepview/grepoutputview.h @@ -1,101 +1,101 @@ /************************************************************************** * Copyright 2010 Silvère Lestang * * Copyright 2010 Julien Desgats * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_GREPOUTPUTVIEW_H #define KDEVPLATFORM_PLUGIN_GREPOUTPUTVIEW_H #include #include #include "ui_grepoutputview.h" namespace KDevelop { class IStatus; } class QModelIndex; class GrepViewPlugin; class GrepOutputModel; class GrepOutputDelegate; class GrepOutputViewFactory: public KDevelop::IToolViewFactory { public: explicit GrepOutputViewFactory(GrepViewPlugin* plugin); - virtual QWidget* create(QWidget* parent = 0) override; - virtual Qt::DockWidgetArea defaultPosition() override; - virtual QString id() const override; + QWidget* create(QWidget* parent = 0) override; + Qt::DockWidgetArea defaultPosition() override; + QString id() const override; private: GrepViewPlugin* m_plugin; }; class GrepOutputView : public QWidget, Ui::GrepOutputView, public KDevelop::IToolViewActionListener { Q_OBJECT Q_INTERFACES(KDevelop::IToolViewActionListener) public: enum MessageType { Information, Error }; GrepOutputView(QWidget* parent, GrepViewPlugin* plugin); - ~GrepOutputView(); + ~GrepOutputView() override; GrepOutputModel* model(); /** * This causes the creation of a new model, the old one is kept in model history. * Oldest models are deleted if needed. * @return pointer to the new model */ GrepOutputModel* renewModel(const QString& name, const QString& description); void setMessage(const QString& msg, MessageType type = Information); public Q_SLOTS: void showErrorMessage( const QString& errorMessage ); void showMessage( KDevelop::IStatus*, const QString& message ); void updateApplyState(const QModelIndex &topLeft, const QModelIndex &bottomRight); void changeModel(int index); void replacementTextChanged(QString); Q_SIGNALS: void outputViewIsClosed(); private: static const int HISTORY_SIZE; QAction* m_next; QAction* m_prev; QAction* m_collapseAll; QAction* m_expandAll; QAction* m_clearSearchHistory; QLabel* m_statusLabel; GrepViewPlugin *m_plugin; private slots: void selectPreviousItem() override; void selectNextItem() override; void collapseAllItems(); void expandAllItems(); void onApply(); void showDialog(); void expandElements( const QModelIndex & parent ); void rowsRemoved(); void clearSearchHistory(); void modelSelectorContextMenu(const QPoint& pos); void updateScrollArea(); void updateCheckable(); }; #endif // KDEVPLATFORM_PLUGIN_GREPOUTPUTVIEW_H diff --git a/plugins/grepview/grepviewplugin.h b/plugins/grepview/grepviewplugin.h index 0beb49f187..61ae56a491 100644 --- a/plugins/grepview/grepviewplugin.h +++ b/plugins/grepview/grepviewplugin.h @@ -1,67 +1,67 @@ /*************************************************************************** * Copyright 1999-2001 by Bernd Gehrmann * * bernd@kdevelop.org * * Copyright 2010 Julien Desgats * * * * 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. * * * ***************************************************************************/ #ifndef GREPVIEWPART_H_ #define GREPVIEWPART_H_ #include #include #include class KJob; class GrepJob; class GrepOutputViewFactory; class GrepViewPlugin : public KDevelop::IPlugin { Q_OBJECT public: explicit GrepViewPlugin( QObject *parent, const QVariantList & = QVariantList() ); - ~GrepViewPlugin(); - virtual void unload() override; + ~GrepViewPlugin() override; + void unload() override; void rememberSearchDirectory(QString const & directory); - virtual KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; + KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; void showDialog(bool setLastUsed = false, QString pattern = QString(), bool showOptions = true); /** * Returns a new instance of GrepJob. Since the plugin supports only one job at the same time, * previous job, if any, is killed before creating a new job. */ GrepJob *newGrepJob(); GrepJob *grepJob(); GrepOutputViewFactory* toolViewFactory() const; public Q_SLOTS: ///@param pattern the pattern to search ///@param directory the directory, or a semicolon-separated list of files ///@param showDIalog whether the search dialog should be shown. if false, /// the parameters of the last search will be used. Q_SCRIPTABLE void startSearch(QString pattern, QString directory, bool showOptions); Q_SIGNALS: Q_SIGNAL void grepJobFinished(); private Q_SLOTS: void showDialogFromMenu(); void showDialogFromProject(); void jobFinished(KJob *job); private: GrepJob *m_currentJob; QString m_directory; QString m_contextMenuDirectory; GrepOutputViewFactory* m_factory; }; #endif diff --git a/plugins/konsole/kdevkonsoleview.h b/plugins/konsole/kdevkonsoleview.h index 2f010dc942..378571e91f 100644 --- a/plugins/konsole/kdevkonsoleview.h +++ b/plugins/konsole/kdevkonsoleview.h @@ -1,41 +1,41 @@ /*************************************************************************** * Copyright 2003, 2006 Adam Treat * * Copyright 2007 Andreas Pakulat * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_KDEVKONSOLEVIEW_H #define KDEVPLATFORM_PLUGIN_KDEVKONSOLEVIEW_H #include #include class KDevKonsoleViewPlugin; class KDevKonsoleView : public QWidget { Q_OBJECT public: explicit KDevKonsoleView( KDevKonsoleViewPlugin* plugin, QWidget *parent = 0 ); - virtual ~KDevKonsoleView(); + ~KDevKonsoleView() override; public slots: void setDirectory( const QUrl &dirUrl ); protected: - virtual bool eventFilter( QObject *obj, QEvent *e ) override; + bool eventFilter( QObject *obj, QEvent *e ) override; private : class KDevKonsoleViewPrivate* const d; Q_PRIVATE_SLOT( d, void _k_slotTerminalClosed() ) }; #endif diff --git a/plugins/konsole/kdevkonsoleviewplugin.cpp b/plugins/konsole/kdevkonsoleviewplugin.cpp index 97592c9aac..229f114958 100644 --- a/plugins/konsole/kdevkonsoleviewplugin.cpp +++ b/plugins/konsole/kdevkonsoleviewplugin.cpp @@ -1,97 +1,97 @@ /*************************************************************************** * Copyright 2003, 2006 Adam Treat * * Copyright 2007 Andreas Pakulat * * * * 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. * * * ***************************************************************************/ #include "kdevkonsoleviewplugin.h" #include #include #include #include #include "kdevkonsoleview.h" #include "debug.h" Q_LOGGING_CATEGORY(PLUGIN_KONSOLE, "kdevplatform.plugins.konsole") QObject* createKonsoleView( QWidget*, QObject* op, const QVariantList& args) { KService::Ptr service = KService::serviceByDesktopName("konsolepart"); KPluginFactory* factory = nullptr; if (service) { factory = KPluginLoader(*service.data()).factory(); } if (!factory) { qWarning() << "Failed to load 'konsolepart' plugin"; } return new KDevKonsoleViewPlugin(factory, op, args); } K_PLUGIN_FACTORY_WITH_JSON(KonsoleViewFactory, "kdevkonsoleview.json", registerPlugin( QString(), &createKonsoleView );) class KDevKonsoleViewFactory: public KDevelop::IToolViewFactory{ public: KDevKonsoleViewFactory(KDevKonsoleViewPlugin *plugin): mplugin(plugin) {} - virtual QWidget* create(QWidget *parent = 0) override + QWidget* create(QWidget *parent = 0) override { return new KDevKonsoleView(mplugin, parent); } - virtual Qt::DockWidgetArea defaultPosition() override + Qt::DockWidgetArea defaultPosition() override { return Qt::BottomDockWidgetArea; } - virtual QString id() const override + QString id() const override { return "org.kdevelop.KonsoleView"; } private: KDevKonsoleViewPlugin *mplugin; }; KDevKonsoleViewPlugin::KDevKonsoleViewPlugin( KPluginFactory* konsoleFactory, QObject *parent, const QVariantList & ) : KDevelop::IPlugin( QStringLiteral("kdevkonsoleview"), parent ) , m_konsoleFactory(konsoleFactory) , m_viewFactory(konsoleFactory ? new KDevKonsoleViewFactory(this) : nullptr) { if (m_viewFactory) { core()->uiController()->addToolView("Konsole", m_viewFactory); } } void KDevKonsoleViewPlugin::unload() { if (m_viewFactory) { core()->uiController()->removeToolView(m_viewFactory); } } 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; } KDevKonsoleViewPlugin::~KDevKonsoleViewPlugin() { } #include "kdevkonsoleviewplugin.moc" diff --git a/plugins/konsole/kdevkonsoleviewplugin.h b/plugins/konsole/kdevkonsoleviewplugin.h index 319a15a5de..655fbf45e2 100644 --- a/plugins/konsole/kdevkonsoleviewplugin.h +++ b/plugins/konsole/kdevkonsoleviewplugin.h @@ -1,42 +1,42 @@ /*************************************************************************** * Copyright 2003, 2006 Adam Treat * * Copyright 2007 Andreas Pakulat * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_KDEVKONSOLEVIEWPLUGIN_H #define KDEVPLATFORM_PLUGIN_KDEVKONSOLEVIEWPLUGIN_H #include #include class KDevKonsoleViewFactory; class KPluginFactory; class KDevKonsoleViewPlugin : public KDevelop::IPlugin { Q_OBJECT public: KDevKonsoleViewPlugin( KPluginFactory*, QObject *parent, const QVariantList & = QVariantList() ); - virtual ~KDevKonsoleViewPlugin(); + ~KDevKonsoleViewPlugin() override; - virtual void unload() override; - virtual bool hasError() const override; - virtual QString errorDescription() const override; + void unload() override; + bool hasError() const override; + QString errorDescription() const override; KPluginFactory* konsoleFactory() const; private: KPluginFactory* m_konsoleFactory; KDevKonsoleViewFactory *m_viewFactory; }; #endif diff --git a/plugins/openwith/openwithplugin.h b/plugins/openwith/openwithplugin.h index 78e79c1e7e..c0242adf84 100644 --- a/plugins/openwith/openwithplugin.h +++ b/plugins/openwith/openwithplugin.h @@ -1,64 +1,64 @@ /* * This file is part of KDevelop * Copyright 2009 Andreas Pakulat * * 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. */ #ifndef KDEVPLATFORM_PLUGIN_OPENWITHPLUGIN_H #define KDEVPLATFORM_PLUGIN_OPENWITHPLUGIN_H #include #include #include #include "iopenwith.h" class QSignalMapper; namespace KDevelop { class ContextMenuExtension; class Context; } class OpenWithPlugin : public KDevelop::IPlugin, public KDevelop::IOpenWith { Q_OBJECT Q_INTERFACES( KDevelop::IOpenWith ) public: OpenWithPlugin( QObject* parent, const QVariantList& args ); - virtual ~OpenWithPlugin(); - virtual KDevelop::ContextMenuExtension contextMenuExtension ( KDevelop::Context* context ) override; + ~OpenWithPlugin() override; + KDevelop::ContextMenuExtension contextMenuExtension ( KDevelop::Context* context ) override; protected: - virtual void openFilesInternal( const QList& files ) override; + void openFilesInternal( const QList& files ) override; private slots: void open( const QString& storageId ); void openService( const KService::Ptr& service ); void openDefault(); private: QList actionsForServiceType( const QString& serviceType ); QScopedPointer m_actionMap; QList m_urls; QString m_mimeType; KService::List m_services; }; #endif // KDEVPLATFORM_PLUGIN_OPENWITHPLUGIN_H diff --git a/plugins/outlineview/outlinemodel.h b/plugins/outlineview/outlinemodel.h index 6253393160..988fd65765 100644 --- a/plugins/outlineview/outlinemodel.h +++ b/plugins/outlineview/outlinemodel.h @@ -1,62 +1,62 @@ /* * KDevelop outline view * Copyright 2010, 2015 Alex Richardson * * 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) 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include #include #include class OutlineNode; namespace KDevelop { class IDocument; class DUContext; class TopDUContext; class Declaration; class ParseJob; } class OutlineModel : public QAbstractItemModel { Q_OBJECT Q_DISABLE_COPY(OutlineModel) public: explicit OutlineModel(QObject* parent = 0); - virtual ~OutlineModel(); + ~OutlineModel() override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; int columnCount(const QModelIndex& parent = QModelIndex()) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; QModelIndex parent(const QModelIndex& child) const override; bool hasChildren(const QModelIndex& parent = QModelIndex()) const override; Qt::ItemFlags flags(const QModelIndex& index) const override; public slots: void activate(const QModelIndex& realIndex); private slots: void onParseJobFinished(KDevelop::ParseJob* job); void rebuildOutline(KDevelop::IDocument* doc); private: std::unique_ptr m_rootNode; KDevelop::IDocument* m_lastDoc; KDevelop::IndexedString m_lastUrl; }; diff --git a/plugins/outlineview/outlineviewplugin.h b/plugins/outlineview/outlineviewplugin.h index 96fdc39f6c..c902e846a8 100644 --- a/plugins/outlineview/outlineviewplugin.h +++ b/plugins/outlineview/outlineviewplugin.h @@ -1,42 +1,42 @@ /* * KDevelop outline view * Copyright 2010, 2015 Alex Richardson * * 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) 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include namespace KDevelop { class Declaration; } class OutlineViewPlugin : public KDevelop::IPlugin { Q_OBJECT public: explicit OutlineViewPlugin(QObject *parent, const QVariantList& args = QVariantList()); - virtual ~OutlineViewPlugin(); + ~OutlineViewPlugin() override; public: // KDevelop::Plugin overrides void unload() override; private: class OutlineViewFactory* m_factory; Q_DISABLE_COPY(OutlineViewPlugin) }; diff --git a/plugins/outlineview/outlinewidget.h b/plugins/outlineview/outlinewidget.h index c7dd510738..e4b32671da 100644 --- a/plugins/outlineview/outlinewidget.h +++ b/plugins/outlineview/outlinewidget.h @@ -1,51 +1,51 @@ /* * KDevelop outline view * Copyright 2010, 2015 Alex Richardson * * 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) 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 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #pragma once #include #include class KRecursiveFilterProxyModel; class QTreeView; class QPushButton; class QLineEdit; class OutlineModel; class OutlineViewPlugin; class OutlineWidget : public QWidget { Q_OBJECT public: OutlineWidget(QWidget* parent, OutlineViewPlugin* plugin); - virtual ~OutlineWidget(); + ~OutlineWidget() override; private: OutlineViewPlugin* m_plugin; OutlineModel* m_model; QTreeView* m_tree; KRecursiveFilterProxyModel* m_proxy; QLineEdit* m_filter; QPushButton* m_sortAlphabetically; Q_DISABLE_COPY(OutlineWidget) public slots: void activated(QModelIndex); void expandFirstLevel(); }; diff --git a/plugins/patchreview/localpatchsource.h b/plugins/patchreview/localpatchsource.h index 8d09199939..64cb20ff44 100644 --- a/plugins/patchreview/localpatchsource.h +++ b/plugins/patchreview/localpatchsource.h @@ -1,86 +1,86 @@ /*************************************************************************** Copyright 2006-2009 David Nolden ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_LOCALPATCHSOURCE_H #define KDEVPLATFORM_PLUGIN_LOCALPATCHSOURCE_H #include #include #include #include namespace Ui { class LocalPatchWidget; } class LocalPatchSource : public KDevelop::IPatchSource { Q_OBJECT friend class LocalPatchWidget; public: LocalPatchSource(); - virtual ~LocalPatchSource(); + ~LocalPatchSource() override; - virtual QString name() const override; + QString name() const override; - virtual QUrl baseDir() const override { + QUrl baseDir() const override { return m_baseDir; } - virtual QUrl file() const override { + QUrl file() const override { return m_filename; } - virtual uint depth() const override { + uint depth() const override { return m_depth; } - virtual void update() override; - virtual QIcon icon() const override; + void update() override; + QIcon icon() const override; void setFilename(const QUrl& filename) { m_filename = filename; } void setBaseDir(const QUrl& dir) { m_baseDir = dir; } void setCommand(const QString& cmd) { m_command = cmd; } QString command() const { return m_command; } - virtual bool isAlreadyApplied() const override { return m_applied; } + bool isAlreadyApplied() const override { return m_applied; } void setAlreadyApplied( bool applied ) { m_applied = applied; } - virtual QWidget* customWidget() const override; + QWidget* customWidget() const override; private: QUrl m_filename; QUrl m_baseDir; QString m_command; bool m_applied; uint m_depth; class LocalPatchWidget* m_widget; }; class LocalPatchWidget : public QWidget { Q_OBJECT public: LocalPatchWidget(LocalPatchSource* lpatch, QWidget* parent); public slots: void updatePatchFromEdit(); void syncPatch(); private: LocalPatchSource* m_lpatch; Ui::LocalPatchWidget* m_ui; }; #endif // KDEVPLATFORM_PLUGIN_LOCALPATCHSOURCE_H diff --git a/plugins/patchreview/patchhighlighter.h b/plugins/patchreview/patchhighlighter.h index 6557ea0fff..07c92dc87d 100644 --- a/plugins/patchreview/patchhighlighter.h +++ b/plugins/patchreview/patchhighlighter.h @@ -1,84 +1,84 @@ /*************************************************************************** Copyright 2006 David Nolden ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_PATCHHIGHLIGHTER_H #define KDEVPLATFORM_PLUGIN_PATCHHIGHLIGHTER_H #include #include #include #include #include namespace Diff2 { class Difference; class DiffModel; } class PatchReviewPlugin; namespace KDevelop { class IDocument; } namespace KTextEditor { class Document; class Range; class Cursor; class Mark; class MovingRange; } ///Delete itself when the document(or textDocument), or Diff-Model is deleted. class PatchHighlighter : public QObject { Q_OBJECT public: PatchHighlighter( Diff2::DiffModel* model, KDevelop::IDocument* doc, PatchReviewPlugin* plugin ) throw( QString ); - ~PatchHighlighter(); + ~PatchHighlighter() override; KDevelop::IDocument* doc(); QList< KTextEditor::MovingRange* > ranges() const; private slots: void documentDestroyed(); void aboutToDeleteMovingInterfaceContent( KTextEditor::Document* ); private: void highlightFromScratch(KTextEditor::Document* doc); void addLineMarker( KTextEditor::MovingRange* arg1, Diff2::Difference* arg2 ); void removeLineMarker( KTextEditor::MovingRange* range ); QStringList splitAndAddNewlines( const QString& text ) const; void performContentChange( KTextEditor::Document* doc, const QStringList& oldLines, const QStringList& newLines, int editLineNumber ); KTextEditor::MovingRange* rangeForMark(const KTextEditor::Mark& mark); void clear(); QSet< KTextEditor::MovingRange* > m_ranges; QMap< KTextEditor::MovingRange*, Diff2::Difference* > m_differencesForRanges; KDevelop::IDocument* m_doc; PatchReviewPlugin* m_plugin; Diff2::DiffModel* m_model; bool m_applying; public slots: void markToolTipRequested( KTextEditor::Document*, const KTextEditor::Mark&, QPoint, bool & ); void showToolTipForMark( QPoint arg1, KTextEditor::MovingRange* arg2); bool isRemoval( Diff2::Difference* ); bool isInsertion( Diff2::Difference* ); void markClicked( KTextEditor::Document*, const KTextEditor::Mark&, bool& ); void textInserted(KTextEditor::Document* doc, const KTextEditor::Cursor& cursor, const QString& text); void textRemoved( KTextEditor::Document*, const KTextEditor::Range&, const QString& oldText ); }; #endif diff --git a/plugins/patchreview/patchreview.cpp b/plugins/patchreview/patchreview.cpp index 0136f0af92..8525157028 100644 --- a/plugins/patchreview/patchreview.cpp +++ b/plugins/patchreview/patchreview.cpp @@ -1,540 +1,540 @@ /*************************************************************************** Copyright 2006-2009 David Nolden ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #include "patchreview.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ///Whether arbitrary exceptions that occurred while diff-parsing within the library should be caught #define CATCHLIBDIFF /* Exclude this file from doublequote_chars check as krazy doesn't understand std::string*/ //krazy:excludeall=doublequote_chars #include #include #include #include #include #include "patchhighlighter.h" #include "patchreviewtoolview.h" #include "localpatchsource.h" #include "debug.h" Q_LOGGING_CATEGORY(PLUGIN_PATCHREVIEW, "kdevplatform.plugins.patchreview") using namespace KDevelop; namespace { // Maximum number of files to open directly within a tab when the review is started const int maximumFilesToOpenDirectly = 15; } Q_DECLARE_METATYPE( const Diff2::DiffModel* ) void PatchReviewPlugin::seekHunk( bool forwards, const QUrl& fileName ) { try { qCDebug(PLUGIN_PATCHREVIEW) << forwards << fileName << fileName.isEmpty(); if ( !m_modelList ) throw "no model"; for ( int a = 0; a < m_modelList->modelCount(); ++a ) { const Diff2::DiffModel* model = m_modelList->modelAt( a ); if ( !model || !model->differences() ) continue; QUrl file = urlForFileModel( model ); if ( !fileName.isEmpty() && fileName != file ) continue; IDocument* doc = ICore::self()->documentController()->documentForUrl( file ); if ( doc && m_highlighters.contains( doc->url() ) && m_highlighters[doc->url()] ) { if ( doc->textDocument() ) { const QList ranges = m_highlighters[doc->url()]->ranges(); KTextEditor::View * v = doc->activeTextView(); int bestLine = -1; if ( v ) { KTextEditor::Cursor c = v->cursorPosition(); for ( QList::const_iterator it = ranges.begin(); it != ranges.end(); ++it ) { int line = ( *it )->start().line(); if ( forwards ) { if ( line > c.line() && ( bestLine == -1 || line < bestLine ) ) bestLine = line; } else { if ( line < c.line() && ( bestLine == -1 || line > bestLine ) ) bestLine = line; } } if ( bestLine != -1 ) { v->setCursorPosition( KTextEditor::Cursor( bestLine, 0 ) ); return; } else if(fileName.isEmpty()) { int next = qBound(0, forwards ? a+1 : a-1, m_modelList->modelCount()-1); ICore::self()->documentController()->openDocument(urlForFileModel(m_modelList->modelAt(next))); } } } } } } catch ( const QString & str ) { qCDebug(PLUGIN_PATCHREVIEW) << "seekHunk():" << str; } catch ( const char * str ) { qCDebug(PLUGIN_PATCHREVIEW) << "seekHunk():" << str; } qCDebug(PLUGIN_PATCHREVIEW) << "no matching hunk found"; } void PatchReviewPlugin::addHighlighting( const QUrl& highlightFile, IDocument* document ) { try { if ( !modelList() ) throw "no model"; for ( int a = 0; a < modelList()->modelCount(); ++a ) { Diff2::DiffModel* model = modelList()->modelAt( a ); if ( !model ) continue; QUrl file = urlForFileModel( model ); if ( file != highlightFile ) continue; qCDebug(PLUGIN_PATCHREVIEW) << "highlighting" << file.toDisplayString(); IDocument* doc = document; if( !doc ) doc = ICore::self()->documentController()->documentForUrl( file ); qCDebug(PLUGIN_PATCHREVIEW) << "highlighting file" << file << "with doc" << doc; if ( !doc || !doc->textDocument() ) continue; removeHighlighting( file ); m_highlighters[file] = new PatchHighlighter( model, doc, this ); } } catch ( const QString & str ) { qCDebug(PLUGIN_PATCHREVIEW) << "highlightFile():" << str; } catch ( const char * str ) { qCDebug(PLUGIN_PATCHREVIEW) << "highlightFile():" << str; } } void PatchReviewPlugin::highlightPatch() { try { if ( !modelList() ) throw "no model"; for ( int a = 0; a < modelList()->modelCount(); ++a ) { const Diff2::DiffModel* model = modelList()->modelAt( a ); if ( !model ) continue; QUrl file = urlForFileModel( model ); addHighlighting( file ); } } catch ( const QString & str ) { qCDebug(PLUGIN_PATCHREVIEW) << "highlightFile():" << str; } catch ( const char * str ) { qCDebug(PLUGIN_PATCHREVIEW) << "highlightFile():" << str; } } void PatchReviewPlugin::removeHighlighting( const QUrl& file ) { if ( file.isEmpty() ) { ///Remove all highlighting qDeleteAll( m_highlighters ); m_highlighters.clear(); } else { HighlightMap::iterator it = m_highlighters.find( file ); if ( it != m_highlighters.end() ) { delete *it; m_highlighters.erase( it ); } } } void PatchReviewPlugin::notifyPatchChanged() { if (m_patch) { qCDebug(PLUGIN_PATCHREVIEW) << "notifying patch change: " << m_patch->file(); m_updateKompareTimer->start( 500 ); } else { m_updateKompareTimer->stop(); } } void PatchReviewPlugin::forceUpdate() { if( m_patch ) { m_patch->update(); notifyPatchChanged(); } } void PatchReviewPlugin::updateKompareModel() { if ( !m_patch ) { ///TODO: this method should be cleaned up, it can be called by the timer and /// e.g. https://bugs.kde.org/show_bug.cgi?id=267187 shows how it could /// lead to asserts before... return; } qCDebug(PLUGIN_PATCHREVIEW) << "updating model"; removeHighlighting(); m_modelList.reset( nullptr ); delete m_diffSettings; { IDocument* patchDoc = ICore::self()->documentController()->documentForUrl( m_patch->file() ); if( patchDoc ) patchDoc->reload(); } QString patchFile; if( m_patch->file().isLocalFile() ) patchFile = m_patch->file().toLocalFile(); else if( m_patch->file().isValid() && !m_patch->file().isEmpty() ) { patchFile = QStandardPaths::writableLocation(QStandardPaths::TempLocation); bool ret = KIO::copy( m_patch->file(), QUrl::fromLocalFile(patchFile) )->exec(); if( !ret ) { qWarning() << "Problem while downloading: " << m_patch->file() << "to" << patchFile; patchFile.clear(); } } if (!patchFile.isEmpty()) //only try to construct the model if we have a patch to load try { m_diffSettings = new DiffSettings( 0 ); m_kompareInfo.reset( new Kompare::Info() ); m_kompareInfo->localDestination = patchFile; m_kompareInfo->localSource = m_patch->baseDir().toLocalFile(); m_kompareInfo->depth = m_patch->depth(); m_kompareInfo->applied = m_patch->isAlreadyApplied(); m_modelList.reset( new Diff2::KompareModelList( m_diffSettings.data(), new QWidget, this ) ); m_modelList->slotKompareInfo( m_kompareInfo.data() ); try { m_modelList->openDirAndDiff(); } catch ( const QString & str ) { throw; } catch ( ... ) { throw QStringLiteral( "lib/libdiff2 crashed, memory may be corrupted. Please restart kdevelop." ); } emit patchChanged(); for( int i = 0; i < m_modelList->modelCount(); i++ ) { const Diff2::DiffModel* model = m_modelList->modelAt( i ); for( int j = 0; j < model->differences()->count(); j++ ) { model->differences()->at( j )->apply( m_patch->isAlreadyApplied() ); } } highlightPatch(); return; } catch ( const QString & str ) { KMessageBox::error( 0, str, i18n( "Kompare Model Update" ) ); } catch ( const char * str ) { KMessageBox::error( 0, str, i18n( "Kompare Model Update" ) ); } removeHighlighting(); m_modelList.reset( nullptr ); m_kompareInfo.reset( nullptr ); delete m_diffSettings; emit patchChanged(); } K_PLUGIN_FACTORY_WITH_JSON(KDevProblemReporterFactory, "kdevpatchreview.json", registerPlugin();) class PatchReviewToolViewFactory : public KDevelop::IToolViewFactory { public: PatchReviewToolViewFactory( PatchReviewPlugin *plugin ) : m_plugin( plugin ) {} - virtual QWidget* create( QWidget *parent = 0 ) override { + QWidget* create( QWidget *parent = 0 ) override { return m_plugin->createToolView( parent ); } - virtual Qt::DockWidgetArea defaultPosition() override { + Qt::DockWidgetArea defaultPosition() override { return Qt::BottomDockWidgetArea; } - virtual QString id() const override { + QString id() const override { return "org.kdevelop.PatchReview"; } private: PatchReviewPlugin *m_plugin; }; PatchReviewPlugin::~PatchReviewPlugin() { removeHighlighting(); // Tweak to work around a crash on OS X; see https://bugs.kde.org/show_bug.cgi?id=338829 // and http://qt-project.org/forums/viewthread/38406/#162801 // modified tweak: use setPatch() and deleteLater in that method. setPatch(0); } void PatchReviewPlugin::clearPatch( QObject* _patch ) { qCDebug(PLUGIN_PATCHREVIEW) << "clearing patch" << _patch << "current:" << ( QObject* )m_patch; IPatchSource::Ptr patch( ( IPatchSource* )_patch ); if( patch == m_patch ) { qCDebug(PLUGIN_PATCHREVIEW) << "is current patch"; setPatch( IPatchSource::Ptr( new LocalPatchSource ) ); } } void PatchReviewPlugin::closeReview() { if( m_patch ) { removeHighlighting(); m_modelList.reset( 0 ); if( !dynamic_cast( m_patch.data() ) ) { // make sure "show" button still openes the file dialog to open a custom patch file setPatch( new LocalPatchSource ); } else emit patchChanged(); Sublime::Area* area = ICore::self()->uiController()->activeArea(); if( area->objectName() == "review" ) { if( ICore::self()->documentController()->saveAllDocuments() ) ICore::self()->uiController()->switchToArea( "code", KDevelop::IUiController::ThisWindow ); } } } void PatchReviewPlugin::cancelReview() { if( m_patch ) { m_patch->cancelReview(); closeReview(); } } void PatchReviewPlugin::finishReview( QList selection ) { if( m_patch && m_patch->finishReview( selection ) ) { closeReview(); } } void PatchReviewPlugin::startReview( IPatchSource* patch, IPatchReview::ReviewMode mode ) { Q_UNUSED( mode ); emit startingNewReview(); setPatch( patch ); QMetaObject::invokeMethod( this, "updateReview", Qt::QueuedConnection ); } void PatchReviewPlugin::switchToEmptyReviewArea() { foreach(Sublime::Area* area, ICore::self()->uiController()->allAreas()) { if (area->objectName() == "review") { emit area->clearDocuments(); } } if ( ICore::self()->uiController()->activeArea()->objectName() != "review" ) ICore::self()->uiController()->switchToArea( "review", KDevelop::IUiController::ThisWindow ); } QUrl PatchReviewPlugin::urlForFileModel( const Diff2::DiffModel* model ) { QUrl file = m_patch->baseDir(); file.setPath(file.toLocalFile() + '/' + model->destinationPath() + '/' + model->destinationFile()); return file; } void PatchReviewPlugin::updateReview() { if( !m_patch ) return; m_updateKompareTimer->stop(); switchToEmptyReviewArea(); 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 ); if( m_modelList->modelCount() < maximumFilesToOpenDirectly ) { //Open all relates files for( int a = 0; a < m_modelList->modelCount(); ++a ) { QUrl absoluteUrl = urlForFileModel( m_modelList->modelAt( a ) ); if( QFileInfo( absoluteUrl.toLocalFile() ).exists() && absoluteUrl.toLocalFile() != "/dev/null" ) { buddyDoc = ICore::self()->documentController()->openDocument( absoluteUrl, KTextEditor::Range::invalid(), IDocumentController::DoNotActivate, "", buddyDoc ); seekHunk( true, absoluteUrl ); //Jump to the first changed position }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 ) { if ( patch == m_patch ) { return; } if( m_patch ) { disconnect( m_patch.data(), &IPatchSource::patchChanged, this, &PatchReviewPlugin::notifyPatchChanged ); if ( qobject_cast( m_patch ) ) { // make sure we don't leak this // TODO: what about other patch sources? m_patch->deleteLater(); } } m_patch = patch; if( m_patch ) { qCDebug(PLUGIN_PATCHREVIEW) << "setting new patch" << patch->name() << "with file" << patch->file() << "basedir" << patch->baseDir(); connect( m_patch.data(), &IPatchSource::patchChanged, this, &PatchReviewPlugin::notifyPatchChanged ); } QString finishText = i18n( "Finish Review" ); if( m_patch && !m_patch->finishReviewCustomText().isEmpty() ) finishText = m_patch->finishReviewCustomText(); m_finishReview->setText( finishText ); notifyPatchChanged(); } PatchReviewPlugin::PatchReviewPlugin( QObject *parent, const QVariantList & ) : KDevelop::IPlugin( "kdevpatchreview", parent ), m_patch( 0 ), m_factory( new PatchReviewToolViewFactory( this ) ) { KDEV_USE_EXTENSION_INTERFACE( KDevelop::IPatchReview ) qRegisterMetaType( "const Diff2::DiffModel*" ); setXMLFile( "kdevpatchreview.rc" ); connect( ICore::self()->documentController(), &IDocumentController::documentClosed, this, &PatchReviewPlugin::documentClosed ); connect( ICore::self()->documentController(), &IDocumentController::textDocumentCreated, this, &PatchReviewPlugin::textDocumentCreated ); connect( ICore::self()->documentController(), &IDocumentController::documentSaved, this, &PatchReviewPlugin::documentSaved ); m_updateKompareTimer = new QTimer( this ); m_updateKompareTimer->setSingleShot( true ); connect( m_updateKompareTimer, &QTimer::timeout, this, &PatchReviewPlugin::updateKompareModel ); m_finishReview = new QAction(i18n("Finish Review"), this); m_finishReview->setIcon( QIcon::fromTheme( "dialog-ok" ) ); actionCollection()->setDefaultShortcut( m_finishReview, Qt::CTRL|Qt::Key_Return ); actionCollection()->addAction("commit_or_finish_review", m_finishReview); foreach(Sublime::Area* area, ICore::self()->uiController()->allAreas()) { if (area->objectName() == "review") area->addAction(m_finishReview); } core()->uiController()->addToolView( i18n( "Patch Review" ), m_factory ); areaChanged(ICore::self()->uiController()->activeArea()); } void PatchReviewPlugin::documentClosed( IDocument* doc ) { removeHighlighting( doc->url() ); } void PatchReviewPlugin::documentSaved( IDocument* doc ) { // 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() ) forceUpdate(); } void PatchReviewPlugin::textDocumentCreated( IDocument* doc ) { if (m_patch) { addHighlighting( doc->url(), doc ); } } void PatchReviewPlugin::unload() { core()->uiController()->removeToolView( m_factory ); KDevelop::IPlugin::unload(); } QWidget* PatchReviewPlugin::createToolView( QWidget* parent ) { return new PatchReviewToolView( parent, this ); } void PatchReviewPlugin::areaChanged(Sublime::Area* area) { bool reviewing = area->objectName() == "review"; m_finishReview->setEnabled(reviewing); if(!reviewing) { closeReview(); } } #include "patchreview.moc" // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on diff --git a/plugins/patchreview/patchreview.h b/plugins/patchreview/patchreview.h index 0d943ac9b3..d5d87c0346 100644 --- a/plugins/patchreview/patchreview.h +++ b/plugins/patchreview/patchreview.h @@ -1,132 +1,132 @@ /*************************************************************************** Copyright 2006 David Nolden ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_PATCHREVIEW_H #define KDEVPLATFORM_PLUGIN_PATCHREVIEW_H #include #include #include #include class PatchHighlighter; class PatchReviewToolViewFactory; class QTimer; namespace KDevelop { class IDocument; } namespace Sublime { class Area; } namespace Diff2 { class KompareModelList; class DiffModel; } namespace Kompare { struct Info; } class DiffSettings; class PatchReviewPlugin; class PatchReviewPlugin : public KDevelop::IPlugin, public KDevelop::IPatchReview { Q_OBJECT Q_INTERFACES( KDevelop::IPatchReview ) public : explicit PatchReviewPlugin( QObject *parent, const QVariantList & = QVariantList() ); - ~PatchReviewPlugin(); - virtual void unload() override; + ~PatchReviewPlugin() override; + void unload() override; QWidget* createToolView( QWidget* parent ); KDevelop::IPatchSource::Ptr patch() const { return m_patch; } Diff2::KompareModelList* modelList() const { return m_modelList.data(); } void seekHunk( bool forwards, const QUrl& file = QUrl() ); void setPatch( KDevelop::IPatchSource* patch ); - virtual void startReview( KDevelop::IPatchSource* patch, ReviewMode mode ) override; + void startReview( KDevelop::IPatchSource* patch, ReviewMode mode ) override; void finishReview( QList< QUrl > selection ); QUrl urlForFileModel( const Diff2::DiffModel* model ); QAction* finishReviewAction() const { return m_finishReview; } Q_SIGNALS: void startingNewReview(); void patchChanged(); public Q_SLOTS : //Does parts of the review-starting that are problematic to do directly in startReview, as they may open dialogs etc. void updateReview(); void cancelReview(); void clearPatch( QObject* patch ); void notifyPatchChanged(); void highlightPatch(); void updateKompareModel(); void forceUpdate(); void areaChanged(Sublime::Area* area); private Q_SLOTS : void documentClosed( KDevelop::IDocument* ); void textDocumentCreated( KDevelop::IDocument* ); void documentSaved( KDevelop::IDocument* ); void closeReview(); private: void switchToEmptyReviewArea(); /// Makes sure that this working set is active only in the @p area, and that its name starts with "review". void setUniqueEmptyWorkingSet(Sublime::Area* area); void addHighlighting( const QUrl& file, KDevelop::IDocument* document = 0 ); void removeHighlighting( const QUrl& file = QUrl() ); KDevelop::IPatchSource::Ptr m_patch; QTimer* m_updateKompareTimer; PatchReviewToolViewFactory* m_factory; QAction* m_finishReview; #if 0 void determineState(); #endif QPointer< DiffSettings > m_diffSettings; QScopedPointer< Kompare::Info > m_kompareInfo; QScopedPointer< Diff2::KompareModelList > m_modelList; typedef QMap< QUrl, QPointer< PatchHighlighter > > HighlightMap; HighlightMap m_highlighters; friend class PatchReviewToolView; // to access slot exporterSelected(); }; #endif // kate: space-indent on; indent-width 2; tab-width 2; replace-tabs on diff --git a/plugins/patchreview/patchreviewtoolview.h b/plugins/patchreview/patchreviewtoolview.h index 3855320bd9..ca78a3f539 100644 --- a/plugins/patchreview/patchreviewtoolview.h +++ b/plugins/patchreview/patchreviewtoolview.h @@ -1,108 +1,108 @@ /*************************************************************************** Copyright 2006-2009 David Nolden ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_PATCHREVIEWTOOLVIEW_H #define KDEVPLATFORM_PLUGIN_PATCHREVIEWTOOLVIEW_H #include #include #include #include #include namespace Sublime { class Area; } namespace KDevelop { class IDocument; } namespace KParts { class Part; } namespace Purpose { class Menu; } class QStandardItem; class KJob; class PatchReviewPlugin; class LocalPatchSource; class QModelIndex; class PatchReviewToolView : public QWidget { Q_OBJECT public: PatchReviewToolView( QWidget* parent, PatchReviewPlugin* plugin ); - ~PatchReviewToolView(); + ~PatchReviewToolView() override; signals: void dialogClosed( PatchReviewToolView* ); void stateChanged( PatchReviewToolView* ); private slots: void startingNewReview(); void fileDoubleClicked( const QModelIndex& i ); void nextHunk(); void prevHunk(); void prevFile(); void nextFile(); void seekFile(bool forwards); void patchChanged(); void slotAppliedChanged( int newState ); void finishReview(); void runTests(); void selectAll(); void deselectAll(); void fileItemChanged( QStandardItem* item ); private: - virtual void resizeEvent(QResizeEvent*) override; + void resizeEvent(QResizeEvent*) override; void activate( const QUrl& url, KDevelop::IDocument* buddy = 0 ) const; void kompareModelChanged(); void showEditDialog(); ///Fills the editor views from m_editingPatch void fillEditFromPatch(); /// Retrieve the patch from plugin and perform all necessary casts LocalPatchSource* GetLocalPatchSource(); Ui_EditPatch m_editPatch; QTime m_lastDataTime; QString m_lastTerminalData; QPointer< KParts::Part > m_konsolePart; /// Whether the set of checked URLs should be reset on the next update bool m_resetCheckedUrls; PatchReviewPlugin* m_plugin; QPointer< QWidget > m_customWidget; QAction* m_selectAllAction; QAction* m_deselectAllAction; Purpose::Menu* m_exportMenu; class PatchFilesModel* m_fileModel; public slots: void documentActivated( KDevelop::IDocument* ); void customContextMenuRequested(const QPoint& p); void testJobResult(KJob* job); void testJobPercent(KJob* job, ulong percent); }; #endif // KDEVPLATFORM_PLUGIN_PATCHREVIEWTOOLVIEW_H diff --git a/plugins/problemreporter/problemhighlighter.h b/plugins/problemreporter/problemhighlighter.h index ca4eedc65b..0a0b7414fc 100644 --- a/plugins/problemreporter/problemhighlighter.h +++ b/plugins/problemreporter/problemhighlighter.h @@ -1,70 +1,70 @@ /* * KDevelop Problem Reporter * * Copyright 2008 Hamish Rodda * Copyright 2008-2009 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. */ #ifndef KDEVPLATFORM_PLUGIN_PROBLEM_HIGHLIGHT_H #define KDEVPLATFORM_PLUGIN_PROBLEM_HIGHLIGHT_H #include #include #include #include #include class ProblemHighlighter : public QObject { Q_OBJECT public: explicit ProblemHighlighter(KTextEditor::Document* document); - virtual ~ProblemHighlighter(); + ~ProblemHighlighter() override; void setProblems(const QVector& problems); private slots: void viewCreated(KTextEditor::Document*, KTextEditor::View*); void aboutToRemoveText(const KTextEditor::Range& range); void clearProblems(); private: QPointer m_document; QList m_topHLRanges; QVector m_problems; QMap m_problemsForRanges; friend class ProblemTextHintProvider; public slots: void settingsChanged(); }; class ProblemTextHintProvider : public KTextEditor::TextHintProvider { public: explicit ProblemTextHintProvider(ProblemHighlighter* highlighter); - virtual QString textHint(KTextEditor::View* view, const KTextEditor::Cursor& position) override; + QString textHint(KTextEditor::View* view, const KTextEditor::Cursor& position) override; private: ProblemHighlighter* m_highlighter; KTextEditor::Range m_currentHintRange; }; #endif // KDEVPLATFORM_PLUGIN_PROBLEM_HIGHLIGHT_H diff --git a/plugins/problemreporter/problemreportermodel.h b/plugins/problemreporter/problemreportermodel.h index f6ffa0397e..0fa61a6bdb 100644 --- a/plugins/problemreporter/problemreportermodel.h +++ b/plugins/problemreporter/problemreportermodel.h @@ -1,86 +1,86 @@ /* * Copyright 2007 Hamish Rodda * Copyright 2015 Laszlo Kis-Adam * * 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. */ #ifndef PROBLEMREPORTERMODEL_H #define PROBLEMREPORTERMODEL_H #include namespace KDevelop { class IndexedString; class TopDUContext; } class WatchedDocumentSet; class QTimer; /** * @brief ProblemModel subclass that retrieves the problems from DUChain. * * Provides a ProblemModel interface so these problems can be shown in the Problems toolview. */ class ProblemReporterModel : public KDevelop::ProblemModel { Q_OBJECT public: explicit ProblemReporterModel(QObject* parent); - ~ProblemReporterModel(); + ~ProblemReporterModel() override; /** * Get problems for @ref url. */ QVector problems(const KDevelop::IndexedString& url, bool showImports) const; /** * Get merged list of problems for all @ref urls. */ QVector problems(const QSet& urls, bool showImports) const; public Q_SLOTS: /** * List of problems for @ref url has been updated */ void problemsUpdated(const KDevelop::IndexedString& url); - void setShowImports(bool showImports); - void forceFullUpdate(); + void setShowImports(bool showImports) override; + void forceFullUpdate() override; protected Q_SLOTS: /// Triggered when the problemstore's problems have changed - void onProblemsChanged(); + void onProblemsChanged() override; private Q_SLOTS: void timerExpired(); - void setCurrentDocument(KDevelop::IDocument* doc); + void setCurrentDocument(KDevelop::IDocument* doc) override; private: void problemsInternal(KDevelop::TopDUContext* context, bool showImports, QSet& visitedContexts, QVector& result) const; void rebuildProblemList(); bool m_showImports; /// include problems from imported documents QTimer* m_minTimer; QTimer* m_maxTimer; const static int MinTimeout; const static int MaxTimeout; }; #endif diff --git a/plugins/problemreporter/problemreporterplugin.cpp b/plugins/problemreporter/problemreporterplugin.cpp index 0f715ce0ef..c9ebbb302d 100644 --- a/plugins/problemreporter/problemreporterplugin.cpp +++ b/plugins/problemreporter/problemreporterplugin.cpp @@ -1,206 +1,206 @@ /* * KDevelop Problem Reporter * * Copyright 2006 Adam Treat * Copyright 2006-2007 Hamish Rodda * Copyright 2007-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 "problemreporterplugin.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "problemhighlighter.h" #include "problemtreeview.h" #include "problemreportermodel.h" #include #include #include #include #include #include #include "shell/problemmodelset.h" #include "problemsview.h" #include Q_LOGGING_CATEGORY(PLUGIN_PROBLEMREPORTER, "kdevplatform.plugins.problemreporter") K_PLUGIN_FACTORY_WITH_JSON(KDevProblemReporterFactory, "kdevproblemreporter.json", registerPlugin();) using namespace KDevelop; class ProblemReporterFactory : public KDevelop::IToolViewFactory { public: - virtual QWidget* create(QWidget* parent = 0) override + QWidget* create(QWidget* parent = 0) override { Q_UNUSED(parent); ProblemsView* v = new ProblemsView(); v->load(); return v; } - virtual Qt::DockWidgetArea defaultPosition() override { return Qt::BottomDockWidgetArea; } + Qt::DockWidgetArea defaultPosition() override { return Qt::BottomDockWidgetArea; } - virtual QString id() const override { return "org.kdevelop.ProblemReporterView"; } + QString id() const override { return "org.kdevelop.ProblemReporterView"; } }; ProblemReporterPlugin::ProblemReporterPlugin(QObject* parent, const QVariantList&) : KDevelop::IPlugin("kdevproblemreporter", parent) , m_factory(new ProblemReporterFactory) , m_model(new ProblemReporterModel(this)) { KDevelop::ProblemModelSet* pms = core()->languageController()->problemModelSet(); pms->addModel("Parser", m_model); core()->uiController()->addToolView(i18n("Problems"), m_factory); setXMLFile("kdevproblemreporter.rc"); connect(ICore::self()->documentController(), &IDocumentController::documentClosed, this, &ProblemReporterPlugin::documentClosed); connect(ICore::self()->documentController(), &IDocumentController::textDocumentCreated, this, &ProblemReporterPlugin::textDocumentCreated); connect(ICore::self()->languageController()->backgroundParser(), &BackgroundParser::parseJobFinished, this, &ProblemReporterPlugin::parseJobFinished, Qt::DirectConnection); } ProblemReporterPlugin::~ProblemReporterPlugin() { qDeleteAll(m_highlighters); } ProblemReporterModel* ProblemReporterPlugin::model() const { return m_model; } void ProblemReporterPlugin::unload() { KDevelop::ProblemModelSet* pms = KDevelop::ICore::self()->languageController()->problemModelSet(); pms->removeModel("Parser"); core()->uiController()->removeToolView(m_factory); } void ProblemReporterPlugin::documentClosed(IDocument* doc) { if (!doc->textDocument()) return; IndexedString url(doc->url()); delete m_highlighters.take(url); } void ProblemReporterPlugin::textDocumentCreated(KDevelop::IDocument* document) { Q_ASSERT(document->textDocument()); m_highlighters.insert(IndexedString(document->url()), new ProblemHighlighter(document->textDocument())); DUChainReadLocker lock(DUChain::lock()); DUChain::self()->updateContextForUrl(IndexedString(document->url()), KDevelop::TopDUContext::AllDeclarationsContextsAndUses, this); } void ProblemReporterPlugin::updateReady(const IndexedString& url, const KDevelop::ReferencedTopDUContext&) { m_model->problemsUpdated(url); ProblemHighlighter* ph = m_highlighters.value(url); if (ph) { QVector allProblems = m_model->problems(url, false); ph->setProblems(allProblems); } } void ProblemReporterPlugin::parseJobFinished(KDevelop::ParseJob* parseJob) { if (parseJob->duChain()) updateReady(parseJob->document()); } KDevelop::ContextMenuExtension ProblemReporterPlugin::contextMenuExtension(KDevelop::Context* context) { KDevelop::ContextMenuExtension extension; KDevelop::EditorContext* editorContext = dynamic_cast(context); if (editorContext) { DUChainReadLocker lock(DUChain::lock(), 1000); if (!lock.locked()) { qCDebug(PLUGIN_PROBLEMREPORTER) << "failed to lock duchain in time"; return extension; } QString title; QList actions; TopDUContext* top = DUChainUtils::standardContextForUrl(editorContext->url()); if (top) { foreach (KDevelop::ProblemPointer problem, top->problems()) { if (problem->range().contains( top->transformToLocalRevision(KTextEditor::Cursor(editorContext->position())))) { KDevelop::IAssistant::Ptr solution = problem->solutionAssistant(); if (solution) { title = solution->title(); foreach (KDevelop::IAssistantAction::Ptr action, solution->actions()) actions << action->toKAction(); } } } } if (!actions.isEmpty()) { QString text; if (title.isEmpty()) text = i18n("Solve Problem"); else { text = i18n("Solve: %1", KDevelop::htmlToPlainText(title)); } QAction* menuAction = new QAction(text, 0); QMenu* menu(new QMenu(text, 0)); menuAction->setMenu(menu); foreach (QAction* action, actions) menu->addAction(action); extension.addAction(ContextMenuExtension::ExtensionGroup, menuAction); } } return extension; } #include "problemreporterplugin.moc" // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/problemreporter/problemreporterplugin.h b/plugins/problemreporter/problemreporterplugin.h index 47e52af0c0..da4576bc45 100644 --- a/plugins/problemreporter/problemreporterplugin.h +++ b/plugins/problemreporter/problemreporterplugin.h @@ -1,81 +1,81 @@ /* * KDevelop Problem Reporter * * Copyright 2006 Adam Treat * Copyright 2006-2007 Hamish Rodda * Copyright 2007-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. */ #ifndef KDEVPLATFORM_PLUGIN_PROBLEMREPORTERPLUGIN_H #define KDEVPLATFORM_PLUGIN_PROBLEMREPORTERPLUGIN_H #include #include #include #include #include Q_DECLARE_LOGGING_CATEGORY(PLUGIN_PROBLEMREPORTER) namespace KTextEditor { class Document; } namespace KDevelop { class IDocument; class ParseJob; } class ProblemHighlighter; class ProblemReporterModel; class ProblemReporterPlugin : public KDevelop::IPlugin { Q_OBJECT public: explicit ProblemReporterPlugin(QObject* parent, const QVariantList& = QVariantList()); - virtual ~ProblemReporterPlugin(); + ~ProblemReporterPlugin() override; - virtual KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; + KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; // KDevelop::Plugin methods - virtual void unload() override; + void unload() override; ProblemReporterModel* model() const; private Q_SLOTS: void updateReady(const KDevelop::IndexedString& url, const KDevelop::ReferencedTopDUContext& = KDevelop::ReferencedTopDUContext()); void textDocumentCreated(KDevelop::IDocument* document); void parseJobFinished(KDevelop::ParseJob* parseJob); private: class ProblemReporterFactory* m_factory; ProblemReporterModel* m_model; QHash m_highlighters; public slots: void documentClosed(KDevelop::IDocument*); }; #endif // KDEVPLATFORM_PLUGIN_PROBLEMREPORTERPLUGIN_H // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/problemreporter/problemsview.h b/plugins/problemreporter/problemsview.h index 5cc3aa56a8..19c1bb73fe 100644 --- a/plugins/problemreporter/problemsview.h +++ b/plugins/problemreporter/problemsview.h @@ -1,90 +1,90 @@ /* * Copyright 2015 Laszlo Kis-Adam * * 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. */ #ifndef PROBLEMSVIEW_H #define PROBLEMSVIEW_H #include #include class ProblemTreeView; 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 { Q_OBJECT Q_INTERFACES(KDevelop::IToolViewActionListener) public: explicit ProblemsView(QWidget* parent = NULL); - ~ProblemsView(); + ~ProblemsView() override; /// Load all the current models and create tabs for them void load(); public Q_SLOTS: /// Triggered when a new model is added to the ModelSet void onModelAdded(const ModelData& data); /// Triggered when a model is removed from the ModelSet void onModelRemoved(const QString& name); /// Triggered when the user (or program) selects a new tab void onCurrentChanged(int idx); /// Triggered when a view changes (happens when the model data changes) void onViewChanged(); void selectNextItem() override; void selectPreviousItem() override; private: ProblemTreeView* currentView() const; /// 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; }; } #endif diff --git a/plugins/problemreporter/problemtreeview.h b/plugins/problemreporter/problemtreeview.h index 5ecaf80638..4a770418ab 100644 --- a/plugins/problemreporter/problemtreeview.h +++ b/plugins/problemreporter/problemtreeview.h @@ -1,75 +1,75 @@ /* * KDevelop Problem Reporter * * Copyright (c) 2007 Hamish Rodda * * 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. */ #ifndef KDEVPLATFORM_PLUGIN_PROBLEMWIDGET_H #define KDEVPLATFORM_PLUGIN_PROBLEMWIDGET_H #include namespace KDevelop { class ParseJob; class TopDUContext; class IDocument; class ProblemModel; } class ProblemReporterPlugin; class QSortFilterProxyModel; class ProblemTreeView : public QTreeView { Q_OBJECT public: ProblemTreeView(QWidget* parent, QAbstractItemModel* itemModel); - virtual ~ProblemTreeView(); + ~ProblemTreeView() override; KDevelop::ProblemModel* model() const; - virtual void setModel(QAbstractItemModel* model) override; + void setModel(QAbstractItemModel* model) override; - virtual void contextMenuEvent(QContextMenuEvent*) override; - virtual void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, + void contextMenuEvent(QContextMenuEvent*) override; + void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& roles = QVector()) override; - virtual void reset() override; + void reset() override; public slots: void openDocumentForCurrentProblem(); signals: // Emitted when the model's rows change (added/removed/reset) void changed(); protected: - virtual void showEvent(QShowEvent* event) override; + void showEvent(QShowEvent* event) override; private slots: void itemActivated(const QModelIndex& index); private: void resizeColumns(); ProblemReporterPlugin* m_plugin; QSortFilterProxyModel* m_proxy; }; #endif // kate: space-indent on; indent-width 2; tab-width: 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/projectfilter/comboboxdelegate.h b/plugins/projectfilter/comboboxdelegate.h index 298319c6e0..9868fb836f 100644 --- a/plugins/projectfilter/comboboxdelegate.h +++ b/plugins/projectfilter/comboboxdelegate.h @@ -1,60 +1,60 @@ /* * This file is part of KDevelop * Copyright 2013 Milian Wolff * * 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 COMBOBOXDELEGATE_H #define COMBOBOXDELEGATE_H #include namespace KDevelop { class ComboBoxDelegate : public QStyledItemDelegate { Q_OBJECT public: struct Item { Item() {} Item(const QString& text, const QVariant& data) : text(text) , data(data) {} QString text; QVariant data; }; explicit ComboBoxDelegate(const QVector& items, QObject* parent = 0); - virtual ~ComboBoxDelegate(); + ~ComboBoxDelegate() override; - virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override; - virtual void setEditorData(QWidget* editor, const QModelIndex& index) const override; - virtual void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override; + QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + void setEditorData(QWidget* editor, const QModelIndex& index) const override; + void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override; private: QVector m_items; }; } Q_DECLARE_TYPEINFO(KDevelop::ComboBoxDelegate::Item, Q_MOVABLE_TYPE); #endif // COMBOBOXDELEGATE_H diff --git a/plugins/projectfilter/filtermodel.h b/plugins/projectfilter/filtermodel.h index 046f433def..c260895f4b 100644 --- a/plugins/projectfilter/filtermodel.h +++ b/plugins/projectfilter/filtermodel.h @@ -1,73 +1,73 @@ /* * This file is part of KDevelop * Copyright 2013 Milian Wolff * * 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 FILTERMODEL_H #define FILTERMODEL_H #include #include "filter.h" namespace KDevelop { class FilterModel : public QAbstractTableModel { Q_OBJECT public: explicit FilterModel(QObject* parent = 0); - virtual ~FilterModel(); + ~FilterModel() override; SerializedFilters filters() const; void setFilters(const SerializedFilters& filters); void moveFilterUp(int row); void moveFilterDown(int row); - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; - virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; - virtual Qt::DropActions supportedDropActions() const override; - virtual Qt::ItemFlags flags(const QModelIndex& index) const override; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; - virtual bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; - virtual bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; - virtual QMap< int, QVariant > itemData(const QModelIndex& index) const override; - virtual bool setItemData(const QModelIndex& index, const QMap< int, QVariant >& roles) override; + Qt::DropActions supportedDropActions() const override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; + bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; + bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; + QMap< int, QVariant > itemData(const QModelIndex& index) const override; + bool setItemData(const QModelIndex& index, const QMap< int, QVariant >& roles) override; enum Columns { Pattern, Targets, Inclusive, NUM_COLUMNS }; private: SerializedFilters m_filters; // workaround a strange behavior in Qt when we try to drop after the last item in the list bool m_ignoredLastInsert; }; } #endif // FILTERMODEL_H diff --git a/plugins/projectfilter/projectfilterconfigpage.h b/plugins/projectfilter/projectfilterconfigpage.h index 9513ed38ca..f2419302c0 100644 --- a/plugins/projectfilter/projectfilterconfigpage.h +++ b/plugins/projectfilter/projectfilterconfigpage.h @@ -1,74 +1,74 @@ /* This file is part of KDevelop Copyright 2013 Milian Wolff Copyright 2008 Alexander Dymo 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 KDEVPLATFORM_PLUGIN_PROJECTFILTERCONFIGPAGE_H #define KDEVPLATFORM_PLUGIN_PROJECTFILTERCONFIGPAGE_H #include #include "projectfiltersettings.h" namespace Ui { class ProjectFilterSettings; } namespace KDevelop { class FilterModel; class ProjectFilterProvider; class ProjectFilterConfigPage : public ProjectConfigPage { Q_OBJECT public: ProjectFilterConfigPage(ProjectFilterProvider* provider, const KDevelop::ProjectConfigOptions& options, QWidget* parent); - virtual ~ProjectFilterConfigPage(); + ~ProjectFilterConfigPage() override; - virtual QString name() const override; - virtual QIcon icon() const override; - virtual QString fullName() const override; + QString name() const override; + QIcon icon() const override; + QString fullName() const override; protected: - virtual bool eventFilter(QObject* object, QEvent* event) override; + bool eventFilter(QObject* object, QEvent* event) override; private slots: void add(); void remove(); void moveUp(); void moveDown(); void selectionChanged(); void emitChanged(); public Q_SLOTS: - virtual void apply() override; - virtual void reset() override; - virtual void defaults() override; + void apply() override; + void reset() override; + void defaults() override; private: void checkFilters(); FilterModel *m_model; ProjectFilterProvider* m_projectFilterProvider; QScopedPointer m_ui; }; } #endif diff --git a/plugins/projectfilter/projectfilterprovider.h b/plugins/projectfilter/projectfilterprovider.h index f9062c35ad..9f1ac4bdb6 100644 --- a/plugins/projectfilter/projectfilterprovider.h +++ b/plugins/projectfilter/projectfilterprovider.h @@ -1,67 +1,67 @@ /* This file is part of KDevelop Copyright 2013 Milian Wolff 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 KDEVPLATFORM_PLUGIN_PROJECTFILTERPROVIDER_H #define KDEVPLATFORM_PLUGIN_PROJECTFILTERPROVIDER_H #include #include #include "projectfilter.h" #include namespace KDevelop { class ProjectFilterProvider: public IPlugin, public IProjectFilterProvider { Q_OBJECT Q_INTERFACES( KDevelop::IProjectFilterProvider ) public: explicit ProjectFilterProvider( QObject* parent = 0, const QVariantList& args = QVariantList() ); - virtual QSharedPointer createFilter(IProject* project) const override; + QSharedPointer createFilter(IProject* project) const override; - virtual ContextMenuExtension contextMenuExtension(Context* context) override; + ContextMenuExtension contextMenuExtension(Context* context) override; - virtual int perProjectConfigPages() const override; - virtual ConfigPage* perProjectConfigPage(int number, const ProjectConfigOptions& options, QWidget* parent) override; + int perProjectConfigPages() const override; + ConfigPage* perProjectConfigPage(int number, const ProjectConfigOptions& options, QWidget* parent) override; signals: void filterChanged(KDevelop::IProjectFilterProvider*, KDevelop::IProject*); public slots: void updateProjectFilters(KDevelop::IProject* project); private slots: void projectClosing(KDevelop::IProject*); void projectAboutToBeOpened(KDevelop::IProject*); void addFilterFromContextMenu(); private: QHash > m_filters; }; } #endif // KDEVPLATFORM_PLUGIN_PROJECTFILTERPROVIDER_H diff --git a/plugins/projectmanagerview/projectbuildsetwidget.h b/plugins/projectmanagerview/projectbuildsetwidget.h index ade1cfcd24..07a9838009 100644 --- a/plugins/projectmanagerview/projectbuildsetwidget.h +++ b/plugins/projectmanagerview/projectbuildsetwidget.h @@ -1,68 +1,68 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2007 Andreas Pakulat * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_PROJECTBUILDSETWIDGET_H #define KDEVPLATFORM_PLUGIN_PROJECTBUILDSETWIDGET_H #include #include class QTreeView; class QToolButton; class ProjectManagerViewPlugin; class QStringListModel; class ProjectManagerView; namespace KDevelop { class ProjectBaseItem; } namespace Ui { class ProjectBuildSetWidget; } class ProjectBuildSetWidget : public QWidget { Q_OBJECT public: explicit ProjectBuildSetWidget( QWidget* parent = 0 ); - ~ProjectBuildSetWidget(); + ~ProjectBuildSetWidget() override; void setProjectView( ProjectManagerView* view ); public slots: void selectionChanged(); private slots: void addItems(); void removeItems(); void moveUp(); void moveDown(); void moveToBottom(); void moveToTop(); void showContextMenu( const QPoint& p ); private: ProjectManagerView* m_view; Ui::ProjectBuildSetWidget* m_ui; }; #endif //kate: space-indent on; indent-width 4; replace-tabs on; auto-insert-doxygen on; indent-mode cstyle; diff --git a/plugins/projectmanagerview/projectmanagerview.h b/plugins/projectmanagerview/projectmanagerview.h index 07e24d6894..1bec6f104e 100644 --- a/plugins/projectmanagerview/projectmanagerview.h +++ b/plugins/projectmanagerview/projectmanagerview.h @@ -1,95 +1,95 @@ /* This file is part of KDevelop Copyright 2005 Roberto Raggi Copyright 2007 Andreas Pakulat 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 KDEVPLATFORM_PLUGIN_PROJECTMANAGERVIEW_H #define KDEVPLATFORM_PLUGIN_PROJECTMANAGERVIEW_H #include #include #include #include class QModelIndex; namespace Ui { class ProjectManagerView; } class ProjectProxyModel; class VcsOverlayProxyModel; namespace KDevelop { class ProjectBaseItem; class Path; } class ProjectManagerView; class ProjectManagerViewPlugin; //own subclass to the current view can be passed from ProjectManagetView to ProjectManagerViewPlugin class ProjectManagerViewItemContext : public KDevelop::ProjectItemContextImpl { public: ProjectManagerViewItemContext(const QList< KDevelop::ProjectBaseItem* >& items, ProjectManagerView *view); ProjectManagerView *view() const; private: ProjectManagerView *m_view; }; class ProjectManagerView: public QWidget { Q_OBJECT public: ProjectManagerView( ProjectManagerViewPlugin*, QWidget *parent ); - virtual ~ProjectManagerView(); + ~ProjectManagerView() override; ProjectManagerViewPlugin* plugin() const { return m_plugin; } QList selectedItems() const; void selectItems(const QList &items); void expandItem(KDevelop::ProjectBaseItem *item); protected: - virtual bool eventFilter(QObject* obj, QEvent* event) override; + bool eventFilter(QObject* obj, QEvent* event) override; private slots: void selectionChanged(); void locateCurrentDocument(); void updateSyncAction(); void open( const KDevelop::Path& ); void toggleHideTargets(bool hidden); private: QModelIndex indexFromView(const QModelIndex& index) const; QModelIndex indexToView(const QModelIndex& index) const; QAction* m_syncAction; QAction* m_toggleTargetsAction; Ui::ProjectManagerView* m_ui; QStringList m_cachedFileList; ProjectProxyModel* m_modelFilter; VcsOverlayProxyModel* m_overlayProxy; ProjectManagerViewPlugin* m_plugin; }; #endif // KDEVPLATFORM_PLUGIN_PROJECTMANAGERVIEW_H diff --git a/plugins/projectmanagerview/projectmanagerviewplugin.cpp b/plugins/projectmanagerview/projectmanagerviewplugin.cpp index b01bd66b36..bdd5dd3292 100644 --- a/plugins/projectmanagerview/projectmanagerviewplugin.cpp +++ b/plugins/projectmanagerview/projectmanagerviewplugin.cpp @@ -1,715 +1,715 @@ /* This file is part of KDevelop Copyright 2004 Roberto Raggi Copyright 2007 Andreas Pakulat 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 "projectmanagerviewplugin.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "projectmanagerview.h" #include "debug.h" using namespace KDevelop; Q_LOGGING_CATEGORY(PLUGIN_PROJECTMANAGERVIEW, "kdevplatform.plugins.projectmanagerview") K_PLUGIN_FACTORY_WITH_JSON(ProjectManagerFactory, "kdevprojectmanagerview.json", registerPlugin();) class KDevProjectManagerViewFactory: public KDevelop::IToolViewFactory { public: KDevProjectManagerViewFactory( ProjectManagerViewPlugin *plugin ): mplugin( plugin ) {} - virtual QWidget* create( QWidget *parent = 0 ) override + QWidget* create( QWidget *parent = 0 ) override { return new ProjectManagerView( mplugin, parent ); } - virtual Qt::DockWidgetArea defaultPosition() override + Qt::DockWidgetArea defaultPosition() override { return Qt::LeftDockWidgetArea; } - virtual QString id() const override + QString id() const override { return "org.kdevelop.ProjectsView"; } private: ProjectManagerViewPlugin *mplugin; }; class ProjectManagerViewPluginPrivate { public: ProjectManagerViewPluginPrivate() {} KDevProjectManagerViewFactory *factory; QList ctxProjectItemList; QAction* m_buildAll; QAction* m_build; QAction* m_install; QAction* m_clean; QAction* m_configure; QAction* m_prune; }; static QList itemsFromIndexes(const QList& indexes) { QList items; ProjectModel* model = ICore::self()->projectController()->projectModel(); foreach(const QModelIndex& index, indexes) { items += model->itemFromIndex(index); } return items; } ProjectManagerViewPlugin::ProjectManagerViewPlugin( QObject *parent, const QVariantList& ) : IPlugin( "kdevprojectmanagerview", parent ), d(new ProjectManagerViewPluginPrivate) { d->m_buildAll = new QAction( i18n("Build all Projects"), this ); d->m_buildAll->setIcon(QIcon::fromTheme("run-build")); connect( d->m_buildAll, &QAction::triggered, this, &ProjectManagerViewPlugin::buildAllProjects ); actionCollection()->addAction( "project_buildall", d->m_buildAll ); d->m_build = new QAction( i18n("Build Selection"), this ); d->m_build->setIconText( i18n("Build") ); actionCollection()->setDefaultShortcut( d->m_build, Qt::Key_F8 ); d->m_build->setIcon(QIcon::fromTheme("run-build")); d->m_build->setEnabled( false ); connect( d->m_build, &QAction::triggered, this, &ProjectManagerViewPlugin::buildProjectItems ); actionCollection()->addAction( "project_build", d->m_build ); d->m_install = new QAction( i18n("Install Selection"), this ); d->m_install->setIconText( i18n("Install") ); d->m_install->setIcon(QIcon::fromTheme("run-build-install")); actionCollection()->setDefaultShortcut( d->m_install, Qt::SHIFT + Qt::Key_F8 ); d->m_install->setEnabled( false ); connect( d->m_install, &QAction::triggered, this, &ProjectManagerViewPlugin::installProjectItems ); actionCollection()->addAction( "project_install", d->m_install ); d->m_clean = new QAction( i18n("Clean Selection"), this ); d->m_clean->setIconText( i18n("Clean") ); d->m_clean->setIcon(QIcon::fromTheme("run-build-clean")); d->m_clean->setEnabled( false ); connect( d->m_clean, &QAction::triggered, this, &ProjectManagerViewPlugin::cleanProjectItems ); actionCollection()->addAction( "project_clean", d->m_clean ); d->m_configure = new QAction( i18n("Configure Selection"), this ); d->m_configure->setMenuRole( QAction::NoRole ); // OSX: Be explicit about role, prevent hiding due to conflict with "Preferences..." menu item d->m_configure->setIconText( i18n("Configure") ); d->m_configure->setIcon(QIcon::fromTheme("run-build-configure")); d->m_configure->setEnabled( false ); connect( d->m_configure, &QAction::triggered, this, &ProjectManagerViewPlugin::configureProjectItems ); actionCollection()->addAction( "project_configure", d->m_configure ); d->m_prune = new QAction( i18n("Prune Selection"), this ); d->m_prune->setIconText( i18n("Prune") ); d->m_prune->setIcon(QIcon::fromTheme("run-build-prune")); d->m_prune->setEnabled( false ); connect( d->m_prune, &QAction::triggered, this, &ProjectManagerViewPlugin::pruneProjectItems ); actionCollection()->addAction( "project_prune", d->m_prune ); // only add the action so that its known in the actionCollection // and so that it's shortcut etc. pp. is restored // apparently that is not possible to be done in the view itself *sigh* actionCollection()->addAction( "locate_document" ); setXMLFile( "kdevprojectmanagerview.rc" ); d->factory = new KDevProjectManagerViewFactory( this ); core()->uiController()->addToolView( i18n("Projects"), d->factory ); connect(core()->selectionController(), &ISelectionController::selectionChanged, this, &ProjectManagerViewPlugin::updateActionState); connect(ICore::self()->projectController()->buildSetModel(), &KDevelop::ProjectBuildSetModel::rowsInserted, this, &ProjectManagerViewPlugin::updateFromBuildSetChange); connect(ICore::self()->projectController()->buildSetModel(), &KDevelop::ProjectBuildSetModel::rowsRemoved, this, &ProjectManagerViewPlugin::updateFromBuildSetChange); connect(ICore::self()->projectController()->buildSetModel(), &KDevelop::ProjectBuildSetModel::modelReset, this, &ProjectManagerViewPlugin::updateFromBuildSetChange); } void ProjectManagerViewPlugin::updateFromBuildSetChange() { updateActionState( core()->selectionController()->currentSelection() ); } void ProjectManagerViewPlugin::updateActionState( KDevelop::Context* ctx ) { bool isEmpty = ICore::self()->projectController()->buildSetModel()->items().isEmpty(); if( isEmpty ) { isEmpty = !ctx || ctx->type() != Context::ProjectItemContext || dynamic_cast( ctx )->items().isEmpty(); } d->m_build->setEnabled( !isEmpty ); d->m_install->setEnabled( !isEmpty ); d->m_clean->setEnabled( !isEmpty ); d->m_configure->setEnabled( !isEmpty ); d->m_prune->setEnabled( !isEmpty ); } ProjectManagerViewPlugin::~ProjectManagerViewPlugin() { delete d; } void ProjectManagerViewPlugin::unload() { qCDebug(PLUGIN_PROJECTMANAGERVIEW) << "unloading manager view"; core()->uiController()->removeToolView(d->factory); } ContextMenuExtension ProjectManagerViewPlugin::contextMenuExtension( KDevelop::Context* context ) { if( context->type() != KDevelop::Context::ProjectItemContext ) return IPlugin::contextMenuExtension( context ); KDevelop::ProjectItemContext* ctx = dynamic_cast( context ); QList items = ctx->items(); d->ctxProjectItemList.clear(); if( items.isEmpty() ) return IPlugin::contextMenuExtension( context ); //TODO: also needs: removeTarget, removeFileFromTarget, runTargetsFromContextMenu ContextMenuExtension menuExt; bool needsCreateFile = true; bool needsCreateFolder = true; bool needsCloseProjects = true; bool needsBuildItems = true; bool needsFolderItems = true; bool needsRemoveAndRename = true; bool needsRemoveTargetFiles = true; bool needsPaste = true; //needsCreateFile if there is one item and it's a folder or target needsCreateFile &= (items.count() == 1) && (items.first()->folder() || items.first()->target()); //needsCreateFolder if there is one item and it's a folder needsCreateFolder &= (items.count() == 1) && (items.first()->folder()); needsPaste = needsCreateFolder; foreach( ProjectBaseItem* item, items ) { d->ctxProjectItemList << item->index(); //needsBuildItems if items are limited to targets and buildfolders needsBuildItems &= item->target() || item->type() == ProjectBaseItem::BuildFolder; //needsCloseProjects if items are limited to top level folders (Project Folders) needsCloseProjects &= item->folder() && !item->folder()->parent(); //needsFolderItems if items are limited to folders needsFolderItems &= (bool)item->folder(); //needsRemove if items are limited to non-top-level folders or files that don't belong to targets needsRemoveAndRename &= (item->folder() && item->parent()) || (item->file() && !item->parent()->target()); //needsRemoveTargets if items are limited to file items with target parents needsRemoveTargetFiles &= (item->file() && item->parent()->target()); } if ( needsCreateFile ) { QAction* action = new QAction( i18n( "Create File" ), this ); action->setIcon(QIcon::fromTheme("document-new")); connect( action, &QAction::triggered, this, &ProjectManagerViewPlugin::createFileFromContextMenu ); menuExt.addAction( ContextMenuExtension::FileGroup, action ); } if ( needsCreateFolder ) { QAction* action = new QAction( i18n( "Create Folder" ), this ); action->setIcon(QIcon::fromTheme("folder-new")); connect( action, &QAction::triggered, this, &ProjectManagerViewPlugin::createFolderFromContextMenu ); menuExt.addAction( ContextMenuExtension::FileGroup, action ); } if ( needsBuildItems ) { QAction* action = new QAction( i18nc( "@action", "Build" ), this ); action->setIcon(QIcon::fromTheme("run-build")); connect( action, &QAction::triggered, this, &ProjectManagerViewPlugin::buildItemsFromContextMenu ); menuExt.addAction( ContextMenuExtension::BuildGroup, action ); action = new QAction( i18nc( "@action", "Install" ), this ); action->setIcon(QIcon::fromTheme("run-install")); connect( action, &QAction::triggered, this, &ProjectManagerViewPlugin::installItemsFromContextMenu ); menuExt.addAction( ContextMenuExtension::BuildGroup, action ); action = new QAction( i18nc( "@action", "Clean" ), this ); action->setIcon(QIcon::fromTheme("run-clean")); connect( action, &QAction::triggered, this, &ProjectManagerViewPlugin::cleanItemsFromContextMenu ); menuExt.addAction( ContextMenuExtension::BuildGroup, action ); action = new QAction( i18n( "Add to Build Set" ), this ); action->setIcon(QIcon::fromTheme("list-add")); connect( action, &QAction::triggered, this, &ProjectManagerViewPlugin::addItemsFromContextMenuToBuildset ); menuExt.addAction( ContextMenuExtension::BuildGroup, action ); } if ( needsCloseProjects ) { QAction* close = new QAction( i18np( "Close Project", "Close Projects", items.count() ), this ); close->setIcon(QIcon::fromTheme("project-development-close")); connect( close, &QAction::triggered, this, &ProjectManagerViewPlugin::closeProjects ); menuExt.addAction( ContextMenuExtension::ProjectGroup, close ); } if ( needsFolderItems ) { QAction* action = new QAction( i18n( "Reload" ), this ); action->setIcon(QIcon::fromTheme("view-refresh")); connect( action, &QAction::triggered, this, &ProjectManagerViewPlugin::reloadFromContextMenu ); menuExt.addAction( ContextMenuExtension::FileGroup, action ); } if ( needsRemoveAndRename ) { QAction* remove = new QAction( i18n( "Remove" ), this ); remove->setIcon(QIcon::fromTheme("user-trash")); connect( remove, &QAction::triggered, this, &ProjectManagerViewPlugin::removeFromContextMenu ); menuExt.addAction( ContextMenuExtension::FileGroup, remove ); QAction* rename = new QAction( i18n( "Rename" ), this ); rename->setIcon(QIcon::fromTheme("edit-rename")); connect( rename, &QAction::triggered, this, &ProjectManagerViewPlugin::renameItemFromContextMenu ); menuExt.addAction( ContextMenuExtension::FileGroup, rename ); } if ( needsRemoveTargetFiles ) { QAction* remove = new QAction( i18n( "Remove From Target" ), this ); remove->setIcon(QIcon::fromTheme("user-trash")); connect( remove, &QAction::triggered, this, &ProjectManagerViewPlugin::removeTargetFilesFromContextMenu ); menuExt.addAction( ContextMenuExtension::FileGroup, remove ); } { QAction* copy = KStandardAction::copy(this, SLOT(copyFromContextMenu()), this); copy->setShortcutContext(Qt::WidgetShortcut); menuExt.addAction( ContextMenuExtension::FileGroup, copy ); } if (needsPaste) { QAction* paste = KStandardAction::paste(this, SLOT(pasteFromContextMenu()), this); paste->setShortcutContext(Qt::WidgetShortcut); menuExt.addAction( ContextMenuExtension::FileGroup, paste ); } return menuExt; } void ProjectManagerViewPlugin::closeProjects() { QList projectsToClose; ProjectModel* model = ICore::self()->projectController()->projectModel(); foreach( const QModelIndex& index, d->ctxProjectItemList ) { KDevelop::ProjectBaseItem* item = model->itemFromIndex(index); if( !projectsToClose.contains( item->project() ) ) { projectsToClose << item->project(); } } d->ctxProjectItemList.clear(); foreach( KDevelop::IProject* proj, projectsToClose ) { core()->projectController()->closeProject( proj ); } } void ProjectManagerViewPlugin::installItemsFromContextMenu() { runBuilderJob( BuilderJob::Install, itemsFromIndexes(d->ctxProjectItemList) ); d->ctxProjectItemList.clear(); } void ProjectManagerViewPlugin::cleanItemsFromContextMenu() { runBuilderJob( BuilderJob::Clean, itemsFromIndexes( d->ctxProjectItemList ) ); d->ctxProjectItemList.clear(); } void ProjectManagerViewPlugin::buildItemsFromContextMenu() { runBuilderJob( BuilderJob::Build, itemsFromIndexes( d->ctxProjectItemList ) ); d->ctxProjectItemList.clear(); } QList ProjectManagerViewPlugin::collectAllProjects() { QList items; foreach( KDevelop::IProject* project, core()->projectController()->projects() ) { items << project->projectItem(); } return items; } void ProjectManagerViewPlugin::buildAllProjects() { runBuilderJob( BuilderJob::Build, collectAllProjects() ); } QList ProjectManagerViewPlugin::collectItems() { QList items; QList buildItems = ICore::self()->projectController()->buildSetModel()->items(); if( !buildItems.isEmpty() ) { foreach( const BuildItem& buildItem, buildItems ) { if( ProjectBaseItem* item = buildItem.findItem() ) { items << item; } } } else { KDevelop::ProjectItemContext* ctx = dynamic_cast(ICore::self()->selectionController()->currentSelection()); items = ctx->items(); } return items; } void ProjectManagerViewPlugin::runBuilderJob( BuilderJob::BuildType type, QList items ) { BuilderJob* builder = new BuilderJob; builder->addItems( type, items ); builder->updateJobName(); ICore::self()->uiController()->registerStatus(new JobStatus(builder)); ICore::self()->runController()->registerJob( builder ); } void ProjectManagerViewPlugin::installProjectItems() { runBuilderJob( KDevelop::BuilderJob::Install, collectItems() ); } void ProjectManagerViewPlugin::pruneProjectItems() { runBuilderJob( KDevelop::BuilderJob::Prune, collectItems() ); } void ProjectManagerViewPlugin::configureProjectItems() { runBuilderJob( KDevelop::BuilderJob::Configure, collectItems() ); } void ProjectManagerViewPlugin::cleanProjectItems() { runBuilderJob( KDevelop::BuilderJob::Clean, collectItems() ); } void ProjectManagerViewPlugin::buildProjectItems() { runBuilderJob( KDevelop::BuilderJob::Build, collectItems() ); } void ProjectManagerViewPlugin::addItemsFromContextMenuToBuildset( ) { foreach( KDevelop::ProjectBaseItem* item, itemsFromIndexes( d->ctxProjectItemList )) { ICore::self()->projectController()->buildSetModel()->addProjectItem( item ); } } void ProjectManagerViewPlugin::runTargetsFromContextMenu( ) { foreach( KDevelop::ProjectBaseItem* item, itemsFromIndexes( d->ctxProjectItemList )) { KDevelop::ProjectExecutableTargetItem* t=item->executable(); if(t) { qCDebug(PLUGIN_PROJECTMANAGERVIEW) << "Running target: " << t->text() << t->builtUrl(); } } } void ProjectManagerViewPlugin::projectConfiguration( ) { if( !d->ctxProjectItemList.isEmpty() ) { ProjectModel* model = ICore::self()->projectController()->projectModel(); core()->projectController()->configureProject( model->itemFromIndex(d->ctxProjectItemList.at( 0 ))->project() ); } } void ProjectManagerViewPlugin::reloadFromContextMenu( ) { QList< KDevelop::ProjectFolderItem* > folders; foreach( KDevelop::ProjectBaseItem* item, itemsFromIndexes( d->ctxProjectItemList ) ) { if ( item->folder() ) { // since reloading should be recursive, only pass the upper-most items bool found = false; foreach ( KDevelop::ProjectFolderItem* existing, folders ) { if ( existing->path().isParentOf(item->folder()->path()) ) { // simply skip this child found = true; break; } else if ( item->folder()->path().isParentOf(existing->path()) ) { // remove the child in the list and add the current item instead folders.removeOne(existing); // continue since there could be more than one existing child } } if ( !found ) { folders << item->folder(); } } } foreach( KDevelop::ProjectFolderItem* folder, folders ) { folder->project()->projectFileManager()->reload(folder); } } void ProjectManagerViewPlugin::createFolderFromContextMenu( ) { foreach( KDevelop::ProjectBaseItem* item, itemsFromIndexes( d->ctxProjectItemList )) { if ( item->folder() ) { QWidget* window(ICore::self()->uiController()->activeMainWindow()->window()); QString name = QInputDialog::getText ( window, i18n ( "Create Folder in %1", item->folder()->path().pathOrUrl() ), i18n ( "Folder Name" ) ); if (!name.isEmpty()) { item->project()->projectFileManager()->addFolder( Path(item->path(), name), item->folder() ); } } } } void ProjectManagerViewPlugin::removeFromContextMenu() { removeItems(itemsFromIndexes( d->ctxProjectItemList )); } void ProjectManagerViewPlugin::removeItems(const QList< ProjectBaseItem* >& items) { if (items.isEmpty()) { return; } //copy the list of selected items and sort it to guarantee parents will come before children QList sortedItems = items; std::sort(sortedItems.begin(), sortedItems.end(), ProjectBaseItem::pathLessThan); Path lastFolder; QMap< IProjectFileManager*, QList > filteredItems; QStringList itemPaths; foreach( KDevelop::ProjectBaseItem* item, sortedItems ) { if (item->isProjectRoot()) { continue; } else if (item->folder() || item->file()) { //make sure no children of folders that will be deleted are listed if (lastFolder.isParentOf(item->path())) { continue; } else if (item->folder()) { lastFolder = item->path(); } IProjectFileManager* manager = item->project()->projectFileManager(); if (manager) { filteredItems[manager] << item; itemPaths << item->path().pathOrUrl(); } } } if (filteredItems.isEmpty()) { return; } if (KMessageBox::warningYesNoList( QApplication::activeWindow(), i18np("Do you really want to delete this item?", "Do you really want to delete these %1 items?", itemPaths.size()), itemPaths, i18n("Delete Files"), KStandardGuiItem::del(), KStandardGuiItem::cancel() ) == KMessageBox::No) { return; } //Go though projectmanagers, have them remove the files and folders that they own QMap< IProjectFileManager*, QList >::iterator it; for (it = filteredItems.begin(); it != filteredItems.end(); ++it) { Q_ASSERT(it.key()); it.key()->removeFilesAndFolders(it.value()); } } void ProjectManagerViewPlugin::removeTargetFilesFromContextMenu() { QList items = itemsFromIndexes( d->ctxProjectItemList ); QMap< IBuildSystemManager*, QList > itemsByBuildSystem; foreach(ProjectBaseItem *item, items) itemsByBuildSystem[item->project()->buildSystemManager()].append(item->file()); QMap< IBuildSystemManager*, QList >::iterator it; for (it = itemsByBuildSystem.begin(); it != itemsByBuildSystem.end(); ++it) it.key()->removeFilesFromTargets(it.value()); } void ProjectManagerViewPlugin::renameItemFromContextMenu() { renameItems(itemsFromIndexes( d->ctxProjectItemList )); } void ProjectManagerViewPlugin::renameItems(const QList< ProjectBaseItem* >& items) { if (items.isEmpty()) { return; } QWidget* window = ICore::self()->uiController()->activeMainWindow()->window(); foreach( KDevelop::ProjectBaseItem* item, items ) { if ((item->type()!=ProjectBaseItem::BuildFolder && item->type()!=ProjectBaseItem::Folder && item->type()!=ProjectBaseItem::File) || !item->parent()) { continue; } const QString src = item->text(); //Change QInputDialog->KFileSaveDialog? QString name = QInputDialog::getText( window, i18n("Rename..."), i18n("New name for '%1':", item->text()), QLineEdit::Normal, item->text() ); if (!name.isEmpty() && name != src) { ProjectBaseItem::RenameStatus status = item->rename( name ); switch(status) { case ProjectBaseItem::RenameOk: break; case ProjectBaseItem::ExistingItemSameName: KMessageBox::error(window, i18n("There is already a file named '%1'", name)); break; case ProjectBaseItem::ProjectManagerRenameFailed: KMessageBox::error(window, i18n("Could not rename '%1'", name)); break; case ProjectBaseItem::InvalidNewName: KMessageBox::error(window, i18n("'%1' is not a valid file name", name)); break; } } } } ProjectFileItem* createFile(const ProjectFolderItem* item) { QWidget* window = ICore::self()->uiController()->activeMainWindow()->window(); QString name = QInputDialog::getText(window, i18n("Create File in %1", item->path().pathOrUrl()), i18n("File name:")); if(name.isEmpty()) return 0; ProjectFileItem* ret = item->project()->projectFileManager()->addFile( Path(item->path(), name), item->folder() ); if (ret) { ICore::self()->documentController()->openDocument( ret->path().toUrl() ); } return ret; } void ProjectManagerViewPlugin::createFileFromContextMenu( ) { foreach( KDevelop::ProjectBaseItem* item, itemsFromIndexes( d->ctxProjectItemList ) ) { if ( item->folder() ) { createFile(item->folder()); } else if ( item->target() ) { ProjectFolderItem* folder=dynamic_cast(item->parent()); if(folder) { ProjectFileItem* f=createFile(folder); if(f) item->project()->buildSystemManager()->addFilesToTarget(QList() << f, item->target()); } } } } void ProjectManagerViewPlugin::copyFromContextMenu() { KDevelop::ProjectItemContext* ctx = dynamic_cast(ICore::self()->selectionController()->currentSelection()); QList urls; foreach (ProjectBaseItem* item, ctx->items()) { if (item->folder() || item->file()) { urls << item->path().toUrl(); } } qCDebug(PLUGIN_PROJECTMANAGERVIEW) << urls; if (!urls.isEmpty()) { QMimeData* data = new QMimeData; data->setUrls(urls); qApp->clipboard()->setMimeData(data); } } void ProjectManagerViewPlugin::pasteFromContextMenu() { KDevelop::ProjectItemContext* ctx = dynamic_cast(ICore::self()->selectionController()->currentSelection()); if (ctx->items().count() != 1) return; //do nothing if multiple or none items are selected ProjectBaseItem* destItem = ctx->items().first(); if (!destItem->folder()) return; //do nothing if the target is not a directory const QMimeData* data = qApp->clipboard()->mimeData(); qCDebug(PLUGIN_PROJECTMANAGERVIEW) << data->urls(); const Path::List paths = toPathList(data->urls()); bool success = destItem->project()->projectFileManager()->copyFilesAndFolders(paths, destItem->folder()); if (success) { ProjectManagerViewItemContext* viewCtx = dynamic_cast(ICore::self()->selectionController()->currentSelection()); if (viewCtx) { //expand target folder viewCtx->view()->expandItem(destItem); //and select new items QList newItems; foreach (const Path &path, paths) { const Path targetPath(destItem->path(), path.lastPathSegment()); foreach (ProjectBaseItem *item, destItem->children()) { if (item->path() == targetPath) { newItems << item; } } } viewCtx->view()->selectItems(newItems); } } } #include "projectmanagerviewplugin.moc" diff --git a/plugins/projectmanagerview/projectmanagerviewplugin.h b/plugins/projectmanagerview/projectmanagerviewplugin.h index d2d7109073..5c50286e52 100644 --- a/plugins/projectmanagerview/projectmanagerviewplugin.h +++ b/plugins/projectmanagerview/projectmanagerviewplugin.h @@ -1,98 +1,98 @@ /* This file is part of KDevelop Copyright 2004 Roberto Raggi Copyright 2007 Andreas Pakulat 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 KDEVPLATFORM_PLUGIN_PROJECTMANAGERVIEWPLUGIN_H #define KDEVPLATFORM_PLUGIN_PROJECTMANAGERVIEWPLUGIN_H #include #include #include #include class ProjectBuildSetModel; namespace KDevelop { class ProjectBaseItem; class ProjectBuilder; class ProjectFileItem; class ProjectFolderItem; class ProjectTargetItem; class IProjectBuilder; class IProject; class ContextMenuExtension; class Context; } class ProjectManagerView; class ProjectManagerViewPlugin: public KDevelop::IPlugin { Q_OBJECT public: public: explicit ProjectManagerViewPlugin(QObject *parent, const QVariantList & = QVariantList() ); - virtual ~ProjectManagerViewPlugin(); + ~ProjectManagerViewPlugin() override; // Plugin methods - virtual void unload() override; + void unload() override; KDevelop::ContextMenuExtension contextMenuExtension( KDevelop::Context* ) override; void removeItems(const QList& items); void renameItems(const QList< KDevelop::ProjectBaseItem* >& items); public Q_SLOTS: void buildProjectItems(); void installProjectItems(); void cleanProjectItems(); void copyFromContextMenu(); void pasteFromContextMenu(); protected Q_SLOTS: void closeProjects(); void buildItemsFromContextMenu(); void installItemsFromContextMenu(); void cleanItemsFromContextMenu(); void configureProjectItems(); void pruneProjectItems(); void buildAllProjects(); void addItemsFromContextMenuToBuildset(); void projectConfiguration(); void runTargetsFromContextMenu(); void reloadFromContextMenu(); void createFolderFromContextMenu(); void createFileFromContextMenu(); void removeFromContextMenu(); void removeTargetFilesFromContextMenu(); void renameItemFromContextMenu(); void updateActionState( KDevelop::Context* ctx ); void updateFromBuildSetChange(); private: QList recurseAndFetchCheckedItems( KDevelop::ProjectBaseItem* item ); QList collectItems(); QList collectAllProjects(); void runBuilderJob( KDevelop::BuilderJob::BuildType type, QList items ); class ProjectManagerViewPluginPrivate* const d; }; #endif diff --git a/plugins/projectmanagerview/projectmodelitemdelegate.h b/plugins/projectmanagerview/projectmodelitemdelegate.h index bb5aa3a874..e89a2288ec 100644 --- a/plugins/projectmanagerview/projectmodelitemdelegate.h +++ b/plugins/projectmanagerview/projectmodelitemdelegate.h @@ -1,41 +1,41 @@ /* This file is part of KDevelop Copyright 2013 Aleix Pol 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 KDEVPLATFORM_PLUGIN_PROJECTMODELITEMDELEGATE_H #define KDEVPLATFORM_PLUGIN_PROJECTMODELITEMDELEGATE_H #include class ProjectModelItemDelegate : public QItemDelegate { Q_OBJECT public: explicit ProjectModelItemDelegate(QObject* parent = 0); - virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; - virtual void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QString &text) const override; private: void drawBranchName(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QString& branchName) const; void drawStyledBackground(QPainter* painter, const QStyleOptionViewItem& option) const; }; #endif // KDEVPLATFORM_PLUGIN_PROJECTMODELITEMDELEGATE_H diff --git a/plugins/projectmanagerview/projectmodelsaver.h b/plugins/projectmanagerview/projectmodelsaver.h index a991144b7f..342858f600 100644 --- a/plugins/projectmanagerview/projectmodelsaver.h +++ b/plugins/projectmanagerview/projectmodelsaver.h @@ -1,54 +1,54 @@ /* This file is part of KDevelop Copyright 2012 Andrew Fuller 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 KDEVPLATFORM_PLUGIN_PROJECTMODELSAVER_H #define KDEVPLATFORM_PLUGIN_PROJECTMODELSAVER_H #include namespace KDevelop { class IProject; class ProjectModelSaver: public KConfigViewStateSaver { Q_OBJECT public: ProjectModelSaver(); /** * If @p project is non-null, only files from that project will * be handled by @code index{From,To}ConfigString @endcode. * * For other files, an invalid index or empty string is be returned. */ void setProject(IProject* project); - virtual QModelIndex indexFromConfigString(const QAbstractItemModel *model, const QString &key) const override; + QModelIndex indexFromConfigString(const QAbstractItemModel *model, const QString &key) const override; - virtual QString indexToConfigString(const QModelIndex &index) const override; + QString indexToConfigString(const QModelIndex &index) const override; private: IProject* m_project; }; } #endif // KDEVPLATFORM_PLUGIN_PROJECTMODELSAVER_H diff --git a/plugins/projectmanagerview/projecttreeview.cpp b/plugins/projectmanagerview/projecttreeview.cpp index b86d73345c..0544e4abe0 100644 --- a/plugins/projectmanagerview/projecttreeview.cpp +++ b/plugins/projectmanagerview/projecttreeview.cpp @@ -1,461 +1,461 @@ /* This file is part of KDevelop Copyright 2005 Roberto Raggi Copyright 2007 Andreas Pakulat Copyright 2009 Aleix Pol 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 "projecttreeview.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "projectmanagerviewplugin.h" #include "projectmodelsaver.h" #include "projectmodelitemdelegate.h" #include "debug.h" #include #include #include #include #include using namespace KDevelop; namespace { const char settingsConfigGroup[] = "ProjectTreeView"; QList fileItemsWithin(const QList& items) { QList fileItems; fileItems.reserve(items.size()); foreach(ProjectBaseItem* item, items) { if (ProjectFileItem *file = item->file()) fileItems.append(file); else if (item->folder()) fileItems.append(fileItemsWithin(item->children())); } return fileItems; } QList topLevelItemsWithin(QList items) { std::sort(items.begin(), items.end(), ProjectBaseItem::pathLessThan); Path lastFolder; for (int i = items.size() - 1; i >= 0; --i) { if (lastFolder.isParentOf(items[i]->path())) items.removeAt(i); else if (items[i]->folder()) lastFolder = items[i]->path(); } return items; } template void filterDroppedItems(QList &items, ProjectBaseItem* dest) { for (int i = items.size() - 1; i >= 0; --i) { //No drag and drop from and to same location if (items[i]->parent() == dest) items.removeAt(i); //No moving between projects (technically feasible if the projectmanager is the same though...) else if (items[i]->project() != dest->project()) items.removeAt(i); } } //TODO test whether this could be replaced by projectbuildsetwidget.cpp::showContextMenu_appendActions void popupContextMenu_appendActions(QMenu& menu, const QList& actions) { menu.addActions(actions); menu.addSeparator(); } } ProjectTreeView::ProjectTreeView( QWidget *parent ) : QTreeView( parent ), m_ctxProject( 0 ) { header()->hide(); setEditTriggers( QAbstractItemView::EditKeyPressed ); setContextMenuPolicy( Qt::CustomContextMenu ); setSelectionMode( QAbstractItemView::ExtendedSelection ); setIndentation(10); setDragEnabled(true); setDragDropMode(QAbstractItemView::InternalMove); setAutoScroll(true); setAutoExpandDelay(300); setItemDelegate(new ProjectModelItemDelegate(this)); connect( this, &ProjectTreeView::customContextMenuRequested, this, &ProjectTreeView::popupContextMenu ); connect( this, &ProjectTreeView::activated, this, &ProjectTreeView::slotActivated ); connect( ICore::self(), &ICore::aboutToShutdown, this, &ProjectTreeView::aboutToShutdown); connect( ICore::self()->projectController(), &IProjectController::projectOpened, this, &ProjectTreeView::restoreState ); connect( ICore::self()->projectController(), &IProjectController::projectClosing, this, &ProjectTreeView::saveState ); restoreState(); } ProjectTreeView::~ProjectTreeView() { } ProjectBaseItem* ProjectTreeView::itemAtPos(QPoint pos) { return indexAt(pos).data(ProjectModel::ProjectItemRole).value(); } void ProjectTreeView::dropEvent(QDropEvent* event) { ProjectItemContext* selectionCtxt = static_cast(KDevelop::ICore::self()->selectionController()->currentSelection()); ProjectBaseItem* destItem = itemAtPos(event->pos()); if (destItem && (dropIndicatorPosition() == AboveItem || dropIndicatorPosition() == BelowItem)) destItem = destItem->parent(); if (selectionCtxt && destItem) { if (ProjectFolderItem *folder = destItem->folder()) { QMenu dropMenu(this); QString seq = QKeySequence( Qt::ShiftModifier ).toString(); seq.chop(1); // chop superfluous '+' QAction* move = new QAction(i18n( "&Move Here" ) + '\t' + seq, &dropMenu); move->setIcon(QIcon::fromTheme("go-jump")); dropMenu.addAction(move); seq = QKeySequence( Qt::ControlModifier ).toString(); seq.chop(1); QAction* copy = new QAction(i18n( "&Copy Here" ) + '\t' + seq, &dropMenu); copy->setIcon(QIcon::fromTheme("edit-copy")); dropMenu.addAction(copy); dropMenu.addSeparator(); QAction* cancel = new QAction(i18n( "C&ancel" ) + '\t' + QKeySequence( Qt::Key_Escape ).toString(), &dropMenu); cancel->setIcon(QIcon::fromTheme("process-stop")); dropMenu.addAction(cancel); QAction *executedAction = 0; Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers(); if (modifiers == Qt::ControlModifier) { executedAction = copy; } else if (modifiers == Qt::ShiftModifier) { executedAction = move; } else { executedAction = dropMenu.exec(this->mapToGlobal(event->pos())); } QList usefulItems = topLevelItemsWithin(selectionCtxt->items()); filterDroppedItems(usefulItems, destItem); Path::List paths; foreach (ProjectBaseItem* i, usefulItems) { paths << i->path(); } bool success = false; if (executedAction == copy) { - success =~ destItem->project()->projectFileManager()->copyFilesAndFolders(paths, folder); + success = destItem->project()->projectFileManager()->copyFilesAndFolders(paths, folder); } else if (executedAction == move) { - success =~ destItem->project()->projectFileManager()->moveFilesAndFolders(usefulItems, folder); + success = destItem->project()->projectFileManager()->moveFilesAndFolders(usefulItems, folder); } if (success) { //expand target folder expand( mapFromItem(folder)); //and select new items QItemSelection selection; foreach (const Path &path, paths) { const Path targetPath(folder->path(), path.lastPathSegment()); foreach (ProjectBaseItem *item, folder->children()) { if (item->path() == targetPath) { QModelIndex indx = mapFromItem( item ); selection.append(QItemSelectionRange(indx, indx)); setCurrentIndex(indx); } } } selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect); } } else if (destItem->target() && destItem->project()->buildSystemManager()) { QMenu dropMenu(this); QString seq = QKeySequence( Qt::ControlModifier ).toString(); seq.chop(1); QAction* addToTarget = new QAction(i18n( "&Add to Target" ) + '\t' + seq, &dropMenu); addToTarget->setIcon(QIcon::fromTheme("edit-link")); dropMenu.addAction(addToTarget); dropMenu.addSeparator(); QAction* cancel = new QAction(i18n( "C&ancel" ) + '\t' + QKeySequence( Qt::Key_Escape ).toString(), &dropMenu); cancel->setIcon(QIcon::fromTheme("process-stop")); dropMenu.addAction(cancel); QAction *executedAction = 0; Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers(); if (modifiers == Qt::ControlModifier) { executedAction = addToTarget; } else { executedAction = dropMenu.exec(this->mapToGlobal(event->pos())); } if (executedAction == addToTarget) { QList usefulItems = fileItemsWithin(selectionCtxt->items()); filterDroppedItems(usefulItems, destItem); destItem->project()->buildSystemManager()->addFilesToTarget(usefulItems, destItem->target()); } } } event->accept(); } QModelIndex ProjectTreeView::mapFromSource(const QAbstractProxyModel* proxy, const QModelIndex& sourceIdx) { const QAbstractItemModel* next = proxy->sourceModel(); Q_ASSERT(next == sourceIdx.model() || qobject_cast(next)); if(next == sourceIdx.model()) return proxy->mapFromSource(sourceIdx); else { const QAbstractProxyModel* nextProxy = qobject_cast(next); QModelIndex idx = mapFromSource(nextProxy, sourceIdx); Q_ASSERT(idx.model() == nextProxy); return proxy->mapFromSource(idx); } } QModelIndex ProjectTreeView::mapFromItem(const ProjectBaseItem* item) { QModelIndex ret = mapFromSource(qobject_cast(model()), item->index()); Q_ASSERT(ret.model() == model()); return ret; } void ProjectTreeView::slotActivated( const QModelIndex &index ) { if ( QApplication::keyboardModifiers() & Qt::CTRL || QApplication::keyboardModifiers() & Qt::SHIFT ) { // Do not open file when Ctrl or Shift is pressed; that's for selection return; } KDevelop::ProjectBaseItem *item = index.data(ProjectModel::ProjectItemRole).value(); if ( item && item->file() ) { emit activate( item->file()->path() ); } } void ProjectTreeView::popupContextMenu( const QPoint &pos ) { QList itemlist; if ( indexAt(pos).isValid() ) { QModelIndexList indexes = selectionModel()->selectedRows(); foreach( const QModelIndex& index, indexes ) { if ( KDevelop::ProjectBaseItem *item = index.data(ProjectModel::ProjectItemRole).value() ) itemlist << item; } } if( !itemlist.isEmpty() ) { m_ctxProject = itemlist.at(0)->project(); } else { m_ctxProject = 0; } QMenu menu( this ); KDevelop::ProjectItemContextImpl context(itemlist); QList extensions = ICore::self()->pluginController()->queryPluginsForContextMenuExtensions( &context ); QList buildActions; QList vcsActions; QList extActions; QList projectActions; QList fileActions; QList runActions; foreach( const ContextMenuExtension& ext, extensions ) { buildActions += ext.actions(ContextMenuExtension::BuildGroup); fileActions += ext.actions(ContextMenuExtension::FileGroup); projectActions += ext.actions(ContextMenuExtension::ProjectGroup); vcsActions += ext.actions(ContextMenuExtension::VcsGroup); extActions += ext.actions(ContextMenuExtension::ExtensionGroup); runActions += ext.actions(ContextMenuExtension::RunGroup); } popupContextMenu_appendActions(menu, buildActions); popupContextMenu_appendActions(menu, runActions ); popupContextMenu_appendActions(menu, fileActions); popupContextMenu_appendActions(menu, vcsActions); popupContextMenu_appendActions(menu, extActions); if ( !itemlist.isEmpty() && itemlist.size() == 1 && itemlist[0]->folder() && !itemlist[0]->folder()->parent() ) { QAction* projectConfig = new QAction(i18n("Open Configuration..."), this); projectConfig->setIcon(QIcon::fromTheme("configure")); connect( projectConfig, &QAction::triggered, this, &ProjectTreeView::openProjectConfig ); projectActions << projectConfig; } popupContextMenu_appendActions(menu, projectActions); if(!itemlist.isEmpty()) KDevelop::populateParentItemsMenu(itemlist.front(), &menu); if ( !menu.isEmpty() ) { menu.exec( mapToGlobal( pos ) ); } } void ProjectTreeView::openProjectConfig() { if( m_ctxProject ) { IProjectController* ip = ICore::self()->projectController(); ip->configureProject( m_ctxProject ); } } void ProjectTreeView::saveState() { KConfigGroup configGroup( ICore::self()->activeSession()->config(), settingsConfigGroup ); ProjectModelSaver saver; saver.setView( this ); saver.saveState( configGroup ); } void ProjectTreeView::restoreState(IProject* project) { KConfigGroup configGroup( ICore::self()->activeSession()->config(), settingsConfigGroup ); // Saver will delete itself when it is complete. ProjectModelSaver *saver = new ProjectModelSaver; saver->setProject( project ); saver->setView( this ); saver->restoreState( configGroup ); } void ProjectTreeView::aboutToShutdown() { // save all projects, not just the last one that is closed disconnect( ICore::self()->projectController(), &IProjectController::projectClosing, this, &ProjectTreeView::saveState ); saveState(); } bool ProjectTreeView::event(QEvent* event) { if(event->type()==QEvent::ToolTip) { QPoint p = mapFromGlobal(QCursor::pos()); QModelIndex idxView = indexAt(p); ProjectBaseItem* it = idxView.data(ProjectModel::ProjectItemRole).value(); QModelIndex idx; if(it) idx = it->index(); if((m_idx!=idx || !m_tooltip) && it && it->file()) { m_idx=idx; ProjectFileItem* file=it->file(); KDevelop::DUChainReadLocker lock(KDevelop::DUChain::lock()); TopDUContext* top= DUChainUtils::standardContextForUrl(file->path().toUrl()); if(m_tooltip) m_tooltip->close(); if(top) { QWidget* navigationWidget = top->createNavigationWidget(); if( navigationWidget ) { m_tooltip = new KDevelop::NavigationToolTip(this, mapToGlobal(p) + QPoint(40, 0), navigationWidget); m_tooltip->resize( navigationWidget->sizeHint() + QSize(10, 10) ); qCDebug(PLUGIN_PROJECTMANAGERVIEW) << "tooltip size" << m_tooltip->size(); ActiveToolTip::showToolTip(m_tooltip); return true; } } } } return QAbstractItemView::event(event); } void ProjectTreeView::keyPressEvent(QKeyEvent* event) { if (event->key() == Qt::Key_Return && currentIndex().isValid() && state()!=QAbstractItemView::EditingState) { event->accept(); slotActivated(currentIndex()); } else QTreeView::keyPressEvent(event); } void ProjectTreeView::drawBranches(QPainter* painter, const QRect& rect, const QModelIndex& index) const { const bool colorizeByProject = KSharedConfig::openConfig()->group("UiSettings").readEntry("ColorizeByProject", false); if (colorizeByProject) { const auto projectPath = index.data(ProjectModel::ProjectRole).value()->path(); const QColor color = WidgetColorizer::colorForId(qHash(projectPath), palette()); WidgetColorizer::drawBranches(this, painter, rect, index, color); } QTreeView::drawBranches(painter, rect, index); } diff --git a/plugins/projectmanagerview/projecttreeview.h b/plugins/projectmanagerview/projecttreeview.h index 6362ae24a4..36e4e375c2 100644 --- a/plugins/projectmanagerview/projecttreeview.h +++ b/plugins/projectmanagerview/projecttreeview.h @@ -1,82 +1,82 @@ /* This file is part of KDevelop Copyright 2005 Roberto Raggi Copyright 2007 Andreas Pakulat 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 KDEVPLATFORM_PLUGIN_PROJECTTREEVIEW_H #define KDEVPLATFORM_PLUGIN_PROJECTTREEVIEW_H #include #include class QAbstractProxyModel; class QAction; class QItemSelectionModel; class QMouseEvent; namespace KDevelop { class IProject; class ProjectModel; class ProjectBaseItem; class ProjectFolderItem; class ProjectFileItem; class ProjectTargetItem; class ProjectBaseItem; class NavigationToolTip; class Path; } class ProjectTreeView: public QTreeView { Q_OBJECT public: explicit ProjectTreeView( QWidget *parent = 0 ); - virtual ~ProjectTreeView(); + ~ProjectTreeView() override; static QModelIndex mapFromSource(const QAbstractProxyModel* proxy, const QModelIndex& sourceIdx); - virtual bool event(QEvent* event) override; + bool event(QEvent* event) override; Q_SIGNALS: void activate( const KDevelop::Path &url ); protected Q_SLOTS: void slotActivated( const QModelIndex &index ); void popupContextMenu( const QPoint &pos ); void openProjectConfig(); void saveState(); void restoreState(KDevelop::IProject* project = 0); void aboutToShutdown(); protected: - virtual void keyPressEvent(QKeyEvent *event) override; - virtual void dropEvent(QDropEvent* event) override; - virtual void drawBranches(QPainter* painter, const QRect& rect, const QModelIndex& index) const override; + void keyPressEvent(QKeyEvent *event) override; + void dropEvent(QDropEvent* event) override; + void drawBranches(QPainter* painter, const QRect& rect, const QModelIndex& index) const override; private: QModelIndex mapFromItem(const KDevelop::ProjectBaseItem* item); KDevelop::ProjectBaseItem* itemAtPos(QPoint pos); KDevelop::IProject* m_ctxProject; QPointer m_tooltip; QPersistentModelIndex m_idx; }; #endif // KDEVPLATFORM_PLUGIN_PROJECTTREEVIEW_H diff --git a/plugins/projectmanagerview/vcsoverlayproxymodel.h b/plugins/projectmanagerview/vcsoverlayproxymodel.h index 71ea9ef168..1b857f0b3e 100644 --- a/plugins/projectmanagerview/vcsoverlayproxymodel.h +++ b/plugins/projectmanagerview/vcsoverlayproxymodel.h @@ -1,54 +1,54 @@ /* This file is part of KDevelop Copyright 2008 Aleix Pol 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 KDEVPLATFORM_PLUGIN_VCSOVERLAYPROXYMODEL_H #define KDEVPLATFORM_PLUGIN_VCSOVERLAYPROXYMODEL_H #include #include class QUrl; namespace KDevelop { class IProject; class VcsJob; } class VcsOverlayProxyModel : public QIdentityProxyModel { Q_OBJECT public: enum Roles { VcsStatusRole = KDevelop::ProjectModel::LastRole }; explicit VcsOverlayProxyModel(QObject* parent = 0); - virtual QVariant data(const QModelIndex& proxyIndex, int role = Qt::DisplayRole) const override; + QVariant data(const QModelIndex& proxyIndex, int role = Qt::DisplayRole) const override; private slots: void addProject(KDevelop::IProject* p); void removeProject(KDevelop::IProject* p); void repositoryBranchChanged(const QUrl& url); void branchNameReady(KDevelop::VcsJob* job); private: QModelIndex indexFromProject(QObject* project); QHash m_branchName; }; #endif // KDEVPLATFORM_PLUGIN_VCSOVERLAYPROXYMODEL_H diff --git a/plugins/quickopen/actionsquickopenprovider.cpp b/plugins/quickopen/actionsquickopenprovider.cpp index 28e5bf66f1..ec38c4de3e 100644 --- a/plugins/quickopen/actionsquickopenprovider.cpp +++ b/plugins/quickopen/actionsquickopenprovider.cpp @@ -1,127 +1,127 @@ /* * This file is part of KDevelop * * Copyright 2015 Aleix Pol Gonzalez * * 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 "actionsquickopenprovider.h" #include #include #include #include #include #include #include #include using namespace KDevelop; class ActionsQuickOpenItem : public QuickOpenDataBase { public: ActionsQuickOpenItem(const QString &display, QAction* action) : QuickOpenDataBase() , m_action(action) , m_display(display) {} - virtual QString text() const override + QString text() const override { return m_display; } - virtual QString htmlDescription() const override + QString htmlDescription() const override { QString desc = m_action->toolTip(); const QKeySequence shortcut = m_action->shortcut(); if (!shortcut.isEmpty()) { desc = i18nc("description (shortcut)", "%1 (%2)", desc, shortcut.toString()); } return desc; } - virtual bool execute(QString&) override + bool execute(QString&) override { m_action->trigger(); return true; } - virtual QIcon icon() const override + QIcon icon() const override { return m_action->icon(); } private: QAction* m_action; ///needed because it won't have the "E&xit" ampersand QString m_display; }; ActionsQuickOpenProvider::ActionsQuickOpenProvider() { } void ActionsQuickOpenProvider::setFilterText(const QString& text) { if (text.size() < 2) { return; } m_results.clear(); const QList collections = KActionCollection::allCollections(); QRegularExpression mnemonicRx("^(.*)&(.+)$"); for (KActionCollection* c : collections) { QList actions = c->actions(); for(QAction* action : actions) { if (!action->isEnabled()) continue; QString display = action->text(); QRegularExpressionMatch match = mnemonicRx.match(display); if (match.hasMatch()) { display = match.captured(1)+match.captured(2); } if (display.contains(text, Qt::CaseInsensitive)) { m_results += QuickOpenDataPointer(new ActionsQuickOpenItem(display, action)); } } } } uint ActionsQuickOpenProvider::unfilteredItemCount() const { uint ret = 0; QList collections = KActionCollection::allCollections(); foreach(KActionCollection* c, collections) { ret += c->count(); } return ret; } QuickOpenDataPointer ActionsQuickOpenProvider::data(uint row) const { return m_results.at(row); } uint ActionsQuickOpenProvider::itemCount() const { return m_results.count(); } void ActionsQuickOpenProvider::reset() { m_results.clear(); } diff --git a/plugins/quickopen/documentationquickopenprovider.cpp b/plugins/quickopen/documentationquickopenprovider.cpp index 0675aa4c79..f94e46e5da 100644 --- a/plugins/quickopen/documentationquickopenprovider.cpp +++ b/plugins/quickopen/documentationquickopenprovider.cpp @@ -1,145 +1,145 @@ /* * This file is part of KDevelop * * Copyright 2013 Aleix Pol Gonzalez * * 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 "documentationquickopenprovider.h" #include #include #include #include #include #include #include using namespace KDevelop; class DocumentationQuickOpenItem : public QuickOpenDataBase { public: DocumentationQuickOpenItem(const QModelIndex& data, IDocumentationProvider* p) : QuickOpenDataBase() , m_data(data) , m_provider(p) {} - virtual QString text() const override + QString text() const override { return m_data.data().toString(); } - virtual QString htmlDescription() const override + QString htmlDescription() const override { return i18n("Documentation in the %1", m_provider->name()); } - virtual bool execute(QString&) override + bool execute(QString&) override { IDocumentation::Ptr docu = m_provider->documentationForIndex(m_data); if(docu) { ICore::self()->documentationController()->showDocumentation(docu); } return docu; } - virtual QIcon icon() const override + QIcon icon() const override { return m_provider->icon(); } private: QModelIndex m_data; IDocumentationProvider* m_provider; }; namespace { uint recursiveRowCount(const QAbstractItemModel* m, const QModelIndex& idx) { uint rows = m->rowCount(idx); uint ret = rows; for(uint i = 0; i < rows; i++) { ret += recursiveRowCount(m, m->index(i, 0, idx)); } return ret; } void matchingIndexes(const QAbstractItemModel* m, const QString& match, const QModelIndex& idx, QList& ret, int& preferred) { if(m->hasChildren(idx)) { for(int i = 0, rows = m->rowCount(); i < rows; i++) { matchingIndexes(m, match, m->index(i, 0, idx), ret, preferred); } } else { int index = idx.data().toString().indexOf(match, 0, Qt::CaseInsensitive); if(index == 0) { ret.insert(preferred++, idx); } else if(index > 0) { ret.append(idx); } } } } DocumentationQuickOpenProvider::DocumentationQuickOpenProvider() { } void DocumentationQuickOpenProvider::setFilterText(const QString& text) { if(text.size() < 2) { return; } m_results.clear(); int split = 0; QList providers = ICore::self()->documentationController()->documentationProviders(); foreach(IDocumentationProvider* p, providers) { QList idxs; int internalSplit = 0; int i = 0; matchingIndexes(p->indexModel(), text, QModelIndex(), idxs, internalSplit); foreach(const QModelIndex& idx, idxs) { m_results.insert(split+i, QuickOpenDataPointer(new DocumentationQuickOpenItem(idx, p))); i++; } split += internalSplit; } } uint DocumentationQuickOpenProvider::unfilteredItemCount() const { uint ret = 0; QList providers = ICore::self()->documentationController()->documentationProviders(); foreach(IDocumentationProvider* p, providers) { ret += recursiveRowCount(p->indexModel(), QModelIndex()); } return ret; } QuickOpenDataPointer DocumentationQuickOpenProvider::data(uint row) const { return m_results.at(row); } uint DocumentationQuickOpenProvider::itemCount() const { return m_results.size(); } void DocumentationQuickOpenProvider::reset() { m_results.clear(); } diff --git a/plugins/quickopen/expandingtree/expandingdelegate.h b/plugins/quickopen/expandingtree/expandingdelegate.h index e5d31590af..adb84c6c19 100644 --- a/plugins/quickopen/expandingtree/expandingdelegate.h +++ b/plugins/quickopen/expandingtree/expandingdelegate.h @@ -1,93 +1,93 @@ /* This file is part of the KDE libraries and the Kate part. * * Copyright (C) 2006 Hamish Rodda * Copyright (C) 2007 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 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 KDEVPLATFORM_PLUGIN_EXPANDINGDELEGATE_H #define KDEVPLATFORM_PLUGIN_EXPANDINGDELEGATE_H #include #include #include #include class KateRenderer; class KateCompletionWidget; class KateDocument; class KateTextLine; class ExpandingWidgetModel; class QVariant; class QStyleOptionViewItem; /** * This is a delegate that cares, together with ExpandingWidgetModel, about embedded widgets in tree-view. * */ class ExpandingDelegate : public QItemDelegate { Q_OBJECT public: explicit ExpandingDelegate(ExpandingWidgetModel* model, QObject* parent = 0L); // Overridden to create highlighting for current index - virtual void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const override; + void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const override; // Returns the basic size-hint as reported by QItemDelegate QSize basicSizeHint( const QModelIndex& index ) const; ExpandingWidgetModel* model() const; protected: //Called right before paint to allow last-minute changes to the style virtual void adjustStyle( const QModelIndex& index, QStyleOptionViewItem & option ) const; - virtual void drawDisplay ( QPainter * painter, const QStyleOptionViewItem & option, const QRect & rect, const QString & text ) const override; - virtual QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const override; - virtual bool editorEvent ( QEvent * event, QAbstractItemModel * model, const QStyleOptionViewItem & option, const QModelIndex & index ) override; + void drawDisplay ( QPainter * painter, const QStyleOptionViewItem & option, const QRect & rect, const QString & text ) const override; + QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const override; + bool editorEvent ( QEvent * event, QAbstractItemModel * model, const QStyleOptionViewItem & option, const QModelIndex & index ) override; virtual void drawBackground ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const; - virtual void drawDecoration(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QPixmap& pixmap) const override; + void drawDecoration(QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QPixmap& pixmap) const override; //option can be changed virtual QList createHighlighting(const QModelIndex& index, QStyleOptionViewItem& option) const; void adjustRect(QRect& rect) const; /** * Creates a list of FormatRanges as should be returned by createHighlighting from a list of QVariants as described in the kde header ktexteditor/codecompletionmodel.h * */ QList highlightingFromVariantList(const QList& customHighlights) const; //Called when an item was expanded/unexpanded and the height changed virtual void heightChanged() const; //Initializes the style options from the index void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const; mutable int m_currentColumnStart; //Text-offset for custom highlighting, will be applied to m_cachedHighlights(Only highlights starting after this will be used). Shoult be zero of the highlighting is not taken from kate. mutable QList m_currentColumnStarts; mutable QList m_cachedHighlights; mutable Qt::Alignment m_cachedAlignment; mutable QColor m_backgroundColor; mutable QModelIndex m_currentIndex; private: ExpandingWidgetModel* m_model; }; #endif // KDEVPLATFORM_PLUGIN_EXPANDINGDELEGATE_H diff --git a/plugins/quickopen/projectfilequickopen.h b/plugins/quickopen/projectfilequickopen.h index 7da5e63170..097fc7ac0b 100644 --- a/plugins/quickopen/projectfilequickopen.h +++ b/plugins/quickopen/projectfilequickopen.h @@ -1,144 +1,144 @@ /* This file is part of the KDE libraries Copyright (C) 2007 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. */ #ifndef PROJECT_FILE_QUICKOPEN #define PROJECT_FILE_QUICKOPEN #include #include #include #include namespace KDevelop { class IProject; class ProjectFileItem; } class QIcon; /** * Internal data class for the BaseFileDataProvider and ProjectFileData. */ struct ProjectFile { ProjectFile() : outsideOfProject(false) {} KDevelop::Path path; // project root folder url KDevelop::Path projectPath; // indexed url - only set for project files // currently open documents don't use this! KDevelop::IndexedString indexedPath; // true for files which reside outside of the project root // this happens e.g. for generated files in out-of-source build folders bool outsideOfProject; }; inline bool operator<(const ProjectFile& left, const ProjectFile& right) { if (left.outsideOfProject != right.outsideOfProject) { return !left.outsideOfProject; } return left.path < right.path; } Q_DECLARE_TYPEINFO(ProjectFile, Q_MOVABLE_TYPE); /** * The shared data class that is used by the quick open model. */ class ProjectFileData : public KDevelop::QuickOpenDataBase { public: explicit ProjectFileData( const ProjectFile& file ); - virtual QString text() const override; - virtual QString htmlDescription() const override; + QString text() const override; + QString htmlDescription() const override; bool execute( QString& filterText ) override; - virtual bool isExpandable() const override; - virtual QWidget* expandingWidget() const override; + bool isExpandable() const override; + QWidget* expandingWidget() const override; - virtual QIcon icon() const override; + QIcon icon() const override; QList highlighting() const override; QString project() const; private: ProjectFile m_file; }; class BaseFileDataProvider : public KDevelop::QuickOpenDataProviderBase, public KDevelop::PathFilter, public KDevelop::QuickOpenFileSetInterface { Q_OBJECT public: BaseFileDataProvider(); - virtual void setFilterText( const QString& text ) override; - virtual uint itemCount() const override; - virtual uint unfilteredItemCount() const override; - virtual KDevelop::QuickOpenDataPointer data( uint row ) const override; + void setFilterText( const QString& text ) override; + uint itemCount() const override; + uint unfilteredItemCount() const override; + KDevelop::QuickOpenDataPointer data( uint row ) const override; inline KDevelop::Path itemPath( const ProjectFile& data ) const { return data.path; } }; /** * QuickOpen data provider for file-completion using project-files. * * It provides all files from all open projects except currently opened ones. */ class ProjectFileDataProvider : public BaseFileDataProvider { Q_OBJECT public: ProjectFileDataProvider(); - virtual void reset() override; - virtual QSet files() const override; + void reset() override; + QSet files() const override; private slots: void projectClosing( KDevelop::IProject* ); void projectOpened( KDevelop::IProject* ); void fileAddedToSet( KDevelop::ProjectFileItem* ); void fileRemovedFromSet( KDevelop::ProjectFileItem* ); private: // project files sorted by their url // this is done so we can limit ourselves to a relatively fast // filtering without any expensive sorting in reset(). QList m_projectFiles; }; /** * Quick open data provider for currently opened documents. */ class OpenFilesDataProvider : public BaseFileDataProvider { Q_OBJECT public: - virtual void reset() override; - virtual QSet files() const override; + void reset() override; + QSet files() const override; }; #endif diff --git a/plugins/quickopen/quickopenmodel.h b/plugins/quickopen/quickopenmodel.h index 0e7e4f0472..ab933c8ee0 100644 --- a/plugins/quickopen/quickopenmodel.h +++ b/plugins/quickopen/quickopenmodel.h @@ -1,132 +1,132 @@ /* This file is part of the KDE libraries Copyright (C) 2007 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. */ #ifndef KDEVPLATFORM_PLUGIN_QUICKOPENMODEL_H #define KDEVPLATFORM_PLUGIN_QUICKOPENMODEL_H #include #include #include #include #include #include #include "expandingtree/expandingwidgetmodel.h" class QuickOpenModel : public ExpandingWidgetModel { Q_OBJECT public: explicit QuickOpenModel( QWidget* parent ); void registerProvider( const QStringList& scopes, const QStringList& type, KDevelop::QuickOpenDataProviderBase* provider ); /** * Remove provider. * @param provider The provider to remove * @return Whether a provider was removed. If false, the provider was not attached. * */ bool removeProvider( KDevelop::QuickOpenDataProviderBase* provider ); ///Returns a list of all scopes that a registered through some providers QStringList allScopes() const; ///Returns a list of all types that a registered through some providers QStringList allTypes() const; /** * @param items The list of items that should be used. * @param scopesThe list of scopes that should be used. * When this is called, the state is restart()ed. * */ void enableProviders( const QStringList& items, const QStringList& scopes ); ///Reset all providers, unexpand everything, empty caches. void restart(bool keepFilterText = false); QModelIndex index( int, int, const QModelIndex& parent ) const override; QModelIndex parent( const QModelIndex& ) const override; int rowCount( const QModelIndex& ) const override; int unfilteredRowCount() const; int columnCount() const; int columnCount( const QModelIndex& ) const override; QVariant data( const QModelIndex&, int ) const override; /** * Tries to execute the item currently selected. * Returns true if the quickopen-dialog should be closed. * @param filterText Should be the current content of the filter line-edit. * * If this returns false, and filterText was changed, the change must be put * into the line-edit. That way items may execute by changing the content * of the line-edit. * */ bool execute( const QModelIndex& index, QString& filterText ); //The expandingwidgetmodel needs access to the tree-view void setTreeView( QTreeView* view ); - virtual QTreeView* treeView() const override; + QTreeView* treeView() const override; virtual QSet fileSet() const; ///This value will be added to the height of all created expanding-widgets void setExpandingWidgetHeightIncrease(int pixels); public slots: void textChanged( const QString& str ); private slots: void destroyed( QObject* obj ); void resetTimer(); void restart_internal( bool keepFilterText ); private: - virtual bool indexIsItem(const QModelIndex& index) const override; + bool indexIsItem(const QModelIndex& index) const override; - virtual int contextMatchQuality(const QModelIndex & index) const override; + int contextMatchQuality(const QModelIndex & index) const override; KDevelop::QuickOpenDataPointer getItem( int row, bool noReset = false ) const; typedef QHash DataList; mutable DataList m_cachedData; QTreeView* m_treeView; QTimer* m_resetTimer; struct ProviderEntry { ProviderEntry() : enabled(false) { } bool enabled; QSet scopes; QSet types; KDevelop::QuickOpenDataProviderBase* provider; }; //typedef QMultiMap< QString, ProviderEntry > ProviderMap; typedef QList ProviderList; QList m_providers; QString m_filterText; int m_expandingWidgetHeightIncrease; mutable int m_resetBehindRow; QSet m_enabledItems; QSet m_enabledScopes; }; #endif diff --git a/plugins/quickopen/quickopenplugin.cpp b/plugins/quickopen/quickopenplugin.cpp index 602575691e..509623df04 100644 --- a/plugins/quickopen/quickopenplugin.cpp +++ b/plugins/quickopen/quickopenplugin.cpp @@ -1,1550 +1,1550 @@ /* * This file is part of KDevelop * * Copyright 2007 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 "quickopenplugin.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "expandingtree/expandingdelegate.h" #include "ui_quickopen.h" #include "quickopenmodel.h" #include "projectfilequickopen.h" #include "projectitemquickopen.h" #include "declarationlistquickopen.h" #include "documentationquickopenprovider.h" #include "actionsquickopenprovider.h" #include "debug.h" #include #include #include #include #include #include #include #include #include Q_LOGGING_CATEGORY(PLUGIN_QUICKOPEN, "kdevplatform.plugins.quickopen") using namespace KDevelop; const bool noHtmlDestriptionInOutline = true; class QuickOpenWidgetCreator { public: virtual ~QuickOpenWidgetCreator() { } virtual QuickOpenWidget* createWidget() = 0; virtual QString objectNameForLine() = 0; virtual void widgetShown() { } }; class StandardQuickOpenWidgetCreator : public QuickOpenWidgetCreator { public: StandardQuickOpenWidgetCreator(const QStringList& items, const QStringList& scopes) : m_items(items) , m_scopes(scopes) { } - virtual QString objectNameForLine() override { + QString objectNameForLine() override { return "Quickopen"; } void setItems(const QStringList& scopes, const QStringList& items) { m_scopes = scopes; m_items = items; } - virtual QuickOpenWidget* createWidget() override { + QuickOpenWidget* createWidget() override { QStringList useItems = m_items; if(useItems.isEmpty()) useItems = QuickOpenPlugin::self()->lastUsedItems; QStringList useScopes = m_scopes; if(useScopes.isEmpty()) useScopes = QuickOpenPlugin::self()->lastUsedScopes; return new QuickOpenWidget( i18n("Quick Open"), QuickOpenPlugin::self()->m_model, QuickOpenPlugin::self()->lastUsedItems, useScopes, false, true ); } QStringList m_items; QStringList m_scopes; }; class QuickOpenDelegate : public ExpandingDelegate { public: QuickOpenDelegate(ExpandingWidgetModel* model, QObject* parent = 0L) : ExpandingDelegate(model, parent) { } - virtual QList createHighlighting(const QModelIndex& index, QStyleOptionViewItem& option) const override { + QList createHighlighting(const QModelIndex& index, QStyleOptionViewItem& option) const override { QList highlighting = index.data(KTextEditor::CodeCompletionModel::CustomHighlight).toList(); if(!highlighting.isEmpty()) return highlightingFromVariantList(highlighting); return ExpandingDelegate::createHighlighting( index, option ); } }; class OutlineFilter : public DUChainUtils::DUChainItemFilter { public: enum OutlineMode { Functions, FunctionsAndClasses }; OutlineFilter(QList& _items, OutlineMode _mode = FunctionsAndClasses) : items(_items), mode(_mode) { } - virtual bool accept(Declaration* decl) override { + bool accept(Declaration* decl) override { if(decl->range().isEmpty()) return false; bool collectable = mode == Functions ? decl->isFunctionDeclaration() : (decl->isFunctionDeclaration() || (decl->internalContext() && decl->internalContext()->type() == DUContext::Class)); if (collectable) { DUChainItem item; item.m_item = IndexedDeclaration(decl); item.m_text = decl->toString(); items << item; return true; } else return false; } - virtual bool accept(DUContext* ctx) override { + bool accept(DUContext* ctx) override { if(ctx->type() == DUContext::Class || ctx->type() == DUContext::Namespace || ctx->type() == DUContext::Global || ctx->type() == DUContext::Other || ctx->type() == DUContext::Helper ) return true; else return false; } QList& items; OutlineMode mode; }; K_PLUGIN_FACTORY_WITH_JSON(KDevQuickOpenFactory, "kdevquickopen.json", registerPlugin();) Declaration* cursorDeclaration() { KTextEditor::View* view = ICore::self()->documentController()->activeTextDocumentView(); if(!view) return 0; KDevelop::DUChainReadLocker lock( DUChain::lock() ); return DUChainUtils::declarationForDefinition( DUChainUtils::itemUnderCursor( view->document()->url(), KTextEditor::Cursor(view->cursorPosition()) ) ); } ///The first definition that belongs to a context that surrounds the current cursor Declaration* cursorContextDeclaration() { KTextEditor::View* view = ICore::self()->documentController()->activeTextDocumentView(); if(!view) return 0; KDevelop::DUChainReadLocker lock( DUChain::lock() ); TopDUContext* ctx = DUChainUtils::standardContextForUrl(view->document()->url()); if(!ctx) return 0; KTextEditor::Cursor cursor(view->cursorPosition()); DUContext* subCtx = ctx->findContext(ctx->transformToLocalRevision(cursor)); while(subCtx && !subCtx->owner()) subCtx = subCtx->parentContext(); Declaration* definition = 0; if(!subCtx || !subCtx->owner()) definition = DUChainUtils::declarationInLine(cursor, ctx); else definition = subCtx->owner(); if(!definition) return 0; return definition; } //Returns only the name, no template-parameters or scope QString cursorItemText() { KDevelop::DUChainReadLocker lock( DUChain::lock() ); Declaration* decl = cursorDeclaration(); if(!decl) return QString(); IDocument* doc = ICore::self()->documentController()->activeDocument(); if(!doc) return QString(); TopDUContext* context = DUChainUtils::standardContextForUrl( doc->url() ); if( !context ) { qCDebug(PLUGIN_QUICKOPEN) << "Got no standard context"; return QString(); } AbstractType::Ptr t = decl->abstractType(); IdentifiedType* idType = dynamic_cast(t.data()); if( idType && idType->declaration(context) ) decl = idType->declaration(context); if(!decl->qualifiedIdentifier().isEmpty()) return decl->qualifiedIdentifier().last().identifier().str(); return QString(); } QuickOpenLineEdit* QuickOpenPlugin::createQuickOpenLineWidget() { return new QuickOpenLineEdit(new StandardQuickOpenWidgetCreator(QStringList(), QStringList())); } void QuickOpenWidget::showStandardButtons(bool show) { if(show) { o.okButton->show(); o.cancelButton->show(); }else{ o.okButton->hide(); o.cancelButton->hide(); } } QuickOpenWidget::QuickOpenWidget( QString title, QuickOpenModel* model, const QStringList& initialItems, const QStringList& initialScopes, bool listOnly, bool noSearchField ) : m_model(model), m_expandedTemporary(false) { m_filterTimer.setSingleShot(true); connect(&m_filterTimer, &QTimer::timeout, this, &QuickOpenWidget::applyFilter); Q_UNUSED( title ); o.setupUi( this ); o.list->header()->hide(); o.list->setRootIsDecorated( false ); o.list->setVerticalScrollMode( QAbstractItemView::ScrollPerItem ); connect(o.list->verticalScrollBar(), &QScrollBar::valueChanged, m_model, &QuickOpenModel::placeExpandingWidgets); o.searchLine->setFocus(); o.list->setItemDelegate( new QuickOpenDelegate( m_model, o.list ) ); if(!listOnly) { QStringList allTypes = m_model->allTypes(); QStringList allScopes = m_model->allScopes(); QMenu* itemsMenu = new QMenu; foreach( const QString &type, allTypes ) { QAction* action = new QAction(type, itemsMenu); action->setCheckable(true); action->setChecked(initialItems.isEmpty() || initialItems.contains( type )); connect( action, &QAction::toggled, this, &QuickOpenWidget::updateProviders, Qt::QueuedConnection ); itemsMenu->addAction(action); } o.itemsButton->setMenu(itemsMenu); QMenu* scopesMenu = new QMenu; foreach( const QString &scope, allScopes ) { QAction* action = new QAction(scope, scopesMenu); action->setCheckable(true); action->setChecked(initialScopes.isEmpty() || initialScopes.contains( scope ) ); connect( action, &QAction::toggled, this, &QuickOpenWidget::updateProviders, Qt::QueuedConnection ); scopesMenu->addAction(action); } o.scopesButton->setMenu(scopesMenu); }else{ o.list->setFocusPolicy(Qt::StrongFocus); o.scopesButton->hide(); o.itemsButton->hide(); o.label->hide(); o.label_2->hide(); } showSearchField(!noSearchField); o.okButton->hide(); o.cancelButton->hide(); o.searchLine->installEventFilter( this ); o.list->installEventFilter( this ); o.list->setFocusPolicy(Qt::NoFocus); o.scopesButton->setFocusPolicy(Qt::NoFocus); o.itemsButton->setFocusPolicy(Qt::NoFocus); connect( o.searchLine, &QLineEdit::textChanged, this, &QuickOpenWidget::textChanged ); connect( o.list, &ExpandingTree::doubleClicked, this, &QuickOpenWidget::doubleClicked ); connect(o.okButton, &QPushButton::clicked, this, &QuickOpenWidget::accept); connect(o.okButton, &QPushButton::clicked, this, &QuickOpenWidget::ready); connect(o.cancelButton, &QPushButton::clicked, this, &QuickOpenWidget::ready); updateProviders(); updateTimerInterval(true); // no need to call this, it's done by updateProviders already // m_model->restart(); } void QuickOpenWidget::updateTimerInterval(bool cheapFilterChange) { const int MAX_ITEMS = 10000; if ( cheapFilterChange && m_model->rowCount(QModelIndex()) < MAX_ITEMS ) { // cheap change and there are currently just a few items, // so apply filter instantly m_filterTimer.setInterval(0); } else if ( m_model->unfilteredRowCount() < MAX_ITEMS ) { // not a cheap change, but there are generally // just a few items in the list: apply filter instantly m_filterTimer.setInterval(0); } else { // otherwise use a timer to prevent sluggishness while typing m_filterTimer.setInterval(300); } } void QuickOpenWidget::showEvent(QShowEvent* e) { QWidget::showEvent(e); // The column width only has an effect _after_ the widget has been shown o.list->setColumnWidth( 0, 20 ); } void QuickOpenWidget::setAlternativeSearchField(QLineEdit* alterantiveSearchField) { o.searchLine = alterantiveSearchField; o.searchLine->installEventFilter( this ); connect( o.searchLine, &QLineEdit::textChanged, this, &QuickOpenWidget::textChanged ); } void QuickOpenWidget::showSearchField(bool b) { if(b){ o.searchLine->show(); o.searchLabel->show(); }else{ o.searchLine->hide(); o.searchLabel->hide(); } } void QuickOpenWidget::prepareShow() { o.list->setModel( 0 ); o.list->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); m_model->setTreeView( o.list ); o.list->setModel( m_model ); m_filterTimer.stop(); m_filter = QString(); if (!m_preselectedText.isEmpty()) { o.searchLine->setText(m_preselectedText); o.searchLine->selectAll(); } m_model->restart(false); connect( o.list->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &QuickOpenWidget::callRowSelected ); connect( o.list->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QuickOpenWidget::callRowSelected ); } void QuickOpenWidgetDialog::run() { m_widget->prepareShow(); m_dialog->show(); } QuickOpenWidget::~QuickOpenWidget() { m_model->setTreeView( 0 ); } QuickOpenWidgetDialog::QuickOpenWidgetDialog(QString title, QuickOpenModel* model, const QStringList& initialItems, const QStringList& initialScopes, bool listOnly, bool noSearchField) { m_widget = new QuickOpenWidget(title, model, initialItems, initialScopes, listOnly, noSearchField); // the QMenu might close on esc and we want to close the whole dialog then connect( m_widget, &QuickOpenWidget::aboutToHide, this, &QuickOpenWidgetDialog::deleteLater ); m_dialog = new QDialog( ICore::self()->uiController()->activeMainWindow() ); m_dialog->resize(QSize(800, 400)); m_dialog->setWindowTitle(title); QVBoxLayout* layout = new QVBoxLayout(m_dialog); layout->addWidget(m_widget); m_widget->showStandardButtons(true); connect(m_widget, &QuickOpenWidget::ready, m_dialog, &QDialog::close); connect( m_dialog, &QDialog::accepted, m_widget, &QuickOpenWidget::accept ); } QuickOpenWidgetDialog::~QuickOpenWidgetDialog() { delete m_dialog; } void QuickOpenWidget::setPreselectedText(const QString& text) { m_preselectedText = text; } void QuickOpenWidget::updateProviders() { if(QAction* action = qobject_cast(sender())) { QMenu* menu = qobject_cast(action->parentWidget()); if(menu) { menu->show(); menu->setActiveAction(action); } } QStringList checkedItems; if(o.itemsButton->menu()) { foreach( QObject* obj, o.itemsButton->menu()->children() ) { QAction* box = qobject_cast( obj ); if( box ) { if( box->isChecked() ) checkedItems << box->text().remove('&'); } } o.itemsButton->setText(checkedItems.join(", ")); } QStringList checkedScopes; if(o.scopesButton->menu()) { foreach( QObject* obj, o.scopesButton->menu()->children() ) { QAction* box = qobject_cast( obj ); if( box ) { if( box->isChecked() ) checkedScopes << box->text().remove('&'); } } o.scopesButton->setText(checkedScopes.join(", ")); } emit itemsChanged( checkedItems ); emit scopesChanged( checkedScopes ); m_model->enableProviders( checkedItems, checkedScopes ); } void QuickOpenWidget::textChanged( const QString& str ) { // "cheap" when something was just appended to the current filter updateTimerInterval(str.startsWith(m_filter)); m_filter = str; m_filterTimer.start(); } void QuickOpenWidget::applyFilter() { m_model->textChanged( m_filter ); QModelIndex currentIndex = m_model->index(0, 0, QModelIndex()); o.list->selectionModel()->setCurrentIndex( currentIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows | QItemSelectionModel::Current ); callRowSelected(); } void QuickOpenWidget::callRowSelected() { QModelIndex currentIndex = o.list->selectionModel()->currentIndex(); if( currentIndex.isValid() ) m_model->rowSelected( currentIndex ); else qCDebug(PLUGIN_QUICKOPEN) << "current index is not valid"; } void QuickOpenWidget::accept() { QString filterText = o.searchLine->text(); m_model->execute( o.list->currentIndex(), filterText ); } void QuickOpenWidget::doubleClicked ( const QModelIndex & index ) { // crash guard: https://bugs.kde.org/show_bug.cgi?id=297178 o.list->setCurrentIndex(index); QMetaObject::invokeMethod(this, "accept", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "ready", Qt::QueuedConnection); } bool QuickOpenWidget::eventFilter ( QObject * watched, QEvent * event ) { QKeyEvent *keyEvent = dynamic_cast(event); if( event->type() == QEvent::KeyRelease ) { if(keyEvent->key() == Qt::Key_Alt) { if((m_expandedTemporary && m_altDownTime.msecsTo( QTime::currentTime() ) > 300) || (!m_expandedTemporary && m_altDownTime.msecsTo( QTime::currentTime() ) < 300 && m_hadNoCommandSinceAlt)) { //Unexpand the item QModelIndex row = o.list->selectionModel()->currentIndex(); if( row.isValid() ) { row = row.sibling( row.row(), 0 ); if(m_model->isExpanded( row )) m_model->setExpanded( row, false ); } } m_expandedTemporary = false; } } if( event->type() == QEvent::KeyPress ) { m_hadNoCommandSinceAlt = false; if(keyEvent->key() == Qt::Key_Alt) { m_hadNoCommandSinceAlt = true; //Expand QModelIndex row = o.list->selectionModel()->currentIndex(); if( row.isValid() ) { row = row.sibling( row.row(), 0 ); m_altDownTime = QTime::currentTime(); if(!m_model->isExpanded( row )) { m_expandedTemporary = true; m_model->setExpanded( row, true ); } } } switch( keyEvent->key() ) { case Qt::Key_Tab: if ( keyEvent->modifiers() == Qt::NoModifier ) { // Tab should work just like Down QCoreApplication::sendEvent(o.list, new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier)); QCoreApplication::sendEvent(o.list, new QKeyEvent(QEvent::KeyRelease, Qt::Key_Down, Qt::NoModifier)); return true; } break; case Qt::Key_Backtab: if ( keyEvent->modifiers() == Qt::ShiftModifier ) { // Shift + Tab should work just like Up QCoreApplication::sendEvent(o.list, new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier)); QCoreApplication::sendEvent(o.list, new QKeyEvent(QEvent::KeyRelease, Qt::Key_Up, Qt::NoModifier)); return true; } break; case Qt::Key_Down: case Qt::Key_Up: { if( keyEvent->modifiers() == Qt::AltModifier ) { QWidget* w = m_model->expandingWidget(o.list->selectionModel()->currentIndex()); if( KDevelop::QuickOpenEmbeddedWidgetInterface* interface = dynamic_cast( w ) ){ if( keyEvent->key() == Qt::Key_Down ) interface->down(); else interface->up(); return true; } return false; } } case Qt::Key_PageUp: case Qt::Key_PageDown: if(watched == o.list ) return false; QApplication::sendEvent( o.list, event ); //callRowSelected(); return true; case Qt::Key_Left: { //Expand/unexpand if( keyEvent->modifiers() == Qt::AltModifier ) { //Eventually Send action to the widget QWidget* w = m_model->expandingWidget(o.list->selectionModel()->currentIndex()); if( KDevelop::QuickOpenEmbeddedWidgetInterface* interface = dynamic_cast( w ) ){ interface->previous(); return true; } } else { QModelIndex row = o.list->selectionModel()->currentIndex(); if( row.isValid() ) { row = row.sibling( row.row(), 0 ); if( m_model->isExpanded( row ) ) { m_model->setExpanded( row, false ); return true; } } } return false; } case Qt::Key_Right: { //Expand/unexpand if( keyEvent->modifiers() == Qt::AltModifier ) { //Eventually Send action to the widget QWidget* w = m_model->expandingWidget(o.list->selectionModel()->currentIndex()); if( KDevelop::QuickOpenEmbeddedWidgetInterface* interface = dynamic_cast( w ) ){ interface->next(); return true; } } else { QModelIndex row = o.list->selectionModel()->currentIndex(); if( row.isValid() ) { row = row.sibling( row.row(), 0 ); if( !m_model->isExpanded( row ) ) { m_model->setExpanded( row, true ); return true; } } } return false; } case Qt::Key_Return: case Qt::Key_Enter: { if (m_filterTimer.isActive()) { m_filterTimer.stop(); applyFilter(); } if( keyEvent->modifiers() == Qt::AltModifier ) { //Eventually Send action to the widget QWidget* w = m_model->expandingWidget(o.list->selectionModel()->currentIndex()); if( KDevelop::QuickOpenEmbeddedWidgetInterface* interface = dynamic_cast( w ) ){ interface->accept(); return true; } } else { QString filterText = o.searchLine->text(); //Safety: Track whether this object is deleted. When execute() is called, a dialog may be opened, //which kills the quickopen widget. QPointer stillExists(this); if( m_model->execute( o.list->currentIndex(), filterText ) ) { if(!stillExists) return true; if(!(keyEvent->modifiers() & Qt::ShiftModifier)) emit ready(); } else { //Maybe the filter-text was changed: if( filterText != o.searchLine->text() ) { o.searchLine->setText( filterText ); } } } return true; } } } return false; } QuickOpenLineEdit* QuickOpenPlugin::quickOpenLine(QString name) { QList< QuickOpenLineEdit* > lines = ICore::self()->uiController()->activeMainWindow()->findChildren(name); foreach(QuickOpenLineEdit* line, lines) { if(line->isVisible()) { return line; } } return 0; } static QuickOpenPlugin* staticQuickOpenPlugin = 0; QuickOpenPlugin* QuickOpenPlugin::self() { return staticQuickOpenPlugin; } void QuickOpenPlugin::createActionsForMainWindow(Sublime::MainWindow* /*window*/, QString& xmlFile, KActionCollection& actions) { xmlFile ="kdevquickopen.rc"; QAction* quickOpen = actions.addAction("quick_open"); quickOpen->setText( i18n("&Quick Open") ); quickOpen->setIcon( QIcon::fromTheme("quickopen") ); actions.setDefaultShortcut( quickOpen, Qt::CTRL | Qt::ALT | Qt::Key_Q ); connect(quickOpen, &QAction::triggered, this, &QuickOpenPlugin::quickOpen); QAction* quickOpenFile = actions.addAction("quick_open_file"); quickOpenFile->setText( i18n("Quick Open &File") ); quickOpenFile->setIcon( QIcon::fromTheme("quickopen-file") ); actions.setDefaultShortcut( quickOpenFile, Qt::CTRL | Qt::ALT | Qt::Key_O ); connect(quickOpenFile, &QAction::triggered, this, &QuickOpenPlugin::quickOpenFile); QAction* quickOpenClass = actions.addAction("quick_open_class"); quickOpenClass->setText( i18n("Quick Open &Class") ); quickOpenClass->setIcon( QIcon::fromTheme("quickopen-class") ); actions.setDefaultShortcut( quickOpenClass, Qt::CTRL | Qt::ALT | Qt::Key_C ); connect(quickOpenClass, &QAction::triggered, this, &QuickOpenPlugin::quickOpenClass); QAction* quickOpenFunction = actions.addAction("quick_open_function"); quickOpenFunction->setText( i18n("Quick Open &Function") ); quickOpenFunction->setIcon( QIcon::fromTheme("quickopen-function") ); actions.setDefaultShortcut( quickOpenFunction, Qt::CTRL | Qt::ALT | Qt::Key_M ); connect(quickOpenFunction, &QAction::triggered, this, &QuickOpenPlugin::quickOpenFunction); QAction* quickOpenAlreadyOpen = actions.addAction("quick_open_already_open"); quickOpenAlreadyOpen->setText( i18n("Quick Open &Already Open File") ); quickOpenAlreadyOpen->setIcon( QIcon::fromTheme("quickopen-file") ); connect(quickOpenAlreadyOpen, &QAction::triggered, this, &QuickOpenPlugin::quickOpenOpenFile); QAction* quickOpenDocumentation = actions.addAction("quick_open_documentation"); quickOpenDocumentation->setText( i18n("Quick Open &Documentation") ); quickOpenDocumentation->setIcon( QIcon::fromTheme("quickopen-documentation") ); actions.setDefaultShortcut( quickOpenDocumentation, Qt::CTRL | Qt::ALT | Qt::Key_D ); connect(quickOpenDocumentation, &QAction::triggered, this, &QuickOpenPlugin::quickOpenDocumentation); QAction* quickOpenActions = actions.addAction("quick_open_actions"); quickOpenActions->setText( i18n("Quick Open &Actions") ); actions.setDefaultShortcut( quickOpenActions, Qt::CTRL | Qt::ALT | Qt::Key_A); connect(quickOpenActions, &QAction::triggered, this, &QuickOpenPlugin::quickOpenActions); m_quickOpenDeclaration = actions.addAction("quick_open_jump_declaration"); m_quickOpenDeclaration->setText( i18n("Jump to Declaration") ); m_quickOpenDeclaration->setIcon( QIcon::fromTheme("go-jump-declaration" ) ); actions.setDefaultShortcut( m_quickOpenDeclaration, Qt::CTRL | Qt::Key_Period ); connect(m_quickOpenDeclaration, &QAction::triggered, this, &QuickOpenPlugin::quickOpenDeclaration, Qt::QueuedConnection); m_quickOpenDefinition = actions.addAction("quick_open_jump_definition"); m_quickOpenDefinition->setText( i18n("Jump to Definition") ); m_quickOpenDefinition->setIcon( QIcon::fromTheme("go-jump-definition" ) ); actions.setDefaultShortcut( m_quickOpenDefinition, Qt::CTRL | Qt::Key_Comma ); connect(m_quickOpenDefinition, &QAction::triggered, this, &QuickOpenPlugin::quickOpenDefinition, Qt::QueuedConnection); QWidgetAction* quickOpenLine = new QWidgetAction(this); quickOpenLine->setText( i18n("Embedded Quick Open") ); // actions.setDefaultShortcut( quickOpenLine, Qt::CTRL | Qt::ALT | Qt::Key_E ); // connect(quickOpenLine, SIGNAL(triggered(bool)), this, SLOT(quickOpenLine(bool))); quickOpenLine->setDefaultWidget(createQuickOpenLineWidget()); actions.addAction("quick_open_line", quickOpenLine); QAction* quickOpenNextFunction = actions.addAction("quick_open_next_function"); quickOpenNextFunction->setText( i18n("Next Function") ); actions.setDefaultShortcut( quickOpenNextFunction, Qt::CTRL| Qt::ALT | Qt::Key_PageDown ); connect(quickOpenNextFunction, &QAction::triggered, this, &QuickOpenPlugin::nextFunction); QAction* quickOpenPrevFunction = actions.addAction("quick_open_prev_function"); quickOpenPrevFunction->setText( i18n("Previous Function") ); actions.setDefaultShortcut( quickOpenPrevFunction, Qt::CTRL| Qt::ALT | Qt::Key_PageUp ); connect(quickOpenPrevFunction, &QAction::triggered, this, &QuickOpenPlugin::previousFunction); QAction* quickOpenNavigateFunctions = actions.addAction("quick_open_outline"); quickOpenNavigateFunctions->setText( i18n("Outline") ); actions.setDefaultShortcut( quickOpenNavigateFunctions, Qt::CTRL| Qt::ALT | Qt::Key_N ); connect(quickOpenNavigateFunctions, &QAction::triggered, this, &QuickOpenPlugin::quickOpenNavigateFunctions); } QuickOpenPlugin::QuickOpenPlugin(QObject *parent, const QVariantList&) : KDevelop::IPlugin("kdevquickopen", parent) { staticQuickOpenPlugin = this; KDEV_USE_EXTENSION_INTERFACE( KDevelop::IQuickOpen ) m_model = new QuickOpenModel( 0 ); KConfigGroup quickopengrp = KSharedConfig::openConfig()->group("QuickOpen"); lastUsedScopes = quickopengrp.readEntry("SelectedScopes", QStringList() << i18n("Project") << i18n("Includes") << i18n("Includers") << i18n("Currently Open") ); lastUsedItems = quickopengrp.readEntry("SelectedItems", QStringList() ); { m_openFilesData = new OpenFilesDataProvider(); QStringList scopes, items; scopes << i18n("Currently Open"); items << i18n("Files"); m_model->registerProvider( scopes, items, m_openFilesData ); } { m_projectFileData = new ProjectFileDataProvider(); QStringList scopes, items; scopes << i18n("Project"); items << i18n("Files"); m_model->registerProvider( scopes, items, m_projectFileData ); } { m_projectItemData = new ProjectItemDataProvider(this); QStringList scopes, items; scopes << i18n("Project"); items << ProjectItemDataProvider::supportedItemTypes(); m_model->registerProvider( scopes, items, m_projectItemData ); } { m_documentationItemData = new DocumentationQuickOpenProvider; QStringList scopes, items; scopes << i18n("Includes"); items << i18n("Documentation"); m_model->registerProvider( scopes, items, m_documentationItemData ); } { m_actionsItemData = new ActionsQuickOpenProvider; QStringList scopes, items; scopes << i18n("Includes"); items << i18n("Actions"); m_model->registerProvider( scopes, items, m_actionsItemData ); } } QuickOpenPlugin::~QuickOpenPlugin() { freeModel(); delete m_model; delete m_projectFileData; delete m_projectItemData; delete m_openFilesData; delete m_documentationItemData; delete m_actionsItemData; } void QuickOpenPlugin::unload() { } ContextMenuExtension QuickOpenPlugin::contextMenuExtension(Context* context) { KDevelop::ContextMenuExtension menuExt = KDevelop::IPlugin::contextMenuExtension( context ); KDevelop::DeclarationContext *codeContext = dynamic_cast(context); if (!codeContext) return menuExt; DUChainReadLocker readLock; Declaration* decl(codeContext->declaration().data()); if (decl) { const bool isDef = FunctionDefinition::definition(decl); if (codeContext->use().isValid() || !isDef) { menuExt.addAction( KDevelop::ContextMenuExtension::ExtensionGroup, m_quickOpenDeclaration); } if(isDef) { menuExt.addAction( KDevelop::ContextMenuExtension::ExtensionGroup, m_quickOpenDefinition); } } return menuExt; } void QuickOpenPlugin::showQuickOpen(const QStringList& items) { if(!freeModel()) return; QStringList initialItems = items; QStringList useScopes = lastUsedScopes; if (!useScopes.contains(i18n("Currently Open"))) useScopes << i18n("Currently Open"); showQuickOpenWidget(initialItems, useScopes, false); } void QuickOpenPlugin::showQuickOpen( ModelTypes modes ) { if(!freeModel()) return; QStringList initialItems; if( modes & Files || modes & OpenFiles ) initialItems << i18n("Files"); if( modes & Functions ) initialItems << i18n("Functions"); if( modes & Classes ) initialItems << i18n("Classes"); QStringList useScopes; if ( modes != OpenFiles ) useScopes = lastUsedScopes; if((modes & OpenFiles) && !useScopes.contains(i18n("Currently Open"))) useScopes << i18n("Currently Open"); bool preselectText = (!(modes & Files) || modes == QuickOpenPlugin::All); showQuickOpenWidget(initialItems, useScopes, preselectText); } void QuickOpenPlugin::showQuickOpenWidget(const QStringList& items, const QStringList& scopes, bool preselectText) { QuickOpenWidgetDialog* dialog = new QuickOpenWidgetDialog( i18n("Quick Open"), m_model, items, scopes ); m_currentWidgetHandler = dialog; if (preselectText) { KDevelop::IDocument *currentDoc = core()->documentController()->activeDocument(); if (currentDoc && currentDoc->isTextDocument()) { QString preselected = currentDoc->textSelection().isEmpty() ? currentDoc->textWord() : currentDoc->textDocument()->text(currentDoc->textSelection()); dialog->widget()->setPreselectedText(preselected); } } connect( dialog->widget(), &QuickOpenWidget::scopesChanged, this, &QuickOpenPlugin::storeScopes ); //Not connecting itemsChanged to storeItems, as showQuickOpen doesn't use lastUsedItems and so shouldn't store item changes //connect( dialog->widget(), SIGNAL(itemsChanged(QStringList)), this, SLOT(storeItems(QStringList)) ); dialog->widget()->o.itemsButton->setEnabled(false); if(quickOpenLine()) { quickOpenLine()->showWithWidget(dialog->widget()); dialog->deleteLater(); }else{ dialog->run(); } } void QuickOpenPlugin::storeScopes( const QStringList& scopes ) { lastUsedScopes = scopes; KConfigGroup grp = KSharedConfig::openConfig()->group("QuickOpen"); grp.writeEntry( "SelectedScopes", scopes ); } void QuickOpenPlugin::storeItems( const QStringList& items ) { lastUsedItems = items; KConfigGroup grp = KSharedConfig::openConfig()->group("QuickOpen"); grp.writeEntry( "SelectedItems", items ); } void QuickOpenPlugin::quickOpen() { if(quickOpenLine()) //Same as clicking on Quick Open quickOpenLine()->setFocus(); else showQuickOpen( All ); } void QuickOpenPlugin::quickOpenFile() { showQuickOpen( (ModelTypes)(Files | OpenFiles) ); } void QuickOpenPlugin::quickOpenFunction() { showQuickOpen( Functions ); } void QuickOpenPlugin::quickOpenClass() { showQuickOpen( Classes ); } void QuickOpenPlugin::quickOpenOpenFile() { showQuickOpen( OpenFiles ); } void QuickOpenPlugin::quickOpenDocumentation() { showQuickOpenWidget(QStringList(i18n("Documentation")), QStringList(i18n("Includes")), true); } void QuickOpenPlugin::quickOpenActions() { showQuickOpenWidget(QStringList(i18n("Actions")), QStringList(i18n("Includes")), true); } QSet QuickOpenPlugin::fileSet() const { return m_model->fileSet(); } void QuickOpenPlugin::registerProvider( const QStringList& scope, const QStringList& type, KDevelop::QuickOpenDataProviderBase* provider ) { m_model->registerProvider( scope, type, provider ); } bool QuickOpenPlugin::removeProvider( KDevelop::QuickOpenDataProviderBase* provider ) { m_model->removeProvider( provider ); return true; } void QuickOpenPlugin::quickOpenDeclaration() { if(jumpToSpecialObject()) return; KDevelop::DUChainReadLocker lock( DUChain::lock() ); Declaration* decl = cursorDeclaration(); if(!decl) { qCDebug(PLUGIN_QUICKOPEN) << "Found no declaration for cursor, cannot jump"; return; } decl->activateSpecialization(); IndexedString u = decl->url(); KTextEditor::Cursor c = decl->rangeInCurrentRevision().start(); if(u.isEmpty()) { qCDebug(PLUGIN_QUICKOPEN) << "Got empty url for declaration" << decl->toString(); return; } lock.unlock(); core()->documentController()->openDocument(u.toUrl(), c); } QWidget* QuickOpenPlugin::specialObjectNavigationWidget() const { KTextEditor::View* view = ICore::self()->documentController()->activeTextDocumentView(); if( !view ) return 0; QUrl url = ICore::self()->documentController()->activeDocument()->url(); const auto languages = ICore::self()->languageController()->languagesForUrl(url); foreach (const auto& language, languages) { QWidget* w = language->specialLanguageObjectNavigationWidget(url, KTextEditor::Cursor(view->cursorPosition()) ); if(w) return w; } return 0; } QPair QuickOpenPlugin::specialObjectJumpPosition() const { KTextEditor::View* view = ICore::self()->documentController()->activeTextDocumentView(); if( !view ) return qMakePair(QUrl(), KTextEditor::Cursor()); QUrl url = ICore::self()->documentController()->activeDocument()->url(); const auto languages = ICore::self()->languageController()->languagesForUrl(url); foreach (const auto& language, languages) { QPair pos = language->specialLanguageObjectJumpCursor(url, KTextEditor::Cursor(view->cursorPosition()) ); if(pos.second.isValid()) { return pos; } } return qMakePair(QUrl(), KTextEditor::Cursor::invalid()); } bool QuickOpenPlugin::jumpToSpecialObject() { QPair pos = specialObjectJumpPosition(); if(pos.second.isValid()) { if(pos.first.isEmpty()) { qCDebug(PLUGIN_QUICKOPEN) << "Got empty url for special language object"; return false; } ICore::self()->documentController()->openDocument(pos.first, pos.second); return true; } return false; } void QuickOpenPlugin::quickOpenDefinition() { if(jumpToSpecialObject()) return; KDevelop::DUChainReadLocker lock( DUChain::lock() ); Declaration* decl = cursorDeclaration(); if(!decl) { qCDebug(PLUGIN_QUICKOPEN) << "Found no declaration for cursor, cannot jump"; return; } IndexedString u = decl->url(); KTextEditor::Cursor c = decl->rangeInCurrentRevision().start(); if(FunctionDefinition* def = FunctionDefinition::definition(decl)) { def->activateSpecialization(); u = def->url(); c = def->rangeInCurrentRevision().start(); }else{ qCDebug(PLUGIN_QUICKOPEN) << "Found no definition for declaration"; decl->activateSpecialization(); } if(u.isEmpty()) { qCDebug(PLUGIN_QUICKOPEN) << "Got empty url for declaration" << decl->toString(); return; } lock.unlock(); core()->documentController()->openDocument(u.toUrl(), c); } bool QuickOpenPlugin::freeModel() { if(m_currentWidgetHandler) delete m_currentWidgetHandler; m_currentWidgetHandler = 0; return true; } void QuickOpenPlugin::nextFunction() { jumpToNearestFunction(NextFunction); } void QuickOpenPlugin::previousFunction() { jumpToNearestFunction(PreviousFunction); } void QuickOpenPlugin::jumpToNearestFunction(QuickOpenPlugin::FunctionJumpDirection direction) { IDocument* doc = ICore::self()->documentController()->activeDocument(); if(!doc) { qCDebug(PLUGIN_QUICKOPEN) << "No active document"; return; } KDevelop::DUChainReadLocker lock( DUChain::lock() ); TopDUContext* context = DUChainUtils::standardContextForUrl( doc->url() ); if( !context ) { qCDebug(PLUGIN_QUICKOPEN) << "Got no standard context"; return; } QList items; OutlineFilter filter(items, OutlineFilter::Functions); DUChainUtils::collectItems( context, filter ); CursorInRevision cursor = context->transformToLocalRevision(KTextEditor::Cursor(doc->cursorPosition())); if (!cursor.isValid()) return; Declaration *nearestDeclBefore = 0; int distanceBefore = INT_MIN; Declaration *nearestDeclAfter = 0; int distanceAfter = INT_MAX; for (int i = 0; i < items.count(); ++i) { Declaration *decl = items[i].m_item.data(); int distance = decl->range().start.line - cursor.line; if (distance < 0 && distance >= distanceBefore) { distanceBefore = distance; nearestDeclBefore = decl; } else if (distance > 0 && distance <= distanceAfter) { distanceAfter = distance; nearestDeclAfter = decl; } } CursorInRevision c = CursorInRevision::invalid(); if (direction == QuickOpenPlugin::NextFunction && nearestDeclAfter) c = nearestDeclAfter->range().start; else if (direction == QuickOpenPlugin::PreviousFunction && nearestDeclBefore) c = nearestDeclBefore->range().start; KTextEditor::Cursor textCursor = KTextEditor::Cursor::invalid(); if (c.isValid()) textCursor = context->transformFromLocalRevision(c); lock.unlock(); if (textCursor.isValid()) core()->documentController()->openDocument(doc->url(), textCursor); else qCDebug(PLUGIN_QUICKOPEN) << "No declaration to jump to"; } struct CreateOutlineDialog { CreateOutlineDialog() : dialog(0), cursorDecl(0), model(0) { } void start() { if(!QuickOpenPlugin::self()->freeModel()) return; IDocument* doc = ICore::self()->documentController()->activeDocument(); if(!doc) { qCDebug(PLUGIN_QUICKOPEN) << "No active document"; return; } KDevelop::DUChainReadLocker lock( DUChain::lock() ); TopDUContext* context = DUChainUtils::standardContextForUrl( doc->url() ); if( !context ) { qCDebug(PLUGIN_QUICKOPEN) << "Got no standard context"; return; } model = new QuickOpenModel(0); OutlineFilter filter(items); DUChainUtils::collectItems( context, filter ); if(noHtmlDestriptionInOutline) { for(int a = 0; a < items.size(); ++a) items[a].m_noHtmlDestription = true; } cursorDecl = cursorContextDeclaration(); model->registerProvider( QStringList(), QStringList(), new DeclarationListDataProvider(QuickOpenPlugin::self(), items, true) ); dialog = new QuickOpenWidgetDialog( i18n("Outline"), model, QStringList(), QStringList(), true ); model->setParent(dialog->widget()); } void finish() { //Select the declaration that contains the cursor if(cursorDecl && dialog) { int num = 0; foreach(const DUChainItem& item, items) { if(item.m_item.data() == cursorDecl) { dialog->widget()->o.list->setCurrentIndex( model->index(num,0,QModelIndex()) ); dialog->widget()->o.list->scrollTo( model->index(num,0,QModelIndex()), QAbstractItemView::PositionAtCenter ); } ++num; } } } QPointer dialog; Declaration* cursorDecl; QList items; QuickOpenModel* model; }; class OutlineQuickopenWidgetCreator : public QuickOpenWidgetCreator { public: OutlineQuickopenWidgetCreator(QStringList /*scopes*/, QStringList /*items*/) : m_creator(0) { } - ~OutlineQuickopenWidgetCreator() { + ~OutlineQuickopenWidgetCreator() override { delete m_creator; } - virtual QuickOpenWidget* createWidget() override { + QuickOpenWidget* createWidget() override { delete m_creator; m_creator = new CreateOutlineDialog; m_creator->start(); if(!m_creator->dialog) return 0; m_creator->dialog->deleteLater(); return m_creator->dialog->widget(); } - virtual void widgetShown() override { + void widgetShown() override { if(m_creator) { m_creator->finish(); delete m_creator; m_creator = 0; } } - virtual QString objectNameForLine() override { + QString objectNameForLine() override { return "Outline"; } CreateOutlineDialog* m_creator; }; void QuickOpenPlugin::quickOpenNavigateFunctions() { CreateOutlineDialog create; create.start(); if(!create.dialog) return; m_currentWidgetHandler = create.dialog; QuickOpenLineEdit* line = quickOpenLine("Outline"); if(!line) line = quickOpenLine(); if(line) { line->showWithWidget(create.dialog->widget()); create.dialog->deleteLater(); }else create.dialog->run(); create.finish(); } QuickOpenLineEdit::QuickOpenLineEdit(QuickOpenWidgetCreator* creator) : m_widget(0), m_forceUpdate(false), m_widgetCreator(creator) { setMinimumWidth(200); setMaximumWidth(400); deactivate(); setDefaultText(i18n("Quick Open...")); setToolTip(i18n("Search for files, classes, functions and more," " allowing you to quickly navigate in your source code.")); setObjectName(m_widgetCreator->objectNameForLine()); setFocusPolicy(Qt::ClickFocus); } QuickOpenLineEdit::~QuickOpenLineEdit() { delete m_widget; delete m_widgetCreator; } bool QuickOpenLineEdit::insideThis(QObject* object) { while (object) { qCDebug(PLUGIN_QUICKOPEN) << object; if (object == this || object == m_widget) { return true; } object = object->parent(); } return false; } void QuickOpenLineEdit::widgetDestroyed(QObject* obj) { Q_UNUSED(obj); // need to use a queued connection here, because this function is called in ~QWidget! // => QuickOpenWidget instance is half-destructed => connections are not yet cleared // => clear() will trigger signals which will operate on the invalid QuickOpenWidget // So, just wait until properly destructed QMetaObject::invokeMethod(this, "deactivate", Qt::QueuedConnection); } void QuickOpenLineEdit::showWithWidget(QuickOpenWidget* widget) { connect(widget, &QuickOpenWidget::destroyed, this, &QuickOpenLineEdit::widgetDestroyed); qCDebug(PLUGIN_QUICKOPEN) << "storing widget" << widget; deactivate(); if(m_widget) { qCDebug(PLUGIN_QUICKOPEN) << "deleting" << m_widget; delete m_widget; } m_widget = widget; m_forceUpdate = true; setFocus(); } void QuickOpenLineEdit::focusInEvent(QFocusEvent* ev) { QLineEdit::focusInEvent(ev); // delete m_widget; qCDebug(PLUGIN_QUICKOPEN) << "got focus"; qCDebug(PLUGIN_QUICKOPEN) << "old widget" << m_widget << "force update:" << m_forceUpdate; if (m_widget && !m_forceUpdate) return; if (!m_forceUpdate && !QuickOpenPlugin::self()->freeModel()) { deactivate(); return; } m_forceUpdate = false; if(!m_widget) { m_widget = m_widgetCreator->createWidget(); if(!m_widget) { deactivate(); return; } } activate(); m_widget->showStandardButtons(false); m_widget->showSearchField(false); m_widget->setParent(0, Qt::ToolTip); m_widget->setFocusPolicy(Qt::NoFocus); m_widget->setAlternativeSearchField(this); QuickOpenPlugin::self()->m_currentWidgetHandler = m_widget; connect(m_widget.data(), &QuickOpenWidget::ready, this, &QuickOpenLineEdit::deactivate); connect( m_widget.data(), &QuickOpenWidget::scopesChanged, QuickOpenPlugin::self(), &QuickOpenPlugin::storeScopes ); connect( m_widget.data(), &QuickOpenWidget::itemsChanged, QuickOpenPlugin::self(), &QuickOpenPlugin::storeItems ); Q_ASSERT(m_widget->o.searchLine == this); m_widget->prepareShow(); QRect widgetGeometry = QRect(mapToGlobal(QPoint(0, height())), mapToGlobal(QPoint(width(), height() + 400))); widgetGeometry.setWidth(700); ///@todo Waste less space QRect screenGeom = QApplication::desktop()->screenGeometry(this); if (widgetGeometry.right() > screenGeom.right()) { widgetGeometry.moveRight(screenGeom.right()); } if (widgetGeometry.bottom() > screenGeom.bottom()) { widgetGeometry.moveBottom(mapToGlobal(QPoint(0, 0)).y()); } m_widget->setGeometry(widgetGeometry); m_widget->show(); m_widgetCreator->widgetShown(); } void QuickOpenLineEdit::hideEvent(QHideEvent* ev) { QWidget::hideEvent(ev); if(m_widget) QMetaObject::invokeMethod(this, "checkFocus", Qt::QueuedConnection); // deactivate(); } bool QuickOpenLineEdit::eventFilter(QObject* obj, QEvent* e) { if (!m_widget) return false; switch (e->type()) { case QEvent::KeyPress: case QEvent::ShortcutOverride: if (static_cast(e)->key() == Qt::Key_Escape) { deactivate(); e->accept(); return true; } break; case QEvent::WindowActivate: case QEvent::WindowDeactivate: qCDebug(PLUGIN_QUICKOPEN) << "closing because of window activation"; deactivate(); break; // handle bug 260657 - "Outline menu doesn't follow main window on its move" case QEvent::Move: { if (QWidget* widget = qobject_cast(obj)) { // close the outline menu in case a parent widget moved if (widget->isAncestorOf(this)) { qCDebug(PLUGIN_QUICKOPEN) << "closing because of parent widget move"; deactivate(); } break; } } case QEvent::FocusIn: if (dynamic_cast(obj)) { QFocusEvent* focusEvent = dynamic_cast(e); Q_ASSERT(focusEvent); //Eat the focus event, keep the focus qCDebug(PLUGIN_QUICKOPEN) << "focus change" << "inside this: " << insideThis(obj) << "this" << this << "obj" << obj; if(obj == this) return false; qCDebug(PLUGIN_QUICKOPEN) << "reason" << focusEvent->reason(); if (focusEvent->reason() != Qt::MouseFocusReason && focusEvent->reason() != Qt::ActiveWindowFocusReason) { QMetaObject::invokeMethod(this, "checkFocus", Qt::QueuedConnection); return false; } if (!insideThis(obj)) deactivate(); } break; default: break; } return false; } void QuickOpenLineEdit::activate() { qCDebug(PLUGIN_QUICKOPEN) << "activating"; setText(""); setStyleSheet(""); qApp->installEventFilter(this); } void QuickOpenLineEdit::deactivate() { qCDebug(PLUGIN_QUICKOPEN) << "deactivating"; clear(); if(m_widget || hasFocus()) QMetaObject::invokeMethod(this, "checkFocus", Qt::QueuedConnection); if (m_widget) m_widget->deleteLater(); m_widget = 0; qApp->removeEventFilter(this); } void QuickOpenLineEdit::checkFocus() { qCDebug(PLUGIN_QUICKOPEN) << "checking focus" << m_widget; if(m_widget) { if(isVisible() && !isHidden()) setFocus(); else deactivate(); }else{ if (ICore::self()->documentController()->activeDocument()) ICore::self()->documentController()->activateDocument(ICore::self()->documentController()->activeDocument()); //Make sure the focus is somewehre else, even if there is no active document setEnabled(false); setEnabled(true); } } IQuickOpenLine* QuickOpenPlugin::createQuickOpenLine(const QStringList& scopes, const QStringList& type, IQuickOpen::QuickOpenType kind) { if(kind == Outline) return new QuickOpenLineEdit(new OutlineQuickopenWidgetCreator(scopes, type)); else return new QuickOpenLineEdit(new StandardQuickOpenWidgetCreator(scopes, type)); } #include "quickopenplugin.moc" // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/quickopen/quickopenplugin.h b/plugins/quickopen/quickopenplugin.h index d781f7327b..8818d0caec 100644 --- a/plugins/quickopen/quickopenplugin.h +++ b/plugins/quickopen/quickopenplugin.h @@ -1,245 +1,245 @@ /* * This file is part of KDevelop * * Copyright 2007 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. */ #ifndef KDEVPLATFORM_PLUGIN_QUICKOPENPLUGIN_H #define KDEVPLATFORM_PLUGIN_QUICKOPENPLUGIN_H #include #include #include #include #include #include #include #include #include "ui_quickopen.h" class QAction; namespace KTextEditor { class Cursor; } class QuickOpenModel; class QuickOpenWidget; class QuickOpenLineEdit; class QuickOpenPlugin : public KDevelop::IPlugin, public KDevelop::IQuickOpen { Q_OBJECT Q_INTERFACES( KDevelop::IQuickOpen ) public: explicit QuickOpenPlugin( QObject *parent, const QVariantList & = QVariantList() ); - virtual ~QuickOpenPlugin(); + ~QuickOpenPlugin() override; static QuickOpenPlugin* self(); // KDevelop::Plugin methods - virtual void unload() override; + void unload() override; - virtual KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; + KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; enum ModelTypes { Files = 1, Functions = 2, Classes = 4, OpenFiles = 8, All = Files + Functions + Classes + OpenFiles }; /** * Shows the quickopen dialog with the specified Model-types * @param modes A combination of ModelTypes * */ void showQuickOpen( ModelTypes modes = All ); void showQuickOpen( const QStringList &items ) override; - virtual void registerProvider( const QStringList& scope, const QStringList& type, KDevelop::QuickOpenDataProviderBase* provider ) override; + void registerProvider( const QStringList& scope, const QStringList& type, KDevelop::QuickOpenDataProviderBase* provider ) override; - virtual bool removeProvider( KDevelop::QuickOpenDataProviderBase* provider ) override; + bool removeProvider( KDevelop::QuickOpenDataProviderBase* provider ) override; - virtual QSet fileSet() const override; + QSet fileSet() const override; //Frees the model by closing active quickopen dialoags, and retuns whether successful. bool freeModel(); - virtual void createActionsForMainWindow( Sublime::MainWindow* window, QString& xmlFile, KActionCollection& actions ) override; + void createActionsForMainWindow( Sublime::MainWindow* window, QString& xmlFile, KActionCollection& actions ) override; QuickOpenLineEdit* createQuickOpenLineWidget(); - virtual KDevelop::IQuickOpenLine* createQuickOpenLine(const QStringList& scopes, const QStringList& type, QuickOpenType kind) override; + KDevelop::IQuickOpenLine* createQuickOpenLine(const QStringList& scopes, const QStringList& type, QuickOpenType kind) override; public slots: void quickOpen(); void quickOpenFile(); void quickOpenFunction(); void quickOpenClass(); void quickOpenDeclaration(); void quickOpenOpenFile(); void quickOpenDefinition(); void quickOpenNavigateFunctions(); void quickOpenDocumentation(); void quickOpenActions(); void previousFunction(); void nextFunction(); private slots: void storeScopes( const QStringList& ); void storeItems( const QStringList& ); private: friend class QuickOpenLineEdit; friend class StandardQuickOpenWidgetCreator; QuickOpenLineEdit* quickOpenLine(QString name = "Quickopen"); enum FunctionJumpDirection { NextFunction, PreviousFunction }; void jumpToNearestFunction(FunctionJumpDirection direction); QPair specialObjectJumpPosition() const; QWidget* specialObjectNavigationWidget() const; bool jumpToSpecialObject(); void showQuickOpenWidget(const QStringList &items, const QStringList &scopes, bool preselectText); QuickOpenModel* m_model; class ProjectFileDataProvider* m_projectFileData; class ProjectItemDataProvider* m_projectItemData; class OpenFilesDataProvider* m_openFilesData; class DocumentationQuickOpenProvider* m_documentationItemData; class ActionsQuickOpenProvider* m_actionsItemData; QStringList lastUsedScopes; QStringList lastUsedItems; //We can only have one widget at a time, because we manipulate the model. QPointer m_currentWidgetHandler; QAction* m_quickOpenDeclaration; QAction* m_quickOpenDefinition; }; ///Will delete itself once the dialog is closed, so use QPointer when referencing it permanently class QuickOpenWidget : public QMenu { Q_OBJECT public: /** * @param initialItems List of items that should initially be enabled in the quickopen-list. If empty, all are enabled. * @param initialScopes List of scopes that should initially be enabled in the quickopen-list. If empty, all are enabled. * @param listOnly when this is true, the given items will be listed, but all filtering using checkboxes is disabled. * @param noSearchFied when this is true, no search-line is shown. * */ QuickOpenWidget( QString title, QuickOpenModel* model, const QStringList& initialItems, const QStringList& initialScopes, bool listOnly = false, bool noSearchField = false ); - ~QuickOpenWidget(); + ~QuickOpenWidget() override; void setPreselectedText(const QString &text); void prepareShow(); void setAlternativeSearchField(QLineEdit* alterantiveSearchField); //Shows OK + Cancel. By default they are hidden void showStandardButtons(bool show); void showSearchField(bool show); signals: void scopesChanged( const QStringList& scopes ); void itemsChanged( const QStringList& scopes ); void ready(); private slots: void callRowSelected(); void updateTimerInterval( bool cheapFilterChange ); void accept(); void textChanged( const QString& str ); void updateProviders(); void doubleClicked ( const QModelIndex & index ); void applyFilter(); private: - virtual void showEvent(QShowEvent *) override; + void showEvent(QShowEvent *) override; - virtual bool eventFilter ( QObject * watched, QEvent * event ) override; + bool eventFilter ( QObject * watched, QEvent * event ) override; QuickOpenModel* m_model; bool m_expandedTemporary, m_hadNoCommandSinceAlt; QTime m_altDownTime; QString m_preselectedText; QTimer m_filterTimer; QString m_filter; public: Ui::QuickOpen o; friend class QuickOpenWidgetDialog; friend class QuickOpenPlugin; friend class QuickOpenLineEdit; }; class QuickOpenWidgetDialog : public QObject { Q_OBJECT public: QuickOpenWidgetDialog( QString title, QuickOpenModel* model, const QStringList& initialItems, const QStringList& initialScopes, bool listOnly = false, bool noSearchField = false ); - ~QuickOpenWidgetDialog(); + ~QuickOpenWidgetDialog() override; ///Shows the dialog void run(); QuickOpenWidget* widget() const { return m_widget; } private: QDialog* m_dialog; //Warning: m_dialog is also the parent QuickOpenWidget* m_widget; }; class QuickOpenWidgetCreator; class QuickOpenLineEdit : public KDevelop::IQuickOpenLine { Q_OBJECT public: explicit QuickOpenLineEdit(QuickOpenWidgetCreator* creator) ; - ~QuickOpenLineEdit() ; + ~QuickOpenLineEdit() override ; bool insideThis(QObject* object); void showWithWidget(QuickOpenWidget* widget); - virtual void setDefaultText(const QString& text) override { + void setDefaultText(const QString& text) override { m_defaultText = text; setPlaceholderText(m_defaultText); } private slots: void activate() ; void deactivate() ; void checkFocus(); void widgetDestroyed(QObject*); private: - virtual void focusInEvent(QFocusEvent* ev) override ; - virtual bool eventFilter(QObject* obj, QEvent* e) override ; - virtual void hideEvent(QHideEvent* ) override; + void focusInEvent(QFocusEvent* ev) override ; + bool eventFilter(QObject* obj, QEvent* e) override ; + void hideEvent(QHideEvent* ) override; QPointer m_widget; bool m_forceUpdate; QString m_defaultText; QuickOpenWidgetCreator* m_widgetCreator; }; #endif // KDEVPLATFORM_PLUGIN_QUICKOPENPLUGIN_H // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/quickopen/tests/quickopentestbase.h b/plugins/quickopen/tests/quickopentestbase.h index 1a8ec9194a..f40a849c63 100644 --- a/plugins/quickopen/tests/quickopentestbase.h +++ b/plugins/quickopen/tests/quickopentestbase.h @@ -1,82 +1,82 @@ /* * Copyright Milian Wolff * * 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_PLUGIN_QUICKOPENTESTBASE_H #define KDEVPLATFORM_PLUGIN_QUICKOPENTESTBASE_H #include #include #include #include #include #include "../duchainitemquickopen.h" #include "../projectfilequickopen.h" class QuickOpenTestBase : public QObject { Q_OBJECT public: explicit QuickOpenTestBase(KDevelop::TestCore::Setup setup, QObject* parent = 0); private slots: void initTestCase(); void cleanupTestCase(); void cleanup(); protected: KDevelop::TestCore* core; KDevelop::TestCore::Setup setup; KDevelop::TestProjectController* projectController; }; class PathTestFilter : public KDevelop::PathFilter { public: KDevelop::Path itemPath(const QString& data) const { return KDevelop::Path(data); } }; KDevelop::TestProject* getProjectWithFiles(int files); template T* createChild(KDevelop::ProjectFolderItem* parent, const QString& childName) { return new T(childName, parent); } QStringList items(const ProjectFileDataProvider& provider); class TestFilter : public KDevelop::Filter { public: - virtual QString itemText(const DUChainItem &data) const override { + QString itemText(const DUChainItem &data) const override { return data.m_text; }; }; Q_DECLARE_METATYPE(QList) #endif // KDEVPLATFORM_PLUGIN_QUICKOPENTESTBASE_H diff --git a/plugins/standardoutputview/standardoutputview.cpp b/plugins/standardoutputview/standardoutputview.cpp index 8535c63f47..db861d1a29 100644 --- a/plugins/standardoutputview/standardoutputview.cpp +++ b/plugins/standardoutputview/standardoutputview.cpp @@ -1,315 +1,315 @@ /* KDevelop Standard OutputView * * Copyright 2006-2007 Andreas Pakulat * Copyright 2007 Dukju Ahn * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include "standardoutputview.h" #include "outputwidget.h" #include "toolviewdata.h" #include "debug.h" #include #include #include #include #include #include #include #include #include #include #include class OutputViewFactory : public KDevelop::IToolViewFactory{ public: OutputViewFactory(const ToolViewData* data): m_data(data) {} - virtual QWidget* create(QWidget *parent = 0) override + QWidget* create(QWidget *parent = 0) override { return new OutputWidget( parent, m_data ); } - virtual Qt::DockWidgetArea defaultPosition() override + Qt::DockWidgetArea defaultPosition() override { return Qt::BottomDockWidgetArea; } - virtual void viewCreated( Sublime::View* view ) override + void viewCreated( Sublime::View* view ) override { m_data->views << view; } - virtual QString id() const override + QString id() const override { //NOTE: id must be unique, see e.g. https://bugs.kde.org/show_bug.cgi?id=287093 return "org.kdevelop.OutputView." + QString::number(m_data->toolViewId); } private: const ToolViewData *m_data; }; StandardOutputView::StandardOutputView(QObject *parent, const QVariantList &) : KDevelop::IPlugin("kdevstandardoutputview", parent) { KDEV_USE_EXTENSION_INTERFACE( KDevelop::IOutputView ) setXMLFile("kdevstandardoutputview.rc"); connect(KDevelop::ICore::self()->uiController()->controller(), &Sublime::Controller::aboutToRemoveView, this, &StandardOutputView::removeSublimeView); } void StandardOutputView::removeSublimeView( Sublime::View* v ) { foreach( ToolViewData* d, toolviews ) { if( d->views.contains(v) ) { if( d->views.count() == 1 ) { toolviews.remove( d->toolViewId ); ids.removeAll( d->toolViewId ); delete d; } else { d->views.removeAll(v); } } } } StandardOutputView::~StandardOutputView() { } int StandardOutputView::standardToolView( KDevelop::IOutputView::StandardToolView view ) { if( standardViews.contains( view ) ) { return standardViews.value( view ); } int ret = -1; switch( view ) { case KDevelop::IOutputView::BuildView: { ret = registerToolView( i18nc("@title:window", "Build"), KDevelop::IOutputView::HistoryView, QIcon::fromTheme("run-build"), KDevelop::IOutputView::AddFilterAction ); break; } case KDevelop::IOutputView::RunView: { ret = registerToolView( i18nc("@title:window", "Run"), KDevelop::IOutputView::MultipleView, QIcon::fromTheme("system-run"), KDevelop::IOutputView::AddFilterAction ); break; } case KDevelop::IOutputView::DebugView: { ret = registerToolView( i18nc("@title:window", "Debug"), KDevelop::IOutputView::MultipleView, QIcon::fromTheme("debug-step-into"), KDevelop::IOutputView::AddFilterAction ); break; } case KDevelop::IOutputView::TestView: { ret = registerToolView( i18nc("@title:window", "Test"), KDevelop::IOutputView::HistoryView, QIcon::fromTheme("system-run")); break; } case KDevelop::IOutputView::VcsView: { ret = registerToolView( i18nc("@title:window", "Version Control"), KDevelop::IOutputView::HistoryView, QIcon::fromTheme("system-run")); break; } } Q_ASSERT(ret != -1); standardViews[view] = ret; return ret; } int StandardOutputView::registerToolView( const QString& title, KDevelop::IOutputView::ViewType type, const QIcon& icon, Options option, const QList& actionList ) { // try to reuse existing toolview foreach( ToolViewData* d, toolviews ) { if ( d->type == type && d->title == title ) { return d->toolViewId; } } // register new tool view const int newid = ids.isEmpty() ? 0 : (ids.last() + 1); qCDebug(PLUGIN_STANDARDOUTPUTVIEW) << "Registering view" << title << "with type:" << type << "id:" << newid; ToolViewData* tvdata = new ToolViewData( this ); tvdata->toolViewId = newid; tvdata->type = type; tvdata->title = title; tvdata->icon = icon; tvdata->plugin = this; tvdata->option = option; tvdata->actionList = actionList; core()->uiController()->addToolView( title, new OutputViewFactory( tvdata ) ); ids << newid; toolviews[newid] = tvdata; return newid; } int StandardOutputView::registerOutputInToolView( int toolViewId, const QString& title, KDevelop::IOutputView::Behaviours behaviour ) { if( !toolviews.contains( toolViewId ) ) return -1; int newid; if( ids.isEmpty() ) { newid = 0; } else { newid = ids.last()+1; } ids << newid; toolviews.value( toolViewId )->addOutput( newid, title, behaviour ); return newid; } void StandardOutputView::raiseOutput(int outputId) { foreach( int _id, toolviews.keys() ) { if( toolviews.value( _id )->outputdata.contains( outputId ) ) { foreach( Sublime::View* v, toolviews.value( _id )->views ) { if( v->hasWidget() ) { OutputWidget* w = qobject_cast( v->widget() ); w->raiseOutput( outputId ); v->requestRaise(); } } } } } void StandardOutputView::setModel( int outputId, QAbstractItemModel* model ) { int tvid = -1; foreach( int _id, toolviews.keys() ) { if( toolviews.value( _id )->outputdata.contains( outputId ) ) { tvid = _id; break; } } if( tvid == -1 ) qCDebug(PLUGIN_STANDARDOUTPUTVIEW) << "Trying to set model on unknown view-id:" << outputId; else { toolviews.value( tvid )->outputdata.value( outputId )->setModel( model ); } } void StandardOutputView::setDelegate( int outputId, QAbstractItemDelegate* delegate ) { int tvid = -1; foreach( int _id, toolviews.keys() ) { if( toolviews.value( _id )->outputdata.contains( outputId ) ) { tvid = _id; break; } } if( tvid == -1 ) qCDebug(PLUGIN_STANDARDOUTPUTVIEW) << "Trying to set model on unknown view-id:" << outputId; else { toolviews.value( tvid )->outputdata.value( outputId )->setDelegate( delegate ); } } void StandardOutputView::removeToolView( int toolviewId ) { if( toolviews.contains(toolviewId) ) { ToolViewData* td = toolviews.value(toolviewId); foreach( Sublime::View* view, td->views ) { if( view->hasWidget() ) { OutputWidget* outputWidget = qobject_cast( view->widget() ); foreach( int outid, td->outputdata.keys() ) { outputWidget->removeOutput( outid ); } } foreach( Sublime::Area* area, KDevelop::ICore::self()->uiController()->controller()->allAreas() ) { area->removeToolView( view ); } } delete td; toolviews.remove(toolviewId); emit toolViewRemoved(toolviewId); } } OutputWidget* StandardOutputView::outputWidgetForId( int outputId ) const { foreach( ToolViewData* td, toolviews ) { if( td->outputdata.contains( outputId ) ) { foreach( Sublime::View* view, td->views ) { if( view->hasWidget() ) return qobject_cast( view->widget() ); } } } return 0; } void StandardOutputView::scrollOutputTo( int outputId, const QModelIndex& idx ) { OutputWidget* widget = outputWidgetForId( outputId ); if( widget ) widget->scrollToIndex( idx ); } void StandardOutputView::removeOutput( int outputId ) { foreach( ToolViewData* td, toolviews ) { if( td->outputdata.contains( outputId ) ) { foreach( Sublime::View* view, td->views ) { if( view->hasWidget() ) qobject_cast( view->widget() )->removeOutput( outputId ); } td->outputdata.remove( outputId ); } } } void StandardOutputView::setTitle(int outputId, const QString& title) { outputWidgetForId(outputId)->setTitle(outputId, title); } diff --git a/plugins/standardoutputview/standardoutputview.h b/plugins/standardoutputview/standardoutputview.h index f526922265..fbc29f3581 100644 --- a/plugins/standardoutputview/standardoutputview.h +++ b/plugins/standardoutputview/standardoutputview.h @@ -1,94 +1,94 @@ /* KDevelop Standard OutputView * * Copyright 2006-2007 Andreas Pakulat * Copyright 2007 Dukju Ahn * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef KDEVPLATFORM_PLUGIN_STANDARDOUTPUTVIEW_H #define KDEVPLATFORM_PLUGIN_STANDARDOUTPUTVIEW_H #include #include #include template class QList; class QAbstractItemModel; class QString; class QModelIndex; class QAbstractItemDelegate; class OutputWidget; class ToolViewData; /** @author Andreas Pakulat */ namespace Sublime { class View; } class StandardOutputView : public KDevelop::IPlugin, public KDevelop::IOutputView { Q_OBJECT Q_INTERFACES( KDevelop::IOutputView ) public: explicit StandardOutputView(QObject *parent = 0, const QVariantList &args = QVariantList()); - virtual ~StandardOutputView(); + ~StandardOutputView() override; int standardToolView( KDevelop::IOutputView::StandardToolView view ) override; int registerToolView( const QString& title, KDevelop::IOutputView::ViewType type = KDevelop::IOutputView::OneView, const QIcon& icon = QIcon(), KDevelop::IOutputView::Options option = ShowItemsButton, const QList& actionList = QList()) override; int registerOutputInToolView( int toolviewId, const QString& title, KDevelop::IOutputView::Behaviours behaviour = KDevelop::IOutputView::AllowUserClose ) override; void raiseOutput( int id ) override; void setModel( int outputId, QAbstractItemModel* model ) override; void setDelegate( int outputId, QAbstractItemDelegate* delegate ) override; OutputWidget* outputWidgetForId( int outputId ) const; - virtual void removeToolView( int toolviewId ) override; - virtual void removeOutput( int outputId ) override; + void removeToolView( int toolviewId ) override; + void removeOutput( int outputId ) override; - virtual void scrollOutputTo( int outputId, const QModelIndex& idx ) override; - virtual void setTitle(int outputId, const QString& title) override; + void scrollOutputTo( int outputId, const QModelIndex& idx ) override; + void setTitle(int outputId, const QString& title) override; public Q_SLOTS: void removeSublimeView( Sublime::View* ); Q_SIGNALS: void activated( const QModelIndex& ); void outputRemoved( int toolviewId, int outputId ); void toolViewRemoved( int toolviewId ); private: QMap toolviews; QList ids; QMap standardViews; }; #endif // KDEVPLATFORM_PLUGIN_STANDARDOUTPUTVIEW_H diff --git a/plugins/standardoutputview/toolviewdata.h b/plugins/standardoutputview/toolviewdata.h index 65c9c078bc..bf6b7e7440 100644 --- a/plugins/standardoutputview/toolviewdata.h +++ b/plugins/standardoutputview/toolviewdata.h @@ -1,81 +1,81 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2008 Andreas Pakulat * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_TOOLVIEWDATA_H #define KDEVPLATFORM_PLUGIN_TOOLVIEWDATA_H #include #include #include namespace Sublime { class View; } class QItemDelegate; class QString; class QAbstractItemModel; class QListView; class StandardOutputView; class ToolViewData; class OutputData : public QObject { Q_OBJECT public: explicit OutputData( ToolViewData* tv ); QAbstractItemDelegate* delegate; QAbstractItemModel* model; ToolViewData* toolView; KDevelop::IOutputView::Behaviours behaviour; QString title; int id; void setModel( QAbstractItemModel* model ); void setDelegate( QAbstractItemDelegate* delegate ); signals: void modelChanged( int ); void delegateChanged( int ); }; class ToolViewData : public QObject { Q_OBJECT public: explicit ToolViewData( QObject* parent ); - ~ToolViewData(); + ~ToolViewData() override; OutputData* addOutput( int id, const QString& title, KDevelop::IOutputView::Behaviours behave ); // If we would adhere to model-view-separation strictly, then this member would move into standardoutputview, but it is more convenient this way. // TODO: move into standardoutputview mutable QList views; StandardOutputView* plugin; QMap outputdata; KDevelop::IOutputView::ViewType type; QString title; QIcon icon; int toolViewId; KDevelop::IOutputView::Options option; QList actionList; signals: void outputAdded( int ); }; #endif diff --git a/plugins/subversion/svncheckoutmetadatawidget.h b/plugins/subversion/svncheckoutmetadatawidget.h index d88fc84cc9..0c6d90ade0 100644 --- a/plugins/subversion/svncheckoutmetadatawidget.h +++ b/plugins/subversion/svncheckoutmetadatawidget.h @@ -1,37 +1,37 @@ /*************************************************************************** * Copyright 2007 Dukju Ahn * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_SVN_CHECKOUTMETADATAWIDGET_H #define KDEVPLATFORM_PLUGIN_SVN_CHECKOUTMETADATAWIDGET_H #include #include namespace Ui { class SvnCheckoutMetadataWidget; } class SvnCheckoutMetadataWidget : public QWidget { Q_OBJECT public: explicit SvnCheckoutMetadataWidget( QWidget *parent ); - virtual ~SvnCheckoutMetadataWidget(); + ~SvnCheckoutMetadataWidget() override; void setDestinationLocation( const QUrl& ); virtual KDevelop::VcsLocation source() const; virtual QUrl destination() const; virtual KDevelop::IBasicVersionControl::RecursionMode recursionMode() const; private: Ui::SvnCheckoutMetadataWidget* m_ui; }; #endif diff --git a/plugins/subversion/svnimportmetadatawidget.h b/plugins/subversion/svnimportmetadatawidget.h index 8bd3079bd4..5c53c595a5 100644 --- a/plugins/subversion/svnimportmetadatawidget.h +++ b/plugins/subversion/svnimportmetadatawidget.h @@ -1,41 +1,41 @@ /*************************************************************************** * Copyright 2007 Dukju Ahn * * Copyright 2007 Andreas Pakulat * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_SVNIMPORTMETADATAWIDGET_H #define KDEVPLATFORM_PLUGIN_SVNIMPORTMETADATAWIDGET_H #include namespace Ui { class SvnImportMetadataWidget; } class SvnImportMetadataWidget : public KDevelop::VcsImportMetadataWidget { Q_OBJECT public: explicit SvnImportMetadataWidget( QWidget *parent ); - virtual ~SvnImportMetadataWidget(); + ~SvnImportMetadataWidget() override; - virtual void setSourceLocation( const KDevelop::VcsLocation& ) override; - virtual void setSourceLocationEditable( bool ) override; - virtual QUrl source() const override; - virtual KDevelop::VcsLocation destination() const override; - virtual QString message() const override; - virtual void setUseSourceDirForDestination( bool ) override; - virtual bool hasValidData() const override; + void setSourceLocation( const KDevelop::VcsLocation& ) override; + void setSourceLocationEditable( bool ) override; + QUrl source() const override; + KDevelop::VcsLocation destination() const override; + QString message() const override; + void setUseSourceDirForDestination( bool ) override; + bool hasValidData() const override; private: Ui::SvnImportMetadataWidget *m_ui; bool useSourceDirForDestination; }; #endif diff --git a/plugins/subversion/svninternaljobbase.h b/plugins/subversion/svninternaljobbase.h index 1010dd8b63..5ef8e7a0b8 100644 --- a/plugins/subversion/svninternaljobbase.h +++ b/plugins/subversion/svninternaljobbase.h @@ -1,129 +1,129 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2007 Andreas Pakulat * * Copyright 2007 Dukju Ahn * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_SVNINTERNALJOBBASE_H #define KDEVPLATFORM_PLUGIN_SVNINTERNALJOBBASE_H #include #include #include #include extern "C" { #include } #include "kdevsvncpp/context_listener.hpp" namespace KDevelop { class VcsRevision; } namespace svn { class Context; class Revision; } class SvnJobBase; class QMutex; class QSemaphore; class SvnInternalJobBase : public QObject, public ThreadWeaver::Job, public svn::ContextListener { Q_OBJECT public: explicit SvnInternalJobBase( SvnJobBase* parent = 0 ); - virtual ~SvnInternalJobBase(); + ~SvnInternalJobBase() override; - virtual bool success() const override; + bool success() const override; bool contextGetLogin( const std::string& realm, std::string& username, std::string& password, bool& maySave ) override; void contextNotify( const char* path, svn_wc_notify_action_t action, svn_node_kind_t kind, const char* mimetype, svn_wc_notify_state_t contentState, svn_wc_notify_state_t propState, svn_revnum_t rev ) override; bool contextCancel() override; bool contextGetLogMessage( std::string& msg ) override; svn::ContextListener::SslServerTrustAnswer contextSslServerTrustPrompt( const svn::ContextListener::SslServerTrustData& data, apr_uint32_t& acceptedFailures ) override; bool contextSslClientCertPrompt( std::string& cert ) override; bool contextSslClientCertPwPrompt( std::string& pw, const std::string& realm, bool& maySave ) override; void initBeforeRun(); void kill(); bool wasKilled(); QString errorMessage() const; svn::Context* m_ctxt; QSemaphore m_guiSemaphore; QString m_login_username; QString m_login_password; bool m_maySave; QString m_commitMessage; svn::ContextListener::SslServerTrustAnswer m_trustAnswer; static svn::Revision createSvnCppRevisionFromVcsRevision( const KDevelop::VcsRevision& ); signals: void needLogin( const QString& ); void showNotification( const QString&, const QString& ); void needCommitMessage(); void needSslServerTrust( const QStringList&, const QString&, const QString&, const QString&, const QString&, const QString&, const QString& ); void needSslClientCert( const QString& ); void needSslClientCertPassword( const QString& ); /** This signal is emitted when this job is being processed by a thread. */ void started(); /** This signal is emitted when the job has been finished (no matter if it succeeded or not). */ void done(); /** This job has failed. * * This signal is emitted when success() returns false after the job is executed. */ void failed(); protected: void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; mutable QMutex m_mutex; mutable QMutex m_killMutex; bool m_success; void setErrorMessage( const QString& ); private: bool sendFirstDelta; bool killed; QString m_errorMessage; }; #endif diff --git a/plugins/subversion/svnjobbase.h b/plugins/subversion/svnjobbase.h index 3311d64565..fdfa0d5dbb 100644 --- a/plugins/subversion/svnjobbase.h +++ b/plugins/subversion/svnjobbase.h @@ -1,92 +1,92 @@ /*************************************************************************** * Copyright 2007 Dukju Ahn * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_SVNJOBBASE_H #define KDEVPLATFORM_PLUGIN_SVNJOBBASE_H #include #include "kdevsvncpp/context_listener.hpp" #include "kdevsvnplugin.h" #include "debug.h" #include extern "C" { #include } class QEvent; class SvnInternalJobBase; namespace ThreadWeaver { class Job; } class KDevSvnPlugin; class SvnJobBase : public KDevelop::VcsJob { Q_OBJECT public: explicit SvnJobBase( KDevSvnPlugin*, KDevelop::OutputJob::OutputJobVerbosity verbosity = KDevelop::OutputJob::Verbose ); - virtual ~SvnJobBase(); + ~SvnJobBase() override; virtual SvnInternalJobBase* internalJob() const = 0; KDevelop::VcsJob::JobStatus status() const override; KDevelop::IPlugin* vcsPlugin() const override; public slots: void askForLogin( const QString& ); void showNotification( const QString&, const QString& ); void askForCommitMessage(); void askForSslServerTrust( const QStringList&, const QString&, const QString&, const QString&, const QString&, const QString&, const QString& ); void askForSslClientCert( const QString& ); void askForSslClientCertPassword( const QString& ); protected slots: void internalJobStarted(); void internalJobDone(); void internalJobFailed(); protected: void startInternalJob(); - virtual bool doKill() override; + bool doKill() override; KDevSvnPlugin* m_part; private: void outputMessage(const QString &message); KDevelop::VcsJob::JobStatus m_status; }; template class SvnJobBaseImpl : public SvnJobBase { public: SvnJobBaseImpl(KDevSvnPlugin* plugin, KDevelop::OutputJob::OutputJobVerbosity verbosity = KDevelop::OutputJob::Verbose) : SvnJobBase(plugin, verbosity) { m_job = new InternalJobClass(this); } SvnInternalJobBase* internalJob() const override { return m_job; } protected: InternalJobClass* m_job = nullptr; }; #endif diff --git a/plugins/subversion/svnssldialog.h b/plugins/subversion/svnssldialog.h index a123a06251..b092f8ca41 100644 --- a/plugins/subversion/svnssldialog.h +++ b/plugins/subversion/svnssldialog.h @@ -1,36 +1,36 @@ /*************************************************************************** * Copyright 2007 Dukju Ahn * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_SVN_SSLDIALOG_H #define KDEVPLATFORM_PLUGIN_SVN_SSLDIALOG_H #include #include class SvnSSLTrustDialog: public QDialog { Q_OBJECT public: explicit SvnSSLTrustDialog( QWidget *parent = 0 ); - virtual ~SvnSSLTrustDialog(); + ~SvnSSLTrustDialog() override; void setCertInfos( const QString& hostname, const QString& fingerPrint, const QString& validfrom, const QString& validuntil, const QString& issuerName, const QString& realm, const QStringList& failures ); bool useTemporarily(); private slots: void buttonClicked(QAbstractButton *button); private: class SvnSSLTrustDialogPrivate *d; QDialogButtonBox *buttonBox; }; #endif diff --git a/plugins/switchtobuddy/switchtobuddyplugin.h b/plugins/switchtobuddy/switchtobuddyplugin.h index df6ada56b4..eb74c511c4 100644 --- a/plugins/switchtobuddy/switchtobuddyplugin.h +++ b/plugins/switchtobuddy/switchtobuddyplugin.h @@ -1,81 +1,81 @@ /* * This file is part of KDevelop * Copyright 2012 André Stein * Copyright 2014 Kevin Funk * * 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. */ #ifndef KDEVPLATFORM_PLUGIN_SWITCHTOBUDDY_H #define KDEVPLATFORM_PLUGIN_SWITCHTOBUDDY_H #include #include #include #include Q_DECLARE_LOGGING_CATEGORY(PLUGIN_SWITCHTOBUDDY) /** * @short Implements a context menu extension in an editor context which provides * an action that allows switching to associated buddy documents. * * Using the @c IBuddyDocumentFinder interface, the current document's * language plugin provides potential buddy candidates. Depending on their * existence on the file system the @c SwitchToBuddyPlugin * enables a 'Switch To XXX' action which opens that buddy document * using the @c IDocumentController. * * If a language plugin either doens't provide the @c IBuddyDocumentFinder * interface or no buddy exists on the file system, no context menu * extension is performed. * * @see IBuddyDocumentFinder * @see IDocumentController */ class SwitchToBuddyPlugin : public KDevelop::IPlugin { Q_OBJECT public: explicit SwitchToBuddyPlugin( QObject *parent, const QVariantList & = QVariantList()); - ~SwitchToBuddyPlugin(); + ~SwitchToBuddyPlugin() override; - virtual KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; - virtual void createActionsForMainWindow(Sublime::MainWindow* window, QString& xmlFile, KActionCollection& actions) override; + KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context) override; + void createActionsForMainWindow(Sublime::MainWindow* window, QString& xmlFile, KActionCollection& actions) override; private slots: /** * Context menu slot which switches to the QUrl provided * in the data part of the sending QAction. */ void switchToBuddy(const QString& url); /** * @brief Switch between definitions and declarations * * E.g. if the cursor in the currently active view points to an implementation file * this shortcut will open the header document (or any buddy file). * * Furthermore, if the cursor points to a definition, and the buddy document contains its declaration, * the cursor will be also set to the declaration's position when the buddy document is opened */ void switchDefinitionDeclaration(); private: class QSignalMapper* m_signalMapper; }; #endif // KDEVPLATFORM_PLUGIN_SWITCHTOBUDDY_H diff --git a/plugins/testview/testview.h b/plugins/testview/testview.h index 1ef93e9602..b4efbc27f3 100644 --- a/plugins/testview/testview.h +++ b/plugins/testview/testview.h @@ -1,71 +1,71 @@ /* This file is part of KDevelop Copyright 2012 Miha Čančula 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_PLUGIN_TESTVIEW_H #define KDEVPLATFORM_PLUGIN_TESTVIEW_H #include #include #include class QSortFilterProxyModel; class QStandardItem; class TestViewPlugin; class QStandardItemModel; namespace KDevelop { class ITestSuite; } class TestView : public QWidget { Q_OBJECT public: explicit TestView(TestViewPlugin* plugin, QWidget* parent = 0); - virtual ~TestView(); + ~TestView() override; public slots: void runSelectedTests(); void showSource(); void addTestSuite(KDevelop::ITestSuite* suite); void removeTestSuite(KDevelop::ITestSuite* suite); void updateTestSuite(KDevelop::ITestSuite* suite, const KDevelop::TestResult& result); void notifyTestCaseStarted(KDevelop::ITestSuite* suite, const QStringList& test_cases); QStandardItem* addProject(KDevelop::IProject* project); void removeProject(KDevelop::IProject* project); void doubleClicked(const QModelIndex& index); QList contextMenuActions(); private: void changeFilter(const QString &newFilter); TestViewPlugin* m_plugin; QStandardItemModel* m_model; QTreeView* m_tree; QSortFilterProxyModel* m_filter; QList m_contextMenuActions; QIcon iconForTestResult(KDevelop::TestResult::TestCaseResult result); QStandardItem* itemForSuite(KDevelop::ITestSuite* suite); QStandardItem* itemForProject(KDevelop::IProject* project); }; #endif // KDEVPLATFORM_PLUGIN_TESTVIEW_H diff --git a/plugins/testview/testviewplugin.cpp b/plugins/testview/testviewplugin.cpp index c4876109b1..67d200eac5 100644 --- a/plugins/testview/testviewplugin.cpp +++ b/plugins/testview/testviewplugin.cpp @@ -1,155 +1,155 @@ /* This file is part of KDevelop Copyright 2012 Miha ?an?ula 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "testviewplugin.h" #include "testview.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include K_PLUGIN_FACTORY_WITH_JSON(TestViewFactory, "kdevtestview.json", registerPlugin();) using namespace KDevelop; class TestToolViewFactory: public KDevelop::IToolViewFactory { public: TestToolViewFactory( TestViewPlugin *plugin ): mplugin( plugin ) {} - virtual QWidget* create( QWidget *parent = 0 ) override + QWidget* create( QWidget *parent = 0 ) override { return new TestView( mplugin, parent ); } - virtual Qt::DockWidgetArea defaultPosition() override + Qt::DockWidgetArea defaultPosition() override { return Qt::LeftDockWidgetArea; } - virtual QString id() const override + QString id() const override { return "org.kdevelop.TestView"; } - virtual QList< QAction* > contextMenuActions(QWidget* viewWidget) const override + QList< QAction* > contextMenuActions(QWidget* viewWidget) const override { return qobject_cast(viewWidget)->contextMenuActions(); } private: TestViewPlugin *mplugin; }; TestViewPlugin::TestViewPlugin(QObject* parent, const QVariantList& args) : IPlugin("kdevtestview", parent) { Q_UNUSED(args) QAction* runAll = new QAction( QIcon::fromTheme("system-run"), i18n("Run All Tests"), this ); connect(runAll, &QAction::triggered, this, &TestViewPlugin::runAllTests); actionCollection()->addAction("run_all_tests", runAll); QAction* stopTest = new QAction( QIcon::fromTheme("process-stop"), i18n("Stop Running Tests"), this ); connect(stopTest, &QAction::triggered, this, &TestViewPlugin::stopRunningTests); actionCollection()->addAction("stop_running_tests", stopTest); setXMLFile("kdevtestview.rc"); m_viewFactory = new TestToolViewFactory(this); core()->uiController()->addToolView(i18n("Unit Tests"), m_viewFactory); connect(core()->runController(),&IRunController::jobRegistered, this, &TestViewPlugin::jobStateChanged); connect(core()->runController(),&IRunController::jobUnregistered, this, &TestViewPlugin::jobStateChanged); jobStateChanged(); } TestViewPlugin::~TestViewPlugin() { } void TestViewPlugin::unload() { core()->uiController()->removeToolView(m_viewFactory); } void TestViewPlugin::runAllTests() { ITestController* tc = core()->testController(); foreach (IProject* project, core()->projectController()->projects()) { QList jobs; foreach (ITestSuite* suite, tc->testSuitesForProject(project)) { if (KJob* job = suite->launchAllCases(ITestSuite::Silent)) { jobs << job; } } if (!jobs.isEmpty()) { KDevelop::ExecuteCompositeJob* compositeJob = new KDevelop::ExecuteCompositeJob(this, jobs); compositeJob->setObjectName(i18np("Run 1 test in %2", "Run %1 tests in %2", jobs.size(), project->name())); compositeJob->setProperty("test_job", true); core()->runController()->registerJob(compositeJob); } } } void TestViewPlugin::stopRunningTests() { foreach (KJob* job, core()->runController()->currentJobs()) { if (job->property("test_job").toBool()) { job->kill(); } } } void TestViewPlugin::jobStateChanged() { bool found = false; foreach (KJob* job, core()->runController()->currentJobs()) { if (job->property("test_job").toBool()) { found = true; break; } } actionCollection()->action("run_all_tests")->setEnabled(!found); actionCollection()->action("stop_running_tests")->setEnabled(found); } #include "testviewplugin.moc" diff --git a/plugins/testview/testviewplugin.h b/plugins/testview/testviewplugin.h index 21a60f1b5f..9252261456 100644 --- a/plugins/testview/testviewplugin.h +++ b/plugins/testview/testviewplugin.h @@ -1,46 +1,46 @@ /* This file is part of KDevelop Copyright 2012 Miha ?an?ula 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_PLUGIN_TESTVIEWPLUGIN_H #define KDEVPLATFORM_PLUGIN_TESTVIEWPLUGIN_H #include "interfaces/iplugin.h" #include class TestToolViewFactory; class TestViewPlugin : public KDevelop::IPlugin { Q_OBJECT public: explicit TestViewPlugin(QObject* parent, const QVariantList& args = QVariantList()); - virtual ~TestViewPlugin(); + ~TestViewPlugin() override; - virtual void unload() override; + void unload() override; private: TestToolViewFactory* m_viewFactory; private slots: void runAllTests(); void stopRunningTests(); void jobStateChanged(); }; #endif // KDEVPLATFORM_PLUGIN_TESTVIEWPLUGIN_H diff --git a/plugins/vcschangesview/vcschangesview.h b/plugins/vcschangesview/vcschangesview.h index 93ec554061..fb5ad4382b 100644 --- a/plugins/vcschangesview/vcschangesview.h +++ b/plugins/vcschangesview/vcschangesview.h @@ -1,48 +1,48 @@ /* * This file is part of KDevelop * Copyright 2010 Aleix Pol Gonzalez * * 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. */ #ifndef KDEVPLATFORM_PLUGIN_VCSCHANGESVIEW_H #define KDEVPLATFORM_PLUGIN_VCSCHANGESVIEW_H #include class VcsProjectIntegrationPlugin; class QUrl; namespace KDevelop { class IProject; } class VcsChangesView : public QTreeView { Q_OBJECT public: explicit VcsChangesView(VcsProjectIntegrationPlugin* plugin, QWidget* parent = 0); - virtual void setModel(QAbstractItemModel* model) override; + void setModel(QAbstractItemModel* model) override; public slots: void popupContextMenu( const QPoint &pos ); void selectCurrentDocument(); void openSelected(const QModelIndex& idx); signals: void reload(const QList& p); void reload(const QList& p); }; #endif // KDEVPLATFORM_PLUGIN_VCSCHANGESVIEW_H diff --git a/plugins/vcschangesview/vcschangesviewplugin.cpp b/plugins/vcschangesview/vcschangesviewplugin.cpp index 7604795cb8..657146cfff 100644 --- a/plugins/vcschangesview/vcschangesviewplugin.cpp +++ b/plugins/vcschangesview/vcschangesviewplugin.cpp @@ -1,107 +1,107 @@ /* This file is part of KDevelop Copyright 2010 Aleix Pol 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 "vcschangesviewplugin.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vcschangesview.h" K_PLUGIN_FACTORY_WITH_JSON(VcsProjectIntegrationFactory, "kdevvcschangesview.json", registerPlugin();) using namespace KDevelop; class VCSProjectToolViewFactory : public KDevelop::IToolViewFactory { public: VCSProjectToolViewFactory(VcsProjectIntegrationPlugin *plugin): m_plugin(plugin) {} - virtual QWidget* create(QWidget *parent = 0) override + QWidget* create(QWidget *parent = 0) override { VcsChangesView* modif = new VcsChangesView(m_plugin, parent); modif->setModel(m_plugin->model()); QObject::connect(modif, static_cast&)>(&VcsChangesView::reload), m_plugin->model(), static_cast&)>(&ProjectChangesModel::reload)); QObject::connect(modif, static_cast&)>(&VcsChangesView::reload), m_plugin->model(), static_cast&)>(&ProjectChangesModel::reload)); QObject::connect(modif, &VcsChangesView::activated, m_plugin, &VcsProjectIntegrationPlugin::activated); return modif; } - virtual Qt::DockWidgetArea defaultPosition() override + Qt::DockWidgetArea defaultPosition() override { return Qt::RightDockWidgetArea; } - virtual QString id() const override + QString id() const override { return "org.kdevelop.VCSProject"; } private: VcsProjectIntegrationPlugin *m_plugin; }; VcsProjectIntegrationPlugin::VcsProjectIntegrationPlugin(QObject* parent, const QVariantList&) : KDevelop::IPlugin("kdevvcsprojectintegration", parent) , m_model(0) { ICore::self()->uiController()->addToolView(i18n("Project Changes"), new VCSProjectToolViewFactory(this)); QAction* synaction = actionCollection()->addAction( "locate_document" ); synaction->setText(i18n("Locate Current Document")); synaction->setIcon(QIcon::fromTheme("dirsync")); synaction->setToolTip(i18n("Locates the current document and selects it.")); QAction* reloadaction = actionCollection()->addAction( "reload_view" ); reloadaction->setText(i18n("Reload View")); reloadaction->setIcon(QIcon::fromTheme("view-refresh")); reloadaction->setToolTip(i18n("Refreshes the view for all projects, in case anything changed.")); } void VcsProjectIntegrationPlugin::activated(const QModelIndex& /*idx*/) { } ProjectChangesModel* VcsProjectIntegrationPlugin::model() { if(!m_model) { m_model = ICore::self()->projectController()->changesModel(); connect(actionCollection()->action("reload_view"), &QAction::triggered, m_model, &ProjectChangesModel::reloadAll); } return m_model; } #include "vcschangesviewplugin.moc" diff --git a/plugins/welcomepage/declarative/kdevelopdashboarddeclarativeplugin.h b/plugins/welcomepage/declarative/kdevelopdashboarddeclarativeplugin.h index 993674fb47..c90a104cdf 100644 --- a/plugins/welcomepage/declarative/kdevelopdashboarddeclarativeplugin.h +++ b/plugins/welcomepage/declarative/kdevelopdashboarddeclarativeplugin.h @@ -1,33 +1,33 @@ /************************************************************************************* * Copyright (C) 2012 by Aleix Pol * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * * as published by the Free Software Foundation; either version 2 * * of the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * *************************************************************************************/ #ifndef KDEVPLATFORM_PLUGIN_KDEVELOPDASBOARDDECLARATIVE_H #define KDEVPLATFORM_PLUGIN_KDEVELOPDASBOARDDECLARATIVE_H #include class KDevplatformDeclarativePlugin : public QQmlExtensionPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") public: - virtual void registerTypes(const char* uri) override; + void registerTypes(const char* uri) override; }; #endif // KDEVPLATFORM_PLUGIN_PLUGIN_KDEVELOPDASBOARDDECLARATIVE_H diff --git a/plugins/welcomepage/sessionsmodel.h b/plugins/welcomepage/sessionsmodel.h index 9b994d366a..8dec80b109 100644 --- a/plugins/welcomepage/sessionsmodel.h +++ b/plugins/welcomepage/sessionsmodel.h @@ -1,43 +1,43 @@ /* This file is part of KDevelop Copyright 2010 Aleix Pol Gonzalez 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. */ #ifndef SESSIONSMODEL_H #define SESSIONSMODEL_H #include #include class SessionsModel : public QAbstractListModel { Q_OBJECT public: enum Roles { Uuid = Qt::UserRole+1, Projects, ProjectNames, VisibleIdentifier }; explicit SessionsModel(QObject* parent = 0); - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; - virtual QHash< int, QByteArray > roleNames() const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QHash< int, QByteArray > roleNames() const override; Q_SCRIPTABLE void loadSession(const QString& nameOrId) const; private: QList m_sessions; private slots: void sessionDeleted(const QString& id); }; #endif // SESSIONSMODEL_H diff --git a/plugins/welcomepage/welcomepagedocument.h b/plugins/welcomepage/welcomepagedocument.h index e0bd36a625..6eac95ed31 100644 --- a/plugins/welcomepage/welcomepagedocument.h +++ b/plugins/welcomepage/welcomepagedocument.h @@ -1,51 +1,51 @@ /* This file is part of KDevelop * Copyright 2010 Aleix Pol Gonzalez * * 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 KDEVPLATFORM_PLUGIN_DASHBOARDDOCUMENT_H #define KDEVPLATFORM_PLUGIN_DASHBOARDDOCUMENT_H #include #include class WelcomePageDocument : public Sublime::UrlDocument, public KDevelop::IDocument { Q_OBJECT public: WelcomePageDocument(); - virtual void activate(Sublime::View* activeView, KParts::MainWindow* mainWindow) override; - virtual void setTextSelection(const KTextEditor::Range& range) override; - virtual void setCursorPosition(const KTextEditor::Cursor& cursor) override; - virtual KTextEditor::Cursor cursorPosition() const override; - virtual KDevelop::IDocument::DocumentState state() const override; - virtual bool isActive() const override; - virtual bool close(KDevelop::IDocument::DocumentSaveMode mode = Default) override; - virtual void reload() override; - virtual bool save(KDevelop::IDocument::DocumentSaveMode mode = Default) override; - virtual KTextEditor::Document* textDocument() const override; - virtual KParts::Part* partForView(QWidget* view) const override; - virtual QMimeType mimeType() const override; - virtual QUrl url() const override; + void activate(Sublime::View* activeView, KParts::MainWindow* mainWindow) override; + void setTextSelection(const KTextEditor::Range& range) override; + void setCursorPosition(const KTextEditor::Cursor& cursor) override; + KTextEditor::Cursor cursorPosition() const override; + KDevelop::IDocument::DocumentState state() const override; + bool isActive() const override; + bool close(KDevelop::IDocument::DocumentSaveMode mode = Default) override; + void reload() override; + bool save(KDevelop::IDocument::DocumentSaveMode mode = Default) override; + KTextEditor::Document* textDocument() const override; + KParts::Part* partForView(QWidget* view) const override; + QMimeType mimeType() const override; + QUrl url() const override; static QUrl welcomePageUrl(); protected: - virtual Sublime::View* newView(Document* doc) override; + Sublime::View* newView(Document* doc) override; }; #endif // KDEVPLATFORM_PLUGIN_DASHBOARDDOCUMENT_H diff --git a/plugins/welcomepage/welcomepageplugin.cpp b/plugins/welcomepage/welcomepageplugin.cpp index ed5c323e89..3032f8e17c 100644 --- a/plugins/welcomepage/welcomepageplugin.cpp +++ b/plugins/welcomepage/welcomepageplugin.cpp @@ -1,77 +1,77 @@ /* This file is part of KDevelop Copyright 2010 Aleix Pol Gonzalez 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 "welcomepageplugin.h" #include #include "welcomepageview.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "welcomepagedocument.h" K_PLUGIN_FACTORY_WITH_JSON(KDevWelcomePagePluginFactory, "kdevwelcomepage.json", registerPlugin();) using namespace KDevelop; class WelcomePageFactory : public KDevelop::IDocumentFactory { public: - virtual IDocument* create(const QUrl& /*url*/, ICore*) override + IDocument* create(const QUrl& /*url*/, ICore*) override { return new WelcomePageDocument(); } }; KDevWelcomePagePlugin::KDevWelcomePagePlugin( QObject* parent, const QVariantList& ) : IPlugin("kdevwelcomepage", parent ) { // ICore::self()->documentController()->registerDocumentForMimetype("text/x-kdevelop-internal", new WelcomePageFactory); // // //FIXME: When and where to open the welcome page? // //QTimer::singleShot(500, this, SLOT(openWelcomePage())); // // QAction* action = actionCollection()->addAction("show-welcomepage"); // action->setText("Show Welcome Page"); // action->setIcon(QIcon::fromTheme("meeting-organizer")); Sublime::MainWindow* mw = qobject_cast(ICore::self()->uiController()->activeMainWindow()); mw->setBackgroundCentralWidget(new WelcomePageWidget(QList(), mw)); } void KDevWelcomePagePlugin::openWelcomePage() { ICore::self()->documentController()->openDocument(WelcomePageDocument::welcomePageUrl()); } #include "welcomepageplugin.moc" diff --git a/plugins/welcomepage/welcomepageview.h b/plugins/welcomepage/welcomepageview.h index 9e6da077f8..4a0f264278 100644 --- a/plugins/welcomepage/welcomepageview.h +++ b/plugins/welcomepage/welcomepageview.h @@ -1,53 +1,53 @@ /* This file is part of KDevelop Copyright 2011 Aleix Pol Gonzalez 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. */ #ifndef WELCOMEPAGEVIEW_H #define WELCOMEPAGEVIEW_H #include #include namespace Sublime { class Area; } namespace KDevelop { class IProject; } class WelcomePageView : public Sublime::View { public: explicit WelcomePageView(Sublime::Document* doc, WidgetOwnership ws = DoNotTakeOwnerShip); - virtual QWidget* createWidget(QWidget* parent) override; + QWidget* createWidget(QWidget* parent) override; }; class WelcomePageWidget : public QQuickWidget { Q_OBJECT public: explicit WelcomePageWidget(const QList< KDevelop::IProject* >& projects, QWidget* parent = 0); public slots: void areaChanged(Sublime::Area* a); }; void trySetupWelcomePageView(); #endif // WELCOMEPAGEVIEW_H diff --git a/project/abstractfilemanagerplugin.h b/project/abstractfilemanagerplugin.h index 16f8e6be29..4c303f2ecc 100644 --- a/project/abstractfilemanagerplugin.h +++ b/project/abstractfilemanagerplugin.h @@ -1,151 +1,151 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2010-2012 Milian Wolff * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_ABSTRACTGENERICMANAGER_H #define KDEVPLATFORM_ABSTRACTGENERICMANAGER_H #include "projectexport.h" #include "interfaces/iprojectfilemanager.h" #include #include class KDirWatch; namespace KDevelop { class FileManagerListJob; /** * This class can be used as a common base for file managers. * * It supports remote files using KIO and uses KDirWatch to synchronize with on-disk changes. */ class KDEVPLATFORMPROJECT_EXPORT AbstractFileManagerPlugin : public IPlugin, public virtual IProjectFileManager { Q_OBJECT Q_INTERFACES( KDevelop::IProjectFileManager ) public: explicit AbstractFileManagerPlugin( const QString& componentName, QObject *parent = 0, const QVariantList &args = QVariantList() ); - virtual ~AbstractFileManagerPlugin(); + ~AbstractFileManagerPlugin() override; // // IProjectFileManager interface // - virtual Features features() const override; - - virtual ProjectFolderItem* addFolder( const Path& folder, ProjectFolderItem *parent ) override; - virtual ProjectFileItem* addFile( const Path& file, ProjectFolderItem *parent ) override; - virtual bool removeFilesAndFolders( const QList &items ) override; - virtual bool moveFilesAndFolders(const QList< ProjectBaseItem* >& items, ProjectFolderItem* newParent) override; - virtual bool copyFilesAndFolders(const Path::List& items, ProjectFolderItem* newParent) override; - virtual bool renameFolder(ProjectFolderItem* folder, const Path& newPath) override; - virtual bool renameFile(ProjectFileItem* file, const Path& newPath) override; - - virtual QList parse( ProjectFolderItem *item ) override; - virtual ProjectFolderItem *import( IProject *project ) override; - virtual bool reload(ProjectFolderItem* item) override; - virtual KJob* createImportJob(ProjectFolderItem* item) override; + Features features() const override; + + ProjectFolderItem* addFolder( const Path& folder, ProjectFolderItem *parent ) override; + ProjectFileItem* addFile( const Path& file, ProjectFolderItem *parent ) override; + bool removeFilesAndFolders( const QList &items ) override; + bool moveFilesAndFolders(const QList< ProjectBaseItem* >& items, ProjectFolderItem* newParent) override; + bool copyFilesAndFolders(const Path::List& items, ProjectFolderItem* newParent) override; + bool renameFolder(ProjectFolderItem* folder, const Path& newPath) override; + bool renameFile(ProjectFileItem* file, const Path& newPath) override; + + QList parse( ProjectFolderItem *item ) override; + ProjectFolderItem *import( IProject *project ) override; + bool reload(ProjectFolderItem* item) override; + KJob* createImportJob(ProjectFolderItem* item) override; protected: // // AbstractFileManagerPlugin interface // /** * Filter interface making it possible to hide files and folders from a project. * * The default implementation will query all IProjectFilter plugins and ask them * whether a given url should be included or not. * * @return True when @p path should belong to @p project, false otherwise. */ virtual bool isValid(const Path& path, const bool isFolder, IProject* project) const; /** * Customization hook enabling you to create custom FolderItems if required. * * The default implementation will return a simple @c ProjectFolderItem */ virtual ProjectFolderItem* createFolderItem( IProject* project, const Path& path, ProjectBaseItem* parent = 0); /** * Customization hook enabling you to create custom FileItems if required. * * The default implementation will return a simple @c ProjectFileItem */ virtual ProjectFileItem* createFileItem( IProject* project, const Path& path, ProjectBaseItem* parent); /** * @return the @c KDirWatch for the given @p project. */ KDirWatch* projectWatcher( IProject* project ) const; /** * Sets a list of filenames to ignore when importing a project * the filter is applied to files and folders, so both will be ignored. * * The filenames are matched via QString::operator==(), so no wildcard or * regex-matching for now * * This can be used for things like VCS-folders/files or other things a * plugin might want to hide. */ void setImportFileNameFilter( const QStringList& filterNames ); private: struct Private; // friend class Private; Private* const d; Q_PRIVATE_SLOT(d, KJob* eventuallyReadFolder( ProjectFolderItem* item, const bool forceRecursion = false )) Q_PRIVATE_SLOT(d, void addJobItems(FileManagerListJob* job, ProjectFolderItem* baseItem, const KIO::UDSEntryList& entries, const bool forceRecursion)) Q_PRIVATE_SLOT(d, void deleted(const QString &path)) Q_PRIVATE_SLOT(d, void created(const QString &path)) Q_PRIVATE_SLOT(d, void projectClosing(KDevelop::IProject* project)) Q_PRIVATE_SLOT(d, void jobFinished(KJob* job)) Q_SIGNALS: void reloadedFileItem(KDevelop::ProjectFileItem* file); void reloadedFolderItem(KDevelop::ProjectFolderItem* folder); void folderAdded(KDevelop::ProjectFolderItem* folder); void folderRemoved(KDevelop::ProjectFolderItem* folder); void folderRenamed(const KDevelop::Path& oldFolder, KDevelop::ProjectFolderItem* newFolder); void fileAdded(KDevelop::ProjectFileItem* file); void fileRemoved(KDevelop::ProjectFileItem* file); void fileRenamed(const KDevelop::Path& oldFile, KDevelop::ProjectFileItem* newFile); }; } #endif // KDEVPLATFORM_ABSTRACTGENERICMANAGER_H diff --git a/project/builderjob.h b/project/builderjob.h index e8f75d2667..ecc77aaa47 100644 --- a/project/builderjob.h +++ b/project/builderjob.h @@ -1,121 +1,121 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2007 Andreas Pakulat * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_BUILDERJOB_H #define KDEVPLATFORM_BUILDERJOB_H #include #include "projectexport.h" #include class KConfigGroup; namespace KDevelop { class ProjectBaseItem; class IProject; /** * Allows to build a list of project items or projects sequentially, where * failing to build one item in the list will fail the whole job. */ class KDEVPLATFORMPROJECT_EXPORT BuilderJob : public ExecuteCompositeJob { Q_OBJECT public: /** * Defines what action to do on the Project builder */ enum BuildType { Build /**< Build the selected items */, Prune /**< Prune the selected items */, Configure /**< Configure the selected items */, Install /**< Install the selected items */, Clean /**< Clean the selected items */ }; /** * Creates a Builder job */ BuilderJob(); - virtual ~BuilderJob(); + ~BuilderJob() override; /** * Allows to easily schedule building a couple of @p items using the * method identified by @p type * * @param type the build method to use * @param items the project items to add */ void addItems( BuildType type, const QList& items ); /** * Allows to easily schedule building a couple of @p projects using the * method identified by @p type * * @param type the build method to use * @param projects the projects to add */ void addProjects( BuildType type, const QList& projects ); /** * Allows to add a single @p item to the end of the list. The item will be * built using the method identified by @p type * * @param item The item to add to the list * @param type The build method to be used for the item */ void addItem( BuildType type, ProjectBaseItem* item ); /** * Allows to add a custom @p job to the end of the list. The build method specified by @p type * and (optionally) an item specified by @p item are needed to create a human-readable job name. * * @param type The build method which is represented by the @p job * @param job The job to add to the list * @param item The item which is build by the @p job */ void addCustomJob( BuildType type, KJob* job, ProjectBaseItem* item = 0 ); /** * Updates the job's name. * * Shall be called before registering this job in the run controller, but after * adding all required tasks to the job. */ void updateJobName(); /** * Starts this job */ void start() override; private: class BuilderJobPrivate* const d; friend class BuilderJobPrivate; }; } #endif diff --git a/project/filemanagerlistjob.h b/project/filemanagerlistjob.h index 5cd88c7558..84796383c8 100644 --- a/project/filemanagerlistjob.h +++ b/project/filemanagerlistjob.h @@ -1,77 +1,77 @@ /* This file is part of KDevelop Copyright 2009 Radu Benea 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 KDEVPLATFORM_FILEMANAGERLISTJOB_H #define KDEVPLATFORM_FILEMANAGERLISTJOB_H #include #include // uncomment to time imort jobs // #define TIME_IMPORT_JOB #ifdef TIME_IMPORT_JOB #include #endif namespace KDevelop { class ProjectFolderItem; class FileManagerListJob : public KIO::Job { Q_OBJECT public: FileManagerListJob(ProjectFolderItem* item, const bool forceRecursion); ProjectFolderItem* item() const; void addSubDir(ProjectFolderItem* item); void removeSubDir(ProjectFolderItem* item); void abort(); - virtual void start() override; + void start() override; signals: void entries(FileManagerListJob* job, ProjectFolderItem* baseItem, const KIO::UDSEntryList& entries, const bool forceRecursion); void nextJob(); private slots: void slotEntries(KIO::Job* job, const KIO::UDSEntryList& entriesIn ); void slotResult(KJob* job) override; void startNextJob(); private: QQueue m_listQueue; /// current base dir ProjectFolderItem* m_item; KIO::UDSEntryList entryList; const bool m_forceRecursion; // kill does not delete the job instantaniously bool m_aborted; #ifdef TIME_IMPORT_JOB QElapsedTimer m_timer; #endif }; } #endif // KDEVPLATFORM_FILEMANAGERLISTJOB_H diff --git a/project/importprojectjob.h b/project/importprojectjob.h index 35357d097c..587572cab0 100644 --- a/project/importprojectjob.h +++ b/project/importprojectjob.h @@ -1,56 +1,56 @@ /* This file is part of KDevelop Copyright 2004 Roberto Raggi Copyright 2007 Andreas Pakulat 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 KDEVPLATFORM_IMPORTPROJECTJOB_H #define KDEVPLATFORM_IMPORTPROJECTJOB_H #include #include "projectexport.h" namespace KDevelop { class ProjectFolderItem; class IProjectFileManager; class KDEVPLATFORMPROJECT_EXPORT ImportProjectJob: public KJob { Q_OBJECT public: ImportProjectJob(ProjectFolderItem *folder, IProjectFileManager *importer); - virtual ~ImportProjectJob(); + ~ImportProjectJob() override; public: void start() override; - virtual bool doKill() override; + bool doKill() override; private Q_SLOTS: void importDone(); void importCanceled(); void aboutToShutdown(); private: class ImportProjectJobPrivate* const d; friend class ImportProjectJobPrivate; }; } #endif // KDEVPLATFORM_IMPORTPROJECTJOB_H diff --git a/project/projectchangesmodel.h b/project/projectchangesmodel.h index 35bc1e2794..a43ae41299 100644 --- a/project/projectchangesmodel.h +++ b/project/projectchangesmodel.h @@ -1,66 +1,66 @@ /* This file is part of KDevelop Copyright 2010 Aleix Pol Gonzalez 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 KDEVPLATFORM_PROJECTCHANGESMODEL_H #define KDEVPLATFORM_PROJECTCHANGESMODEL_H #include #include #include "projectexport.h" class KJob; namespace KDevelop { class IProject; class IDocument; class KDEVPLATFORMPROJECT_EXPORT ProjectChangesModel : public VcsFileChangesModel { Q_OBJECT public: enum Role { ProjectNameRole = LastItemRole+1 }; explicit ProjectChangesModel(QObject* parent); - virtual ~ProjectChangesModel(); + ~ProjectChangesModel() override; void updateState(KDevelop::IProject* p, const KDevelop::VcsStatusInfo& status); void changes(KDevelop::IProject* project, const QList& urls, KDevelop::IBasicVersionControl::RecursionMode mode); public slots: void reloadAll(); void reload(const QList& p); void reload(const QList& p); void addProject(KDevelop::IProject* p); void removeProject(KDevelop::IProject* p); void statusReady(KJob* job); void documentSaved(KDevelop::IDocument*); void itemsAdded(const QModelIndex& idx, int start, int end); void jobUnregistered(KJob*); void repositoryBranchChanged(const QUrl& url); void branchNameReady(KDevelop::VcsJob* job); private: QStandardItem* projectItem(KDevelop::IProject* p) const; }; } #endif // KDEVPLATFORM_PROJECTCHANGESMODEL_H diff --git a/project/projectconfigskeleton.h b/project/projectconfigskeleton.h index bf00e5f1c1..ed17ed0997 100644 --- a/project/projectconfigskeleton.h +++ b/project/projectconfigskeleton.h @@ -1,72 +1,72 @@ /* This file is part of KDevelop Copyright 2006 Adam Treat Copyright 2007 Andreas Pakulat 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 KDEVPLATFORM_PROJECTCONFIGSKELETON_H #define KDEVPLATFORM_PROJECTCONFIGSKELETON_H #include "projectexport.h" #include namespace KDevelop { class Path; class KDEVPLATFORMPROJECT_EXPORT ProjectConfigSkeleton: public KConfigSkeleton { Q_OBJECT public: /** * Constructs a new skeleton, the skeleton will write to the developer * configuration file, which is by default located in projectdir/.kdev4 * The defaults will be set from the project file, which is in the projectdir * * @param configname The absolute filename of the developer configuration file */ explicit ProjectConfigSkeleton( const QString & configname ); - virtual ~ProjectConfigSkeleton(); + ~ProjectConfigSkeleton() override; void setDeveloperTempFile( const QString& ); void setProjectTempFile( const QString& ); void setProjectFile( const Path& ); void setDeveloperFile( const Path& ); void setDefaults() override; bool useDefaults( bool b ) override; bool writeConfig(); Path projectFile() const; Path developerFile() const; private: /** * There's no way in KDE4 API to find out the file that the config object * was created from, so we can't apply defaults when using this * constructors. Thus I'm making this private, so we can find out when * this constructor is used and see if we need to add appropriate API to * kdelibs */ explicit ProjectConfigSkeleton( KSharedConfigPtr config ); struct ProjectConfigSkeletonPrivate * const d; }; } #endif diff --git a/project/projectfiltermanager.h b/project/projectfiltermanager.h index 61c2207779..acd9c3c0d2 100644 --- a/project/projectfiltermanager.h +++ b/project/projectfiltermanager.h @@ -1,100 +1,100 @@ /* This file is part of KDevelop Copyright 2013 Milian Wolff 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 KDEVPLATFORM_PROJECTFILTERMANAGER_H #define KDEVPLATFORM_PROJECTFILTERMANAGER_H #include "projectexport.h" #include #include #include namespace KDevelop { class IProjectFilter; class IProjectFilterProvider; class IPlugin; class IProject; class Path; /** * @short A helper class to manage project filtering in file managers. * * Use this class in implementations of IProjectFileManager to simplify * the management of IProjectFilter instances for projects managed by * your file manager. * * NOTE: This interface is _not_ threadsafe. But you can use filtersForProject() * to implement thread safe filtering. * * @author Milian Wolff */ class KDEVPLATFORMPROJECT_EXPORT ProjectFilterManager : public QObject { Q_OBJECT public: explicit ProjectFilterManager(QObject* parent = 0); - virtual ~ProjectFilterManager(); + ~ProjectFilterManager() override; /** * @copydoc IProjectFilter::isValid */ bool isValid(const Path& path, bool isFolder, IProject* project) const; /** * Manage the filters of the given project. */ void add(IProject* project); /** * Remove the managed filters of the given project. */ void remove(IProject* project); /** * TODO: remove this once the cmake manager got cleaned up to not need this * anymore. * * @return true if the project is managed, false otherwise. */ bool isManaged(IProject* project) const; /** * @return the current list of project filters for a given managed project. * * This can be used to implement a thread safe project filtering */ QVector > filtersForProject(IProject* project) const; private: struct Private; QScopedPointer d; Q_PRIVATE_SLOT(d, void pluginLoaded( KDevelop::IPlugin* ) ) Q_PRIVATE_SLOT(d, void unloadingPlugin( KDevelop::IPlugin* ) ) Q_PRIVATE_SLOT(d, void filterChanged( KDevelop::IProjectFilterProvider*, KDevelop::IProject* ) ) }; } #endif // KDEVPLATFORM_PROJECTFILTERMANAGER_H diff --git a/project/projectmodel.h b/project/projectmodel.h index acf0655b61..b164ae856c 100644 --- a/project/projectmodel.h +++ b/project/projectmodel.h @@ -1,492 +1,492 @@ /* This file is part of KDevelop Copyright 2005 Roberto Raggi Copyright 2007 Andreas Pakulat Copyright 2007 Aleix Pol 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 KDEVPLATFORM_PROJECTMODEL_H #define KDEVPLATFORM_PROJECTMODEL_H #include #include #include "projectexport.h" #include template struct QPair; template class QList; namespace KDevelop { class IProject; class ProjectFolderItem; class ProjectBuildFolderItem; class ProjectFileItem; class ProjectTargetItem; class ProjectExecutableTargetItem; class ProjectLibraryTargetItem; class ProjectModel; class IndexedString; class Path; /** * Base class to implement the visitor pattern for the project item tree. * * Feel free to subclass it and add overloads for the methods corresponding * to the items you are interested in. * * Start visiting using one of the visit methods. */ class KDEVPLATFORMPROJECT_EXPORT ProjectVisitor { public: ProjectVisitor(); virtual ~ProjectVisitor(); /** * Visit the whole project model tree. */ virtual void visit( ProjectModel* ); /** * Visit the tree starting from the project root item. */ virtual void visit( IProject* ); /** * Visit the folder and anything it contains. */ virtual void visit( ProjectFolderItem* ); /** * Visit the file. */ virtual void visit( ProjectFileItem* ); /** * Visit the build folder and anything it contains. */ virtual void visit( ProjectBuildFolderItem* ); /** * Visit the target and all children it may contain. */ virtual void visit( ProjectExecutableTargetItem* ); /** * Visit the target and all children it may contain. */ virtual void visit( ProjectLibraryTargetItem* ); }; /** * Interface that allows a developer to implement the three basic types of * items you would see in a multi-project * \li Folder * \li Project * \li Custom Target * \li Library Target * \li Executable Target * \li File */ class KDEVPLATFORMPROJECT_EXPORT ProjectBaseItem { public: ProjectBaseItem( IProject*, const QString &name, ProjectBaseItem *parent = 0 ); virtual ~ProjectBaseItem(); enum ProjectItemType { BaseItem = 0 /** item is a base item */, BuildFolder = 1 /** item is a buildable folder */, Folder = 2 /** item is a folder */, ExecutableTarget = 3 /** item is an executable target */, LibraryTarget = 4 /** item is a library target */, Target = 5 /** item is a target */, File = 6 /** item is a file */, CustomProjectItemType = 100 /** type which should be used as base for custom types */ }; enum RenameStatus { RenameOk = 0, ExistingItemSameName = 1, ProjectManagerRenameFailed = 2, InvalidNewName = 3 }; /** @returns Returns the project that the item belongs to. */ IProject* project() const; /** @returns If this item is a folder, it returns a pointer to the folder, otherwise returns a 0 pointer. */ virtual ProjectFolderItem *folder() const; /** @returns If this item is a target, it returns a pointer to the target, otherwise returns a 0 pointer. */ virtual ProjectTargetItem *target() const; /** @returns If this item is a file, it returns a pointer to the file, otherwise returns a 0 pointer. */ virtual ProjectFileItem *file() const; /** @returns If this item is a file, it returns a pointer to the file, otherwise returns a 0 pointer. */ virtual ProjectExecutableTargetItem *executable() const; /** @returns Returns a list of the folders that have this object as the parent. */ QList folderList() const; /** @returns Returns a list of the targets that have this object as the parent. */ QList targetList() const; /** @returns Returns a list of the files that have this object as the parent. */ QList fileList() const; virtual bool lessThan( const KDevelop::ProjectBaseItem* ) const; static bool pathLessThan(KDevelop::ProjectBaseItem* item1, KDevelop::ProjectBaseItem* item2); /** @returns the @p row item in the list of children of this item or 0 if there is no such child. */ ProjectBaseItem* child( int row ) const; /** @returns the list of children of this item. */ QList children() const; /** @returns a valid QModelIndex for usage with the model API for this item. */ QModelIndex index() const; /** @returns The parent item if this item has one, else it return 0. */ virtual ProjectBaseItem* parent() const; /** @returns the displayed text of this item. */ QString text() const; /** @returns the row in the list of children of this items parent, or -1. */ int row() const; /** @returns the number of children of this item, or 0 if there are none. */ int rowCount() const; /** @returns the model to which this item belongs, or 0 if its not associated to a model. */ ProjectModel* model() const; /** * Adds a new child item to this item. */ void appendRow( ProjectBaseItem* item ); /** * Removes and deletes the item at the given @p row if there is one. */ void removeRow( int row ); /** * Removes and deletes the @p count items after the given @p row if there is one. */ void removeRows( int row, int count ); /** * Returns and removes the item at the given @p row if there is one. */ ProjectBaseItem* takeRow( int row ); /** @returns RTTI info, allows to know the type of item */ virtual int type() const; /** @returns a string to pass to QIcon::fromTheme() as icon-name suitable to represent this item. */ virtual QString iconName() const; /** * Set the path of this item. * * @note This function never renames the item in the project manager or * on the filesystem, it only changes the path and possibly the text nothing else. */ virtual void setPath( const Path& ); /** * @returns the path of this item. */ Path path() const; /** * @returns the basename of this items path (if any) * * Convenience function, returns the same as @c text() for most items. */ QString baseName() const; /** * Renames the item to the new name. * @returns status information whether the renaming succeeded. */ virtual RenameStatus rename( const QString& newname ); bool isProjectRoot() const; /** * Default flags: Qt::ItemIsEnabled | Qt::ItemIsSelectable * * @returns the flags supported by the item */ virtual Qt::ItemFlags flags(); /** * Sets what flags should be returned by ::flags() method. */ void setFlags(Qt::ItemFlags flags); protected: /** * Allows to change the displayed text of this item. * * Most items assume text == baseName so this is *not* public. * * @param text the new text */ void setText( const QString& text ); class ProjectBaseItemPrivate* const d_ptr; ProjectBaseItem( ProjectBaseItemPrivate& dd ); void setRow( int row ); void setModel( ProjectModel* model ); private: Q_DECLARE_PRIVATE(ProjectBaseItem) friend class ProjectModel; }; /** * Implementation of the ProjectBaseItem interface that is specific to a * folder */ class KDEVPLATFORMPROJECT_EXPORT ProjectFolderItem: public ProjectBaseItem { public: /** * Create a new ProjectFolderItem with the given @p path and an optional @p parent * in the given @p project. */ ProjectFolderItem( IProject* project, const Path& path, ProjectBaseItem* parent = 0 ); /** * Create a child ProjectFolderItem of @p parent with @p name. * * The path is set automatically. */ ProjectFolderItem( const QString& name, ProjectBaseItem *parent ); - virtual ~ProjectFolderItem(); + ~ProjectFolderItem() override; - virtual void setPath(const Path& ) override; + void setPath(const Path& ) override; - virtual ProjectFolderItem *folder() const override; + ProjectFolderItem *folder() const override; ///Reimplemented from QStandardItem - virtual int type() const override; + int type() const override; /** * Get the folder name, equal to path().fileName() or text(). */ QString folderName() const; /** @returns Returns whether this folder directly contains the specified file or folder. */ bool hasFileOrFolder(const QString& name) const; - virtual QString iconName() const override; - virtual RenameStatus rename(const QString& newname) override; + QString iconName() const override; + RenameStatus rename(const QString& newname) override; private: void propagateRename( const Path& newBase ) const; }; /** * Folder which contains buildable targets as part of a buildable project */ class KDEVPLATFORMPROJECT_EXPORT ProjectBuildFolderItem: public ProjectFolderItem { public: /** * Create a new ProjectBuildFolderItem with the given @p path with the optional * parent @p parent in the given @p project. */ ProjectBuildFolderItem( IProject* project, const Path &path, ProjectBaseItem* parent = 0 ); /** * Create a child ProjectBuildFolderItem of @p parent with @p name. * * The path is set automatically. */ ProjectBuildFolderItem( const QString &name, ProjectBaseItem *parent ); ///Reimplemented from QStandardItem - virtual int type() const override; - virtual QString iconName() const override; + int type() const override; + QString iconName() const override; }; /** * Object which represents a target in a build system. * * This object contains all properties specific to a target. */ class KDEVPLATFORMPROJECT_EXPORT ProjectTargetItem: public ProjectBaseItem { public: ProjectTargetItem( IProject*, const QString &name, ProjectBaseItem *parent = 0 ); ///Reimplemented from QStandardItem - virtual int type() const override; + int type() const override; - virtual ProjectTargetItem *target() const override; - virtual QString iconName() const override; - virtual void setPath(const Path& path ) override; + ProjectTargetItem *target() const override; + QString iconName() const override; + void setPath(const Path& path ) override; }; /** * Object which represents an executable target in a build system. * * This object contains all properties specific to an executable. */ class KDEVPLATFORMPROJECT_EXPORT ProjectExecutableTargetItem: public ProjectTargetItem { public: ProjectExecutableTargetItem( IProject*, const QString &name, ProjectBaseItem *parent = 0 ); - virtual ProjectExecutableTargetItem *executable() const override; - virtual int type() const override; + ProjectExecutableTargetItem *executable() const override; + int type() const override; virtual QUrl builtUrl() const=0; virtual QUrl installedUrl() const=0; }; /** * Object which represents a library target in a build system. * * This object contains all properties specific to a library. */ class KDEVPLATFORMPROJECT_EXPORT ProjectLibraryTargetItem: public ProjectTargetItem { public: ProjectLibraryTargetItem(IProject* project, const QString &name, ProjectBaseItem *parent = 0 ); - virtual int type() const override; + int type() const override; }; /** * Object which represents a file. */ class KDEVPLATFORMPROJECT_EXPORT ProjectFileItem: public ProjectBaseItem { public: /** * Create a new ProjectFileItem with the given @p path and an optional @p parent * in the given @p project. */ ProjectFileItem( IProject* project, const Path& path, ProjectBaseItem* parent = 0 ); /** * Create a child ProjectFileItem of @p parent with the given @p name. * * The path is set automatically. */ ProjectFileItem( const QString& name, ProjectBaseItem *parent ); - ~ProjectFileItem(); + ~ProjectFileItem() override; ///Reimplemented from QStandardItem - virtual int type() const override; + int type() const override; - virtual ProjectFileItem *file() const override; + ProjectFileItem *file() const override; /** * @returns the file name, equal to path().fileName() or text() */ QString fileName() const; - virtual void setPath( const Path& ) override; - virtual QString iconName() const override; - virtual RenameStatus rename(const QString& newname) override; + void setPath( const Path& ) override; + QString iconName() const override; + RenameStatus rename(const QString& newname) override; /** * @return the items indexed path, which is often required for performant * lookups or memory efficient storage. */ IndexedString indexedPath() const; }; /** * Class providing some convenience methods for accessing the project model * @todo: maybe switch to QAbstractItemModel, would make the implementation * for at least the checkbox-behaviour easier */ class KDEVPLATFORMPROJECT_EXPORT ProjectModel: public QAbstractItemModel { Q_OBJECT public: enum Roles { ProjectRole = Qt::UserRole+1 , ProjectItemRole , UrlRole , LastRole }; explicit ProjectModel( QObject *parent = 0 ); - virtual ~ProjectModel(); + ~ProjectModel() override; void clear(); void appendRow( ProjectBaseItem* item ); void removeRow( int row ); ProjectBaseItem* takeRow( int row ); ProjectBaseItem* itemAt( int row ) const; QList topItems() const; QModelIndex pathToIndex(const QStringList& tofetch) const; QStringList pathFromIndex(const QModelIndex& index) const; QModelIndex indexFromItem( const ProjectBaseItem* item ) const; ProjectBaseItem* itemFromIndex( const QModelIndex& ) const; - virtual int columnCount( const QModelIndex& parent = QModelIndex() ) const override; - virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const override; - virtual QModelIndex parent( const QModelIndex& child ) const override; - virtual int rowCount( const QModelIndex& parent = QModelIndex() ) const override; - virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + int columnCount( const QModelIndex& parent = QModelIndex() ) const override; + QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const override; + QModelIndex parent( const QModelIndex& child ) const override; + int rowCount( const QModelIndex& parent = QModelIndex() ) const override; + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; - virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; - virtual bool insertColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override; - virtual bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; + bool insertColumns(int column, int count, const QModelIndex& parent = QModelIndex()) override; + bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; - virtual Qt::ItemFlags flags(const QModelIndex& index) const override; - virtual Qt::DropActions supportedDropActions() const override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + Qt::DropActions supportedDropActions() const override; /** * @return all items for the given indexed path. */ QList itemsForPath(const IndexedString& path) const; /** * Returns the first item for the given indexed path. */ ProjectBaseItem* itemForPath(const IndexedString& path) const; private: class ProjectModelPrivate* const d; friend class ProjectBaseItem; }; KDEVPLATFORMPROJECT_EXPORT QStringList joinProjectBasePath( const QStringList& partialpath, KDevelop::ProjectBaseItem* item ); KDEVPLATFORMPROJECT_EXPORT QStringList removeProjectBasePath( const QStringList& fullpath, KDevelop::ProjectBaseItem* item ); } Q_DECLARE_METATYPE(KDevelop::ProjectBaseItem*) Q_DECLARE_METATYPE(KDevelop::ProjectFolderItem*) Q_DECLARE_METATYPE(KDevelop::ProjectFileItem*) Q_DECLARE_METATYPE(KDevelop::ProjectLibraryTargetItem*) Q_DECLARE_METATYPE(KDevelop::ProjectExecutableTargetItem*) Q_DECLARE_METATYPE(KDevelop::ProjectTargetItem*) Q_DECLARE_METATYPE(KDevelop::ProjectBuildFolderItem*) Q_DECLARE_METATYPE(QList) #endif // KDEVPLATFORM_PROJECTMODEL_H diff --git a/project/tests/projectmodelperformancetest.h b/project/tests/projectmodelperformancetest.h index b799afeb14..a7be335318 100644 --- a/project/tests/projectmodelperformancetest.h +++ b/project/tests/projectmodelperformancetest.h @@ -1,52 +1,52 @@ /*************************************************************************** * Copyright 2010 Andreas Pakulat * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVELOP_PROJECT_PROJECTMODELPERFORMANCETEST_INCLUDED #define KDEVELOP_PROJECT_PROJECTMODELPERFORMANCETEST_INCLUDED #include #include namespace KDevelop { class ProjectModel; class ProjectBaseItem; } class QTreeView; class ProjectModelPerformanceTest : public QWidget { Q_OBJECT public: ProjectModelPerformanceTest(QWidget* parent = 0); - virtual ~ProjectModelPerformanceTest(); + ~ProjectModelPerformanceTest() override; private slots: void init(); void addSmallTree(); void addBigTree(); void addBigTreeDelayed(); void addItemDelayed(); private: QStack currentParent; int originalWidth; KDevelop::ProjectModel* model; QTreeView* view; }; #endif diff --git a/serialization/indexedstring.cpp b/serialization/indexedstring.cpp index 4f8e791307..268c669b34 100644 --- a/serialization/indexedstring.cpp +++ b/serialization/indexedstring.cpp @@ -1,289 +1,290 @@ /*************************************************************************** Copyright 2008 David Nolden ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #include "indexedstring.h" #include "serialization/stringrepository.h" #include "referencecounting.h" namespace KDevelop { namespace { struct IndexedStringData { unsigned short length; unsigned int refCount; unsigned int itemSize() const { return sizeof(IndexedStringData) + length; } unsigned int hash() const { IndexedString::RunningHash running; const char* str = ((const char*)this) + sizeof(IndexedStringData); for(int a = length-1; a >= 0; --a) { running.append(*str); ++str; } return running.hash; } }; inline void increase(uint& val) { ++val; } inline void decrease(uint& val) { --val; } struct IndexedStringRepositoryItemRequest { //The text is supposed to be utf8 encoded IndexedStringRepositoryItemRequest(const char* text, unsigned int hash, unsigned short length) : m_hash(hash), m_length(length), m_text(text) { } enum { AverageSize = 10 //This should be the approximate average size of an Item }; typedef unsigned int HashType; //Should return the hash-value associated with this request(For example the hash of a string) HashType hash() const { return m_hash; } //Should return the size of an item created with createItem uint itemSize() const { return sizeof(IndexedStringData) + m_length; } //Should create an item where the information of the requested item is permanently stored. The pointer //@param item equals an allocated range with the size of itemSize(). void createItem(IndexedStringData* item) const { item->length = m_length; item->refCount = 0; ++item; memcpy(item, m_text, m_length); } static void destroy(IndexedStringData* item, KDevelop::AbstractItemRepository&) { Q_UNUSED(item); //Nothing to do here (The object is not intelligent) } static bool persistent(const IndexedStringData* item) { return (bool)item->refCount; } //Should return whether the here requested item equals the given item bool equals(const IndexedStringData* item) const { return item->length == m_length && (memcmp(++item, m_text, m_length) == 0); } unsigned int m_hash; unsigned short m_length; const char* m_text; }; typedef ItemRepository IndexedStringRepository; ///@param item must be valid(nonzero) inline QString stringFromItem(const IndexedStringData* item) { const unsigned short* textPos = (unsigned short*)(item+1); return QString::fromUtf8((char*)textPos, item->length); } inline QByteArray arrayFromItem(const IndexedStringData* item) { const unsigned short* textPos = (unsigned short*)(item+1); return QByteArray((char*)textPos, item->length); } inline const char* c_strFromItem(const IndexedStringData* item) { return (const char*)(item+1); } } namespace { RepositoryManager< IndexedStringRepository >& getGlobalIndexedStringRepository(){ static RepositoryManager< IndexedStringRepository > globalIndexedStringRepository("String Index"); return globalIndexedStringRepository; } } IndexedString::IndexedString() : m_index(0) { } ///@param str must be a utf8 encoded string, does not need to be 0-terminated. ///@param length must be its length in bytes. IndexedString::IndexedString( const char* str, unsigned short length, unsigned int hash ) { if(!length) m_index = 0; else if(length == 1) m_index = 0xffff0000 | str[0]; else { QMutexLocker lock(getGlobalIndexedStringRepository()->mutex()); m_index = getGlobalIndexedStringRepository()->index(IndexedStringRepositoryItemRequest(str, hash ? hash : hashString(str, length), length)); if(shouldDoDUChainReferenceCounting(this)) increase(getGlobalIndexedStringRepository()->dynamicItemFromIndexSimple(m_index)->refCount); } } IndexedString::IndexedString( char c ) : m_index(0xffff0000 | c) {} IndexedString::IndexedString( const QUrl& url ) : IndexedString(url.isLocalFile() ? url.toLocalFile() : url.toString()) { Q_ASSERT(url.isEmpty() || !url.isRelative()); } IndexedString::IndexedString( const QString& string ) : IndexedString(string.toUtf8()) {} IndexedString::IndexedString( const char* str) : IndexedString(str, str ? strlen(str) : 0) {} IndexedString::IndexedString( const QByteArray& str) : IndexedString(str.constData(), str.length()) {} IndexedString::~IndexedString() { if(m_index && (m_index & 0xffff0000) != 0xffff0000) { if(shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(getGlobalIndexedStringRepository()->mutex()); decrease(getGlobalIndexedStringRepository()->dynamicItemFromIndexSimple(m_index)->refCount); } } } IndexedString::IndexedString( const IndexedString& rhs ) : m_index(rhs.m_index) { if(m_index && (m_index & 0xffff0000) != 0xffff0000) { if(shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(getGlobalIndexedStringRepository()->mutex()); increase(getGlobalIndexedStringRepository()->dynamicItemFromIndexSimple(m_index)->refCount); } } } IndexedString& IndexedString::operator=(const IndexedString& rhs) { if(m_index == rhs.m_index) return *this; if(m_index && (m_index & 0xffff0000) != 0xffff0000) { if(shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(getGlobalIndexedStringRepository()->mutex()); decrease(getGlobalIndexedStringRepository()->dynamicItemFromIndexSimple(m_index)->refCount); } } m_index = rhs.m_index; if(m_index && (m_index & 0xffff0000) != 0xffff0000) { if(shouldDoDUChainReferenceCounting(this)) { QMutexLocker lock(getGlobalIndexedStringRepository()->mutex()); increase(getGlobalIndexedStringRepository()->dynamicItemFromIndexSimple(m_index)->refCount); } } return *this; } QUrl IndexedString::toUrl() const { if (isEmpty()) { return {}; } - QUrl ret = QUrl::fromUserInput( str() ); - Q_ASSERT(!ret.isRelative()); - return ret; + + const QUrl url = QUrl::fromUserInput( str() ); + Q_ASSERT(url.isEmpty() || !url.isRelative()); + return url; } QString IndexedString::str() const { if(!m_index) return QString(); else if((m_index & 0xffff0000) == 0xffff0000) return QString(QChar((char)m_index & 0xff)); else return stringFromItem(getGlobalIndexedStringRepository()->itemFromIndex(m_index)); } int IndexedString::length() const { return lengthFromIndex(m_index); } int IndexedString::lengthFromIndex(unsigned int index) { if(!index) return 0; else if((index & 0xffff0000) == 0xffff0000) return 1; else return getGlobalIndexedStringRepository()->itemFromIndex(index)->length; } const char* IndexedString::c_str() const { if(!m_index) return 0; else if((m_index & 0xffff0000) == 0xffff0000) return ((char*)&m_index)+3; //The last byte contains the character else return c_strFromItem(getGlobalIndexedStringRepository()->itemFromIndex(m_index)); } QByteArray IndexedString::byteArray() const { if(!m_index) return QByteArray(); else if((m_index & 0xffff0000) == 0xffff0000) return QString(QChar((char)m_index & 0xff)).toUtf8(); else return arrayFromItem(getGlobalIndexedStringRepository()->itemFromIndex(m_index)); } unsigned int IndexedString::hashString(const char* str, unsigned short length) { RunningHash running; for(int a = length-1; a >= 0; --a) { running.append(*str); ++str; } return running.hash; } uint IndexedString::indexForString( const char* str, short unsigned length, uint hash) { if(!length) return 0; else if(length == 1) return 0xffff0000 | str[0]; else { QMutexLocker lock(getGlobalIndexedStringRepository()->mutex()); return getGlobalIndexedStringRepository()->index(IndexedStringRepositoryItemRequest(str, hash ? hash : hashString(str, length), length)); } } uint IndexedString::indexForString(const QString& str, uint hash) { const QByteArray array(str.toUtf8()); return indexForString(array.constBegin(), array.size(), hash); } } QDebug operator<<(QDebug s, const KDevelop::IndexedString& string) { s.nospace() << string.str(); return s.space(); } diff --git a/shell/areadisplay.h b/shell/areadisplay.h index 994390d5cd..8112a31203 100644 --- a/shell/areadisplay.h +++ b/shell/areadisplay.h @@ -1,64 +1,64 @@ /*************************************************************************** * Copyright 2013 Aleix Pol Gonzalez * * * * 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 Library 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. * ***************************************************************************/ #ifndef AREADISPLAY_H #define AREADISPLAY_H #include class QLabel; class QToolButton; class QMenu; namespace KDevelop { class MainWindow; } namespace Sublime { class MainWindow; class Area; } /** * This widget displays the current area by the menu */ class AreaDisplay : public QWidget { Q_OBJECT public: explicit AreaDisplay(KDevelop::MainWindow* parent); - virtual QSize sizeHint() const override; - virtual QSize minimumSizeHint() const override; + QSize sizeHint() const override; + QSize minimumSizeHint() const override; protected: - virtual bool eventFilter(QObject* obj, QEvent* event) override; + bool eventFilter(QObject* obj, QEvent* event) override; private slots: void newArea(Sublime::Area* area); void backToCode(); private: QLabel* m_separator; QMenu* m_menu; QToolButton* m_button; KDevelop::MainWindow* m_mainWindow; }; #endif // AREADISPLAY_H diff --git a/shell/checkerstatus.h b/shell/checkerstatus.h index 8ba7b32e63..6407a98349 100644 --- a/shell/checkerstatus.h +++ b/shell/checkerstatus.h @@ -1,97 +1,97 @@ /* * Copyright 2015 Laszlo Kis-Adam * * 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. */ #ifndef CHECKER_STATUS_H #define CHECKER_STATUS_H #include #include struct CheckerStatusPrivate; namespace KDevelop { /** * Status / Progress reporter for checker tools. It shows a progress bar as more and more items are checked. * As part of initialization the max. number of items have to be set, and then when an item is checked that has to be indicated to the class. When stopped the progressbar first filled up to max, then it disappears. * * Initialization: * @code * m_status = new CheckerStatus(); * m_status->setCheckerName(QStringLiteral("SomeChecker")); * ICore::self()->uiController()->registerStatus(m_status); * @endcode * * Starting: * @code * m_status->setMaxItems(9001); * m_status->start(); * @endcode * * Stopping: * @code * m_status->stop(); * @endcode * * Showing progress: * @code * m_status->itemChecked(); * @endcode */ class KDEVPLATFORMSHELL_EXPORT CheckerStatus : public QObject, public KDevelop::IStatus { Q_OBJECT Q_INTERFACES(KDevelop::IStatus) public: CheckerStatus(); - ~CheckerStatus(); + ~CheckerStatus() override; - virtual QString statusName() const override; + QString statusName() const override; /// Sets the name of the checker tool void setCheckerName(const QString &name); /// Sets the maximum number of items that will be checked void setMaxItems(int maxItems); /// Increases the number of checked items void itemChecked(); /// Starts status / progress reporting void start(); /// Stops status / progress reporting void stop(); signals: void clearMessage(KDevelop::IStatus*) override; void showMessage(KDevelop::IStatus*, const QString &message, int timeout = 0) override; void showErrorMessage(const QString & message, int timeout = 0) override; void hideProgress(KDevelop::IStatus*) override; void showProgress(KDevelop::IStatus*, int minimum, int maximum, int value) override; private: QScopedPointer d; }; } #endif diff --git a/shell/configdialog.h b/shell/configdialog.h index a91ea399f0..f927bb5fb2 100644 --- a/shell/configdialog.h +++ b/shell/configdialog.h @@ -1,89 +1,89 @@ /* * This file is part of KDevelop * Copyright 2014 Alex Richardson * * 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 KDEVPLATFORM_CONFIGDIALOG_H #define KDEVPLATFORM_CONFIGDIALOG_H #include namespace KDevelop { class ConfigPage; class IPlugin; /** * This class is meant to be used to show the global config dialog and the per-project config dialog. * * This used to be handled by KSettings::Dialog, but since we are no longer using KCMs for config widgets, * we use this class instead. * * TODO: check if we can share this with Kate */ class ConfigDialog : public KPageDialog { Q_OBJECT public: explicit ConfigDialog(const QVector& pages, QWidget* parent = 0, Qt::WindowFlags flags = 0); public Q_SLOTS: /** * Remove a config page */ void removeConfigPage(ConfigPage* page); /** * Add a new config page. * @param page the new page to add * @param next if this parameter is passed the new page will be before it, otherwise * it will be inserted as the last config page. */ void addConfigPage(ConfigPage* page, ConfigPage* next = nullptr); /** * Add a new sub config page * @param parentPage the parent page * @param page the page to add */ void addSubConfigPage(ConfigPage* parentPage, ConfigPage* page); Q_SIGNALS: void configSaved(ConfigPage* page); protected: - virtual void closeEvent(QCloseEvent* event) override; + void closeEvent(QCloseEvent* event) override; private: KPageWidgetItem* itemForPage(ConfigPage* page) const; int checkForUnsavedChanges(KPageWidgetItem* current, KPageWidgetItem* before); void applyChanges(ConfigPage* page); void removePagesForPlugin(IPlugin* plugin); void addConfigPageInternal(KPageWidgetItem* item, ConfigPage* page); void onPageChanged(); private: // we have to use QPointer since KPageDialog::removePage() also removes all child pages QList> m_pages; // TODO: use a QVector once we depend on Qt 5.4 bool m_currentPageHasChanges = false; bool m_currentlyApplyingChanges = false; }; } #endif // KDEVPLATFORM_CONFIGDIALOG_H diff --git a/shell/debugcontroller.cpp b/shell/debugcontroller.cpp index 64ab25d77e..520a356ffb 100644 --- a/shell/debugcontroller.cpp +++ b/shell/debugcontroller.cpp @@ -1,534 +1,534 @@ /* This file is part of KDevelop * * Copyright 1999-2001 John Birch * Copyright 2001 by Bernd Gehrmann * Copyright 2006 Vladimir Prus * Copyright 2007 Hamish Rodda * Copyright 2009 Niko Sams * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include "debugcontroller.h" #include #include #include #include #include #include #include "../interfaces/idocument.h" #include "../interfaces/icore.h" #include "../interfaces/idocumentcontroller.h" #include "../interfaces/ipartcontroller.h" #include "../interfaces/contextmenuextension.h" #include "../interfaces/context.h" #include "../language/interfaces/editorcontext.h" #include "../sublime/view.h" #include "../sublime/mainwindow.h" #include "../sublime/area.h" #include "../debugger/breakpoint/breakpointmodel.h" #include "../debugger/breakpoint/breakpointwidget.h" #include "../debugger/variable/variablewidget.h" #include "../debugger/framestack/framestackmodel.h" #include "../debugger/framestack/framestackwidget.h" #include "core.h" #include "debug.h" #include "uicontroller.h" namespace KDevelop { template class DebuggerToolFactory : public KDevelop::IToolViewFactory { public: DebuggerToolFactory(DebugController* controller, const QString &id, Qt::DockWidgetArea defaultArea) : m_controller(controller), m_id(id), m_defaultArea(defaultArea) {} - virtual QWidget* create(QWidget *parent = 0) override + QWidget* create(QWidget *parent = 0) override { return new T(m_controller, parent); } - virtual QString id() const override + QString id() const override { return m_id; } - virtual Qt::DockWidgetArea defaultPosition() override + Qt::DockWidgetArea defaultPosition() override { return m_defaultArea; } - virtual void viewCreated(Sublime::View* view) override + void viewCreated(Sublime::View* view) override { if (view->widget()->metaObject()->indexOfSignal("requestRaise()") != -1) QObject::connect(view->widget(), SIGNAL(requestRaise()), view, SLOT(requestRaise())); } /* At present, some debugger widgets (e.g. breakpoint) contain actions so that shortcuts work, but they don't need any toolbar. So, suppress toolbar action. */ - virtual QList toolBarActions( QWidget* viewWidget ) const override + QList toolBarActions( QWidget* viewWidget ) const override { Q_UNUSED(viewWidget); return QList(); } private: DebugController* m_controller; QString m_id; Qt::DockWidgetArea m_defaultArea; }; DebugController::DebugController(QObject *parent) : IDebugController(parent), KXMLGUIClient(), m_continueDebugger(0), m_stopDebugger(0), m_interruptDebugger(0), m_runToCursor(0), m_jumpToCursor(0), m_stepOver(0), m_stepIntoInstruction(0), m_stepInto(0), m_stepOverInstruction(0), m_stepOut(0), m_toggleBreakpoint(0), m_breakpointModel(new BreakpointModel(this)), m_variableCollection(new VariableCollection(this)), m_uiInitialized(false) { setComponentName("kdevdebugger", "kdevdebugger"); setXMLFile("kdevdebuggershellui.rc"); } void DebugController::initialize() { m_breakpointModel->load(); } void DebugController::initializeUi() { if (m_uiInitialized) return; m_uiInitialized = true; if((Core::self()->setupFlags() & Core::NoUi)) return; setupActions(); ICore::self()->uiController()->addToolView( i18n("Frame Stack"), new DebuggerToolFactory( this, "org.kdevelop.debugger.StackView", Qt::BottomDockWidgetArea)); ICore::self()->uiController()->addToolView( i18n("Breakpoints"), new DebuggerToolFactory( this, "org.kdevelop.debugger.BreakpointsView", Qt::BottomDockWidgetArea)); ICore::self()->uiController()->addToolView( i18n("Variables"), new DebuggerToolFactory( this, "org.kdevelop.debugger.VariablesView", Qt::LeftDockWidgetArea)); foreach(KParts::Part* p, KDevelop::ICore::self()->partController()->parts()) partAdded(p); connect(KDevelop::ICore::self()->partController(), &IPartController::partAdded, this, &DebugController::partAdded); ICore::self()->uiController()->activeMainWindow()->guiFactory()->addClient(this); stateChanged("ended"); } void DebugController::cleanup() { if (m_currentSession) m_currentSession.data()->stopDebugger(); } DebugController::~DebugController() { } BreakpointModel* DebugController::breakpointModel() { return m_breakpointModel; } VariableCollection* DebugController::variableCollection() { return m_variableCollection; } void DebugController::partAdded(KParts::Part* part) { if (KTextEditor::Document* doc = dynamic_cast(part)) { KTextEditor::MarkInterface *iface = dynamic_cast(doc); if( !iface ) return; iface->setMarkPixmap(KTextEditor::MarkInterface::Execution, *executionPointPixmap()); } } IDebugSession* DebugController::currentSession() { return m_currentSession.data(); } void DebugController::setupActions() { KActionCollection* ac = actionCollection(); QAction* action = m_continueDebugger = new QAction(QIcon::fromTheme("media-playback-start"), i18n("&Continue"), this); action->setToolTip( i18n("Continue application execution") ); action->setWhatsThis( i18n("Continues the execution of your application in the " "debugger. This only takes effect when the application " "has been halted by the debugger (i.e. a breakpoint has " "been activated or the interrupt was pressed).") ); ac->addAction("debug_continue", action); connect(action, &QAction::triggered, this, &DebugController::run); #if 0 m_restartDebugger = action = new QAction(QIcon::fromTheme("media-seek-backward"), i18n("&Restart"), this); action->setToolTip( i18n("Restart program") ); action->setWhatsThis( i18n("Restarts applications from the beginning.") ); action->setEnabled(false); connect(action, SIGNAL(triggered(bool)), this, SLOT(restartDebugger())); ac->addAction("debug_restart", action); #endif m_interruptDebugger = action = new QAction(QIcon::fromTheme("media-playback-pause"), i18n("Interrupt"), this); action->setToolTip( i18n("Interrupt application") ); action->setWhatsThis(i18n("Interrupts the debugged process or current debugger command.")); connect(action, &QAction::triggered, this, &DebugController::interruptDebugger); ac->addAction("debug_pause", action); m_runToCursor = action = new QAction(QIcon::fromTheme("debug-run-cursor"), i18n("Run to &Cursor"), this); action->setToolTip( i18n("Run to cursor") ); action->setWhatsThis(i18n("Continues execution until the cursor position is reached.")); connect(action, &QAction::triggered, this, &DebugController::runToCursor); ac->addAction("debug_runtocursor", action); m_jumpToCursor = action = new QAction(QIcon::fromTheme("debug-execute-to-cursor"), i18n("Set E&xecution Position to Cursor"), this); action->setToolTip( i18n("Jump to cursor") ); action->setWhatsThis(i18n("Continue execution from the current cursor position.")); connect(action, &QAction::triggered, this, &DebugController::jumpToCursor); ac->addAction("debug_jumptocursor", action); m_stepOver = action = new QAction(QIcon::fromTheme("debug-step-over"), i18n("Step &Over"), this); ac->setDefaultShortcut( action, Qt::Key_F10); action->setToolTip( i18n("Step over the next line") ); action->setWhatsThis( i18n("Executes one line of source in the current source file. " "If the source line is a call to a function the whole " "function is executed and the app will stop at the line " "following the function call.") ); connect(action, &QAction::triggered, this, &DebugController::stepOver); ac->addAction("debug_stepover", action); m_stepOverInstruction = action = new QAction(QIcon::fromTheme("debug-step-instruction"), i18n("Step over Ins&truction"), this); action->setToolTip( i18n("Step over instruction") ); action->setWhatsThis(i18n("Steps over the next assembly instruction.")); connect(action, &QAction::triggered, this, &DebugController::stepOverInstruction); ac->addAction("debug_stepoverinst", action); m_stepInto = action = new QAction(QIcon::fromTheme("debug-step-into"), i18n("Step &Into"), this); ac->setDefaultShortcut( action, Qt::Key_F11); action->setToolTip( i18n("Step into the next statement") ); action->setWhatsThis( i18n("Executes exactly one line of source. If the source line " "is a call to a function then execution will stop after " "the function has been entered.") ); connect(action, &QAction::triggered, this, &DebugController::stepInto); ac->addAction("debug_stepinto", action); m_stepIntoInstruction = action = new QAction(QIcon::fromTheme("debug-step-into-instruction"), i18n("Step into I&nstruction"), this); action->setToolTip( i18n("Step into instruction") ); action->setWhatsThis(i18n("Steps into the next assembly instruction.")); connect(action, &QAction::triggered, this, &DebugController::stepIntoInstruction); ac->addAction("debug_stepintoinst", action); m_stepOut = action = new QAction(QIcon::fromTheme("debug-step-out"), i18n("Step O&ut"), this); ac->setDefaultShortcut( action, Qt::Key_F12); action->setToolTip( i18n("Step out of the current function") ); action->setWhatsThis( i18n("Executes the application until the currently executing " "function is completed. The debugger will then display " "the line after the original call to that function. If " "program execution is in the outermost frame (i.e. in " "main()) then this operation has no effect.") ); connect(action, &QAction::triggered, this, &DebugController::stepOut); ac->addAction("debug_stepout", action); m_toggleBreakpoint = action = new QAction(QIcon::fromTheme("script-error"), i18n("Toggle Breakpoint"), this); ac->setDefaultShortcut( action, i18n("Ctrl+Alt+B") ); action->setToolTip(i18n("Toggle breakpoint")); action->setWhatsThis(i18n("Toggles the breakpoint at the current line in editor.")); connect(action, &QAction::triggered, this, &DebugController::toggleBreakpoint); ac->addAction("debug_toggle_breakpoint", action); } void DebugController::addSession(IDebugSession* session) { qCDebug(SHELL) << session; Q_ASSERT(session->variableController()); Q_ASSERT(session->breakpointController()); Q_ASSERT(session->frameStackModel()); //TODO support multiple sessions if (m_currentSession) { m_currentSession.data()->stopDebugger(); } m_currentSession = session; connect(session, &IDebugSession::stateChanged, this, &DebugController::debuggerStateChanged); connect(session, &IDebugSession::showStepInSource, this, &DebugController::showStepInSource); connect(session, &IDebugSession::clearExecutionPoint, this, &DebugController::clearExecutionPoint); connect(session, &IDebugSession::raiseFramestackViews, this, &DebugController::raiseFramestackViews); updateDebuggerState(session->state(), session); emit currentSessionChanged(session); if((Core::self()->setupFlags() & Core::NoUi)) return; Sublime::MainWindow* mainWindow = Core::self()->uiControllerInternal()->activeSublimeWindow(); if (mainWindow->area()->objectName() != "debug") { QString workingSet = mainWindow->area()->workingSet(); ICore::self()->uiController()->switchToArea("debug", IUiController::ThisWindow); mainWindow->area()->setWorkingSet(workingSet); connect(mainWindow, &Sublime::MainWindow::areaChanged, this, &DebugController::areaChanged); } } void DebugController::clearExecutionPoint() { qCDebug(SHELL); foreach (KDevelop::IDocument* document, KDevelop::ICore::self()->documentController()->openDocuments()) { KTextEditor::MarkInterface *iface = dynamic_cast(document->textDocument()); if (!iface) continue; QHashIterator it = iface->marks(); while (it.hasNext()) { KTextEditor::Mark* mark = it.next().value(); if( mark->type & KTextEditor::MarkInterface::Execution ) iface->removeMark( mark->line, KTextEditor::MarkInterface::Execution ); } } } void DebugController::showStepInSource(const QUrl &url, int lineNum) { if((Core::self()->setupFlags() & Core::NoUi)) return; clearExecutionPoint(); qCDebug(SHELL) << url << lineNum; Q_ASSERT(dynamic_cast(sender())); QPair openUrl = static_cast(sender())->convertToLocalUrl(qMakePair( url, lineNum )); KDevelop::IDocument* document = KDevelop::ICore::self() ->documentController() ->openDocument(openUrl.first, KTextEditor::Cursor(openUrl.second, 0), IDocumentController::DoNotFocus); if( !document ) return; KTextEditor::MarkInterface *iface = dynamic_cast(document->textDocument()); if( !iface ) return; document->textDocument()->blockSignals(true); iface->addMark( lineNum, KTextEditor::MarkInterface::Execution ); document->textDocument()->blockSignals(false); } void DebugController::debuggerStateChanged(KDevelop::IDebugSession::DebuggerState state) { Q_ASSERT(dynamic_cast(sender())); IDebugSession* session = static_cast(sender()); qCDebug(SHELL) << session << state << "current" << m_currentSession.data(); if (session == m_currentSession.data()) { updateDebuggerState(state, session); } if (state == IDebugSession::EndedState) { if (session == m_currentSession.data()) { m_currentSession.clear(); emit currentSessionChanged(0); if (!Core::self()->shuttingDown()) { Sublime::MainWindow* mainWindow = Core::self()->uiControllerInternal()->activeSublimeWindow(); if (mainWindow && mainWindow->area()->objectName() != "code") { QString workingSet = mainWindow->area()->workingSet(); ICore::self()->uiController()->switchToArea("code", IUiController::ThisWindow); mainWindow->area()->setWorkingSet(workingSet); } ICore::self()->uiController()->findToolView(i18n("Debug"), 0, IUiController::Raise); } } session->deleteLater(); } } void DebugController::updateDebuggerState(IDebugSession::DebuggerState state, IDebugSession *session) { Q_UNUSED(session); if((Core::self()->setupFlags() & Core::NoUi)) return; qCDebug(SHELL) << state; switch (state) { case IDebugSession::StoppedState: case IDebugSession::NotStartedState: case IDebugSession::StoppingState: qCDebug(SHELL) << "new state: stopped"; stateChanged("stopped"); //m_restartDebugger->setEnabled(session->restartAvailable()); break; case IDebugSession::StartingState: case IDebugSession::PausedState: qCDebug(SHELL) << "new state: paused"; stateChanged("paused"); //m_restartDebugger->setEnabled(session->restartAvailable()); break; case IDebugSession::ActiveState: qCDebug(SHELL) << "new state: active"; stateChanged("active"); //m_restartDebugger->setEnabled(false); break; case IDebugSession::EndedState: qCDebug(SHELL) << "new state: ended"; stateChanged("ended"); //m_restartDebugger->setEnabled(false); break; } if (state == IDebugSession::PausedState && ICore::self()->uiController()->activeMainWindow()) { ICore::self()->uiController()->activeMainWindow()->activateWindow(); } } ContextMenuExtension DebugController::contextMenuExtension( Context* context ) { ContextMenuExtension menuExt; if( context->type() != Context::EditorContext ) return menuExt; KDevelop::EditorContext *econtext = dynamic_cast(context); if (!econtext) return menuExt; if (m_currentSession && m_currentSession.data()->isRunning()) { menuExt.addAction( KDevelop::ContextMenuExtension::DebugGroup, m_runToCursor); } if (econtext->url().isLocalFile()) { menuExt.addAction( KDevelop::ContextMenuExtension::DebugGroup, m_toggleBreakpoint); } return menuExt; } #if 0 void DebugController::restartDebugger() { if (m_currentSession) { m_currentSession.data()->restartDebugger(); } } #endif void DebugController::stopDebugger() { if (m_currentSession) { m_currentSession.data()->stopDebugger(); } } void DebugController::interruptDebugger() { if (m_currentSession) { m_currentSession.data()->interruptDebugger(); } } void DebugController::run() { if (m_currentSession) { m_currentSession.data()->run(); } } void DebugController::runToCursor() { if (m_currentSession) { m_currentSession.data()->runToCursor(); } } void DebugController::jumpToCursor() { if (m_currentSession) { m_currentSession.data()->jumpToCursor(); } } void DebugController::stepOver() { if (m_currentSession) { m_currentSession.data()->stepOver(); } } void DebugController::stepIntoInstruction() { if (m_currentSession) { m_currentSession.data()->stepIntoInstruction(); } } void DebugController::stepInto() { if (m_currentSession) { m_currentSession.data()->stepInto(); } } void DebugController::stepOverInstruction() { if (m_currentSession) { m_currentSession.data()->stepOverInstruction(); } } void DebugController::stepOut() { if (m_currentSession) { m_currentSession.data()->stepOut(); } } void DebugController::areaChanged(Sublime::Area* newArea) { if (newArea->objectName()!="debug") { stopDebugger(); } } void DebugController::toggleBreakpoint() { if (KDevelop::IDocument* document = KDevelop::ICore::self()->documentController()->activeDocument()) { KTextEditor::Cursor cursor = document->cursorPosition(); if (!cursor.isValid()) return; breakpointModel()->toggleBreakpoint(document->url(), cursor); } } const QPixmap* DebugController::executionPointPixmap() { static QPixmap pixmap=QIcon::fromTheme("go-next").pixmap(QSize(22,22), QIcon::Normal, QIcon::Off); return &pixmap; } } diff --git a/shell/debugcontroller.h b/shell/debugcontroller.h index 6314e781b5..e3f8a1726d 100644 --- a/shell/debugcontroller.h +++ b/shell/debugcontroller.h @@ -1,123 +1,123 @@ /* This file is part of KDevelop * * Copyright 1999-2001 John Birch * Copyright 2001 by Bernd Gehrmann * Copyright 2007 Hamish Rodda * Copyright 2009 Niko Sams * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef KDEVPLATFORM_DEBUGCONTROLLER_H #define KDEVPLATFORM_DEBUGCONTROLLER_H #include #include #include #include #include "../interfaces/idebugcontroller.h" #include "../debugger/interfaces/idebugsession.h" class QAction; namespace Sublime { class Area; } namespace KParts { class Part; } namespace KDevelop { class Context; class ContextMenuExtension; class DebugController : public IDebugController, public KXMLGUIClient { Q_OBJECT public: explicit DebugController(QObject *parent = 0); - ~DebugController(); + ~DebugController() override; void initialize(); void cleanup(); /// Must be called by debugger plugin that needs debugger actions and toolviews. - virtual void initializeUi() override; + void initializeUi() override; - virtual void addSession(IDebugSession* session) override; - virtual IDebugSession* currentSession() override; + void addSession(IDebugSession* session) override; + IDebugSession* currentSession() override; ContextMenuExtension contextMenuExtension( Context* context ); - virtual BreakpointModel* breakpointModel() override; - virtual VariableCollection* variableCollection() override; + BreakpointModel* breakpointModel() override; + VariableCollection* variableCollection() override; private Q_SLOTS: //void restartDebugger(); void stopDebugger(); void interruptDebugger(); void run(); void runToCursor(); void jumpToCursor(); void stepOver(); void stepIntoInstruction(); void stepInto(); void stepOverInstruction(); void stepOut(); void toggleBreakpoint(); void debuggerStateChanged(KDevelop::IDebugSession::DebuggerState state); void showStepInSource(const QUrl &file, int line); void clearExecutionPoint(); void partAdded(KParts::Part* part); void areaChanged(Sublime::Area* newArea); Q_SIGNALS: void raiseFramestackViews(); private: void setupActions(); void updateDebuggerState(KDevelop::IDebugSession::DebuggerState state, KDevelop::IDebugSession* session); static const QPixmap* executionPointPixmap(); QAction* m_continueDebugger; //QAction* m_restartDebugger; QAction* m_stopDebugger; QAction* m_interruptDebugger; QAction* m_runToCursor; QAction* m_jumpToCursor; QAction* m_stepOver; QAction* m_stepIntoInstruction; QAction* m_stepInto; QAction* m_stepOverInstruction; QAction* m_stepOut; QAction* m_toggleBreakpoint; QPointer m_currentSession; BreakpointModel *m_breakpointModel; VariableCollection *m_variableCollection; bool m_uiInitialized; }; } #endif diff --git a/shell/documentationcontroller.cpp b/shell/documentationcontroller.cpp index 032900c4f1..c517fa736e 100644 --- a/shell/documentationcontroller.cpp +++ b/shell/documentationcontroller.cpp @@ -1,234 +1,234 @@ /* Copyright 2009 Aleix Pol Gonzalez Copyright 2010 Benjamin Port 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 "documentationcontroller.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 using namespace KDevelop; namespace { /** * Return a "more useful" declaration that documentation providers can look-up * * @code * QPoint point; * ^-- cursor here * @endcode * * In this case, this method returns a Declaration pointer to the *type* * instead of a pointer to the instance, which is more useful when looking for help * * @return A more appropriate Declaration pointer or the given parameter @p decl */ Declaration* usefulDeclaration(Declaration* decl) { if (!decl) return nullptr; // First: Attempt to find the declaration of a definition decl = DUChainUtils::declarationForDefinition(decl); // Convenience feature: Retrieve the type declaration of instances, // it makes no sense to pass the declaration pointer of instances of types if (decl->kind() == Declaration::Instance) { AbstractType::Ptr type = TypeUtils::targetTypeKeepAliases(decl->abstractType(), decl->topContext()); IdentifiedType* idType = dynamic_cast(type.data()); Declaration* idDecl = idType ? idType->declaration(decl->topContext()) : 0; if (idDecl) { decl = idDecl; } } return decl; } } class DocumentationViewFactory: public KDevelop::IToolViewFactory { public: DocumentationViewFactory() : mProvidersModel(0) {} - virtual QWidget* create( QWidget *parent = 0 ) override + QWidget* create( QWidget *parent = 0 ) override { return new DocumentationView( parent, providers() ); } - virtual Qt::DockWidgetArea defaultPosition() override { return Qt::RightDockWidgetArea; } - virtual QString id() const override { return "org.kdevelop.DocumentationView"; } + Qt::DockWidgetArea defaultPosition() override { return Qt::RightDockWidgetArea; } + QString id() const override { return "org.kdevelop.DocumentationView"; } private: ProvidersModel* providers() { if(!mProvidersModel) mProvidersModel = new ProvidersModel; return mProvidersModel; } ProvidersModel* mProvidersModel; }; DocumentationController::DocumentationController(Core* core) : m_factory(new DocumentationViewFactory) { m_showDocumentation = core->uiController()->activeMainWindow()->actionCollection()->addAction("showDocumentation"); m_showDocumentation->setText(i18n("Show Documentation")); m_showDocumentation->setIcon(QIcon::fromTheme("documentation")); connect(m_showDocumentation, &QAction::triggered, this, &DocumentationController::doShowDocumentation); } void DocumentationController::initialize() { if(!documentationProviders().isEmpty() && !(Core::self()->setupFlags() & Core::NoUi)) { Core::self()->uiController()->addToolView( i18n("Documentation"), m_factory ); } } void KDevelop::DocumentationController::doShowDocumentation() { KTextEditor::View* view = ICore::self()->documentController()->activeTextDocumentView(); if(!view) return; KDevelop::DUChainReadLocker lock( DUChain::lock() ); Declaration* decl = usefulDeclaration(DUChainUtils::itemUnderCursor(view->document()->url(), KTextEditor::Cursor(view->cursorPosition()))); auto documentation = documentationForDeclaration(decl); if (documentation) { showDocumentation(documentation); } } KDevelop::ContextMenuExtension KDevelop::DocumentationController::contextMenuExtension ( Context* context ) { ContextMenuExtension menuExt; DeclarationContext* ctx = dynamic_cast(context); if(ctx) { DUChainReadLocker lock(DUChain::lock()); if(!ctx->declaration().data()) return menuExt; auto doc = documentationForDeclaration(ctx->declaration().data()); if (doc) { menuExt.addAction(ContextMenuExtension::ExtensionGroup, m_showDocumentation);; } } return menuExt; } IDocumentation::Ptr DocumentationController::documentationForDeclaration(Declaration* decl) { if (!decl) return {}; foreach (IDocumentationProvider* doc, documentationProviders()) { qCDebug(SHELL) << "Documentation provider found:" << doc; auto ret = doc->documentationForDeclaration(decl); qCDebug(SHELL) << "Documentation proposed: " << ret.data(); if (ret) { return ret; } } return {}; } QList< IDocumentationProvider* > DocumentationController::documentationProviders() const { QList plugins=ICore::self()->pluginController()->allPluginsForExtension("org.kdevelop.IDocumentationProvider"); QList pluginsProvider=ICore::self()->pluginController()->allPluginsForExtension("org.kdevelop.IDocumentationProviderProvider"); QList ret; foreach(IPlugin* p, pluginsProvider) { IDocumentationProviderProvider *docProvider=p->extension(); if (!docProvider) { qWarning() << "plugin" << p << "does not implement ProviderProvider extension, rerun kbuildsycoca5"; continue; } ret.append(docProvider->providers()); } foreach(IPlugin* p, plugins) { IDocumentationProvider *doc=p->extension(); if (!doc) { qWarning() << "plugin" << p << "does not implement Provider extension, rerun kbuildsycoca5"; continue; } ret.append(doc); } return ret; } void KDevelop::DocumentationController::showDocumentation(const IDocumentation::Ptr& doc) { QWidget* w = ICore::self()->uiController()->findToolView(i18n("Documentation"), m_factory, KDevelop::IUiController::CreateAndRaise); if(!w) { qWarning() << "Could not add documentation toolview"; return; } DocumentationView* view = dynamic_cast(w); if( !view ) { qWarning() << "Could not cast toolview" << w << "to DocumentationView class!"; return; } view->showDocumentation(doc); } void DocumentationController::changedDocumentationProviders() { emit providersChanged(); } diff --git a/shell/documentationcontroller.h b/shell/documentationcontroller.h index 3c23556881..815777074a 100644 --- a/shell/documentationcontroller.h +++ b/shell/documentationcontroller.h @@ -1,62 +1,62 @@ /* Copyright 2009 Aleix Pol Gonzalez Copyright 2010 Benjamin Port 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. */ #ifndef KDEVPLATFORM_DOCUMENTATIONCONTROLLER_H #define KDEVPLATFORM_DOCUMENTATIONCONTROLLER_H #include class DocumentationViewFactory; class QAction; namespace KDevelop { class Core; class Context; class ContextMenuExtension; class DocumentationController : public IDocumentationController { Q_OBJECT public: explicit DocumentationController(Core* core); void initialize(); - virtual QList documentationProviders() const override; - virtual IDocumentation::Ptr documentationForDeclaration(Declaration* declaration) override; - virtual void showDocumentation(const IDocumentation::Ptr& doc) override; + QList documentationProviders() const override; + IDocumentation::Ptr documentationForDeclaration(Declaration* declaration) override; + void showDocumentation(const IDocumentation::Ptr& doc) override; ContextMenuExtension contextMenuExtension( Context* context ); public slots: - virtual void changedDocumentationProviders() override; + void changedDocumentationProviders() override; private slots: void doShowDocumentation(); private: DocumentationViewFactory* m_factory; QAction* m_showDocumentation; }; } #endif // KDEVPLATFORM_DOCUMENTATIONCONTROLLER_H diff --git a/shell/documentcontroller.h b/shell/documentcontroller.h index 2f4ad301e1..3e49f7933c 100644 --- a/shell/documentcontroller.h +++ b/shell/documentcontroller.h @@ -1,183 +1,183 @@ /* This document is part of the KDE project Copyright 2002 Matthias Hoelzer-Kluepfel Copyright 2002 Bernd Gehrmann Copyright 2003 Roberto Raggi Copyright 2003 Hamish Rodda Copyright 2003 Harald Fernengel Copyright 2003 Jens Dagerbo Copyright 2005 Adam Treat Copyright 2004-2007 Alexander Dymo Copyright 2007 Andreas Pakulat 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 document COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_DOCUMENTCONTROLLER_H #define KDEVPLATFORM_DOCUMENTCONTROLLER_H #include #include #include "shellexport.h" namespace KTextEditor { class View; } namespace Sublime { class Document; class Area; class AreaIndex; } namespace KDevelop { class ProjectFileItem; class IProject; class MainWindow; /** * \short Interface to control open documents. * The document controller manages open documents in the IDE. * Open documents are usually editors, GUI designers, html documentation etc. * * Please note that this interface gives access to documents and not to their views. * It is possible that more than 1 view is shown in KDevelop for a document. */ class KDEVPLATFORMSHELL_EXPORT DocumentController: public IDocumentController { Q_OBJECT Q_CLASSINFO( "D-Bus Interface", "org.kdevelop.DocumentController" ) public: /**Constructor. @param parent The parent object.*/ explicit DocumentController( QObject *parent = 0 ); - virtual ~DocumentController(); + ~DocumentController() override; /**Finds the first document object corresponding to a given url. @param url The Url of the document. @return The corresponding document, or null if not found.*/ - virtual IDocument* documentForUrl( const QUrl & url ) const override; + IDocument* documentForUrl( const QUrl & url ) const override; /**@return The list of open documents*/ - virtual QList openDocuments() const override; + QList openDocuments() const override; /**Refers to the document currently active or focused. @return The active document.*/ - virtual IDocument* activeDocument() const override; + IDocument* activeDocument() const override; - virtual KTextEditor::View* activeTextDocumentView() const override; + KTextEditor::View* activeTextDocumentView() const override; - virtual void activateDocument( IDocument * document, const KTextEditor::Range& range = KTextEditor::Range::invalid() ) override; + void activateDocument( IDocument * document, const KTextEditor::Range& range = KTextEditor::Range::invalid() ) override; - virtual void registerDocumentForMimetype( const QString&, KDevelop::IDocumentFactory* ) override; + void registerDocumentForMimetype( const QString&, KDevelop::IDocumentFactory* ) override; /// Request the document controller to save all documents. /// If the \a mode is not IDocument::Silent, ask the user which documents to save. /// Returns false if the user cancels the save dialog. - virtual bool saveAllDocuments(IDocument::DocumentSaveMode mode) override; + bool saveAllDocuments(IDocument::DocumentSaveMode mode) override; bool saveAllDocumentsForWindow(KParts::MainWindow* mw, IDocument::DocumentSaveMode mode, bool currentAreaOnly = false) override; void initialize(); void cleanup(); virtual QStringList documentTypes() const; QString documentType(Sublime::Document* document) const; using IDocumentController::openDocument; /**checks that url is an url of empty document*/ static bool isEmptyDocumentUrl(const QUrl &url); static QUrl nextEmptyDocumentUrl(); - virtual IDocumentFactory* factory(const QString& mime) const override; + IDocumentFactory* factory(const QString& mime) const override; - virtual bool openDocument(IDocument* doc, + bool openDocument(IDocument* doc, const KTextEditor::Range& range = KTextEditor::Range::invalid(), DocumentActivationParams activationParams = 0, IDocument* buddy = 0) override; - virtual KTextEditor::Document* globalTextEditorInstance() override; + KTextEditor::Document* globalTextEditorInstance() override; public Q_SLOTS: /**Opens a new or existing document. @param url The full Url of the document to open. If it is empty, a dialog to choose the document will be opened. @param range The location information, if applicable. @param activationParams Indicates whether to fully activate the document. @param buddy The buddy document @return The opened document */ - virtual Q_SCRIPTABLE IDocument* openDocument( const QUrl &url, + Q_SCRIPTABLE IDocument* openDocument( const QUrl &url, const KTextEditor::Range& range = KTextEditor::Range::invalid(), DocumentActivationParams activationParams = 0, const QString& encoding = {}, IDocument* buddy = 0 ) override; - virtual Q_SCRIPTABLE IDocument* openDocumentFromText( const QString& data ) override; + Q_SCRIPTABLE IDocument* openDocumentFromText( const QString& data ) override; - virtual KDevelop::IDocument* openDocument( const QUrl &url, const QString& prefname ) override; + KDevelop::IDocument* openDocument( const QUrl &url, const QString& prefname ) override; virtual void closeDocument( const QUrl &url ); void fileClose(); void slotSaveAllDocuments(); - virtual bool closeAllDocuments() override; + bool closeAllDocuments() override; void closeAllOtherDocuments(); void reloadAllDocuments(); // DBUS-compatible versions of openDocument virtual Q_SCRIPTABLE bool openDocumentSimple( QString url, int line = -1, int column = 0 ); // Opens a list of documents, with optional split-view separators, like: "file1 / [ file2 - fil3 ]" (see kdevplatform_shell_environment.sh) virtual Q_SCRIPTABLE bool openDocumentsSimple( QStringList urls ); virtual Q_SCRIPTABLE bool openDocumentFromTextSimple( QString text ); // If 'target' is empty, returns the currently active document, or // the currently selected project-item if no document is active. // If 'target' is "[selection]", returns the path of the currently active selection. // If 'target' is the name of a project, returns the root-path of that project. // Whenever the returned path corresponds to a directory, a '/.' suffix is appended. Q_SCRIPTABLE QString activeDocumentPath(QString target = {}) const; // Returns all open documents in the current area Q_SCRIPTABLE QStringList activeDocumentPaths() const; void vcsAnnotateCurrentDocument(); private Q_SLOTS: virtual void slotOpenDocument(const QUrl &url); void notifyDocumentClosed(Sublime::Document* doc); private: bool openDocumentsWithSplitSeparators( Sublime::AreaIndex* index, QStringList urlsWithSeparators, bool& isFirstView ); QList visibleDocumentsInWindow(MainWindow* mw) const; QList documentsExclusivelyInWindow(MainWindow* mw, bool currentAreaOnly = false) const; QList modifiedDocuments(const QList& list) const; bool saveSomeDocuments(const QList& list, IDocument::DocumentSaveMode mode) override; void setupActions(); Q_PRIVATE_SLOT(d, void removeDocument(Sublime::Document*)) Q_PRIVATE_SLOT(d, void chooseDocument()) Q_PRIVATE_SLOT(d, void changeDocumentUrl(KDevelop::IDocument*)) friend struct DocumentControllerPrivate; struct DocumentControllerPrivate *d; }; } #endif diff --git a/shell/editorconfigpage.cpp b/shell/editorconfigpage.cpp index 337348fbd0..34f4c1cbb7 100644 --- a/shell/editorconfigpage.cpp +++ b/shell/editorconfigpage.cpp @@ -1,127 +1,127 @@ /* * This file is part of KDevelop * Copyright 2014 Alex Richardson * * 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 "editorconfigpage.h" #include #include #include #include using namespace KDevelop; namespace { class KTextEditorConfigPageAdapter : public ConfigPage { Q_OBJECT public: explicit KTextEditorConfigPageAdapter(KTextEditor::ConfigPage* page, QWidget* parent = nullptr) : ConfigPage(nullptr, nullptr, parent), m_page(page) { page->setParent(this); QVBoxLayout* layout = new QVBoxLayout(this); layout->addWidget(page); setLayout(layout); connect(page, &KTextEditor::ConfigPage::changed, this, &ConfigPage::changed); } - virtual ~KTextEditorConfigPageAdapter() {} + ~KTextEditorConfigPageAdapter() override {} - virtual QString name() const override + QString name() const override { return m_page->name(); } - virtual QIcon icon() const override + QIcon icon() const override { return m_page->icon(); } - virtual QString fullName() const override + QString fullName() const override { return m_page->fullName(); } public Q_SLOTS: - virtual void apply() override + void apply() override { m_page->apply(); } - virtual void defaults() override + void defaults() override { m_page->defaults(); } - virtual void reset() override + void reset() override { m_page->reset(); } private: KTextEditor::ConfigPage* m_page; }; } EditorConfigPage::EditorConfigPage(QWidget* parent) : ConfigPage(nullptr, nullptr, parent) { setObjectName("editorconfig"); } EditorConfigPage::~EditorConfigPage() {}; QString EditorConfigPage::name() const { return i18n("Editor"); } QIcon EditorConfigPage::icon() const { return QIcon::fromTheme(QStringLiteral("accessories-text-editor")); } QString EditorConfigPage::fullName() const { return i18n("Configure Text editor"); } int EditorConfigPage::childPages() const { return KTextEditor::Editor::instance()->configPages(); } ConfigPage* EditorConfigPage::childPage(int number) { auto page = KTextEditor::Editor::instance()->configPage(number, this); if (page) { return new KTextEditorConfigPageAdapter(page, this); } return nullptr; } #include "editorconfigpage.moc" diff --git a/shell/editorconfigpage.h b/shell/editorconfigpage.h index 6e103377d2..719023ff85 100644 --- a/shell/editorconfigpage.h +++ b/shell/editorconfigpage.h @@ -1,53 +1,53 @@ /* * This file is part of KDevelop * Copyright 2014 Alex Richardson * * 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 KDEVPLATFORM_EDITORCONFIGPAGE_H #define KDEVPLATFORM_EDITORCONFIGPAGE_H #include namespace KDevelop { /** * This class makes all the KTextEditor config pages available for use * as a single KDevelop::ConfigPage */ class EditorConfigPage : public ConfigPage { Q_OBJECT public: explicit EditorConfigPage(QWidget* parent); - virtual ~EditorConfigPage(); + ~EditorConfigPage() override; - virtual QString name() const override; - virtual QIcon icon() const override; - virtual QString fullName() const override; - virtual int childPages() const override; - virtual ConfigPage* childPage(int number) override; + QString name() const override; + QIcon icon() const override; + QString fullName() const override; + int childPages() const override; + ConfigPage* childPage(int number) override; public Q_SLOTS: // nothing to edit on this page, only subpages have actual configuration - virtual void apply() override {}; - virtual void reset() override {}; - virtual void defaults() override {}; + void apply() override {}; + void reset() override {}; + void defaults() override {}; }; } #endif // KDEVPLATFORM_EDITORCONFIGPAGE_H diff --git a/shell/environmentconfigurebutton.h b/shell/environmentconfigurebutton.h index ff063fcee7..c0b54c8c74 100644 --- a/shell/environmentconfigurebutton.h +++ b/shell/environmentconfigurebutton.h @@ -1,61 +1,61 @@ /* This file is part of KDevelop Copyright 2010 Milian Wolff 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 KDEVPLATFORM_ENVIRONMENTCONFIGUREBUTTON_H #define KDEVPLATFORM_ENVIRONMENTCONFIGUREBUTTON_H #include "shellexport.h" #include namespace KDevelop { class EnvironmentSelectionWidget; /** * A tool button that shows a dialog to configure the environment settings. * You want to place that next to an @c EnvironmentSelectionWidget and pass * that one along. This button will automatically update the selection widget * if required then. */ class KDEVPLATFORMSHELL_EXPORT EnvironmentConfigureButton : public QPushButton { Q_OBJECT public: explicit EnvironmentConfigureButton(QWidget* parent = 0); - ~EnvironmentConfigureButton(); + ~EnvironmentConfigureButton() override; void setSelectionWidget(EnvironmentSelectionWidget* widget); signals: /** * Gets emitted whenever the dialog was acceppted * and the env settings might have changed. */ void environmentConfigured(); private: class EnvironmentConfigureButtonPrivate* const d; friend class EnvironmentConfigureButtonPrivate; }; } #endif // KDEVPLATFORM_ENVIRONMENTCONFIGUREBUTTON_H diff --git a/shell/filteredproblemstore.h b/shell/filteredproblemstore.h index 2ef5414562..b6faa38fe9 100644 --- a/shell/filteredproblemstore.h +++ b/shell/filteredproblemstore.h @@ -1,118 +1,118 @@ /* * Copyright 2015 Laszlo Kis-Adam * * 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. */ #ifndef FILTEREDPROBLEMSTORE_H #define FILTEREDPROBLEMSTORE_H #include "problemstore.h" #include "problemconstants.h" namespace KDevelop { struct FilteredProblemStorePrivate; /** * @brief ProblemStore subclass that can group by severity, and path, and filter by scope, and severity. * * Internally grouping is implemented using a tree structure. * When grouping is on, the top level nodes are the groups, and their children are the nodes containing the problems that belong into that node. * If the problems have diagnostics, then the diagnostics are added as children nodes as well. This was implemented so they can be browsed in a model/view architecture. * When grouping is off, the top level nodes are the problem nodes. * * Grouping can be set and queried using the following methods * \li setGrouping(); * \li grouping(); * * Valid grouping settings: * \li NoGrouping * \li PathGrouping * \li SeverityGrouping * * Severity filter can be set and queried using the following methods * \li setSeverity() * \li severity() * * Valid severity setting: * \li IProblem::Error * \li IProblem::Warning * \li IProblem::Hint * * When changing the grouping or filtering method the following signals are emitted in order: * \li beginRebuild() * \li endRebuild() * \li changed() * * Usage example: * @code * IProblem::Ptr problem(new DetectedProblem); * problem->setSeverity(IProblem::Error); * ... * FilteredProblemStore *store = new FilteredProblemStore(); * store->setGrouping(SeverityGrouping); * store->addProblem(problem); * ProblemStoreNode *label = store->findNode(0); // Label node with the label "Error" * ProblemNode *problemNode = dynamic_cast(label->child(0)); // the node with the problem * problemNode->problem(); // The problem we added * @endcode * */ class KDEVPLATFORMSHELL_EXPORT FilteredProblemStore : public ProblemStore { Q_OBJECT public: explicit FilteredProblemStore(QObject *parent = nullptr); - ~FilteredProblemStore(); + ~FilteredProblemStore() override; /// Adds a problem, which is then filtered and also added to the filtered problem list if it matches the filters void addProblem(const IProblem::Ptr &problem) override; /// Retrieves the specified node const ProblemStoreNode* findNode(int row, ProblemStoreNode *parent = nullptr) const override; /// Retrieves the number of filtered problems int count(ProblemStoreNode *parent = nullptr) const override; /// Clears the problems void clear() override; /// Rebuilds the filtered problem list void rebuild() override; /// Set the grouping method. See the GroupingMethod enum. void setGrouping(int grouping) override; /// Tells which grouping strategy is currently in use int grouping() const; /// Sets whether we should bypass the scope filter void setBypassScopeFilter(bool bypass) override; /// Tells whether the scope filter bypass is on bool bypassScopeFilter() const; private: friend struct FilteredProblemStorePrivate; QScopedPointer d; }; } #endif diff --git a/shell/ktexteditorpluginintegration.cpp b/shell/ktexteditorpluginintegration.cpp index 9dc9588760..272df408a4 100644 --- a/shell/ktexteditorpluginintegration.cpp +++ b/shell/ktexteditorpluginintegration.cpp @@ -1,334 +1,334 @@ /* Copyright 2015 Milian Wolff 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 "ktexteditorpluginintegration.h" #include #include #include #include #include #include #include #include #include "core.h" #include "uicontroller.h" #include "documentcontroller.h" #include "plugincontroller.h" #include "mainwindow.h" #include "textdocument.h" #include using namespace KDevelop; namespace { KTextEditor::MainWindow *toKteWrapper(KParts::MainWindow *window) { if (auto mainWindow = dynamic_cast(window)) { return mainWindow->kateWrapper() ? mainWindow->kateWrapper()->interface() : nullptr; } else { return nullptr; } } KTextEditor::View *toKteView(Sublime::View *view) { if (auto textView = dynamic_cast(view)) { return textView->textView(); } else { return nullptr; } } class ToolViewFactory; /** * This HACK is required to massage the KTextEditor plugin API into the * GUI concepts we apply in KDevelop. Kate does not allow the user to * delete toolviews and then readd them. We do. To support our use case * we prevent the widget we return to KTextEditor plugins from * MainWindow::createToolView from getting destroyed. This widget class * unsets the parent of the so called container in its dtor. The * ToolViewFactory handles the ownership and destroys the kate widget * as needed. */ class KeepAliveWidget : public QWidget { Q_OBJECT public: explicit KeepAliveWidget(ToolViewFactory *factory, QWidget *parent = nullptr) : QWidget(parent) , m_factory(factory) { } - ~KeepAliveWidget(); + ~KeepAliveWidget() override; private: ToolViewFactory *m_factory; }; class ToolViewFactory : public QObject, public KDevelop::IToolViewFactory { Q_OBJECT public: ToolViewFactory(const QString &text, const QIcon &icon, const QString &identifier, KTextEditor::MainWindow::ToolViewPosition pos) : m_text(text) , m_icon(icon) , m_identifier(identifier) , m_container(new QWidget) , m_pos(pos) { m_container->setLayout(new QVBoxLayout); } - ~ToolViewFactory() + ~ToolViewFactory() override { delete m_container; } QWidget *create(QWidget *parent = nullptr) override { auto widget = new KeepAliveWidget(this, parent); widget->setWindowTitle(m_text); widget->setWindowIcon(m_icon); widget->setLayout(new QVBoxLayout); widget->layout()->addWidget(m_container); widget->addActions(m_container->actions()); return widget; } - virtual Qt::DockWidgetArea defaultPosition() override + Qt::DockWidgetArea defaultPosition() override { switch (m_pos) { case KTextEditor::MainWindow::Left: return Qt::LeftDockWidgetArea; case KTextEditor::MainWindow::Right: return Qt::RightDockWidgetArea; case KTextEditor::MainWindow::Top: return Qt::TopDockWidgetArea; case KTextEditor::MainWindow::Bottom: return Qt::BottomDockWidgetArea; } Q_UNREACHABLE(); } QString id() const override { return m_identifier; } QWidget *container() const { return m_container; } private: QString m_text; QIcon m_icon; QString m_identifier; QPointer m_container; KTextEditor::MainWindow::ToolViewPosition m_pos; friend class KeepAliveWidget; }; KeepAliveWidget::~KeepAliveWidget() { // if the container is still valid, unparent it to prevent it from getting deleted // this happens when the user removes a toolview // on shutdown, the container does get deleted, thus we must guard against that. if (m_factory->container()) { Q_ASSERT(m_factory->container()->parentWidget() == this); m_factory->container()->setParent(nullptr); } } } namespace KTextEditorIntegration { Application::Application(QObject *parent) : QObject(parent) { } Application::~Application() { KTextEditor::Editor::instance()->setApplication(nullptr); } KTextEditor::MainWindow *Application::activeMainWindow() const { return toKteWrapper(Core::self()->uiController()->activeMainWindow()); } QList Application::mainWindows() const { return {activeMainWindow()}; } KTextEditor::Plugin *Application::plugin(const QString &id) const { auto kdevPlugin = Core::self()->pluginController()->loadPlugin(id); const auto plugin = dynamic_cast(kdevPlugin); return plugin ? plugin->interface() : nullptr; } MainWindow::MainWindow(KDevelop::MainWindow *mainWindow) : QObject(mainWindow) , m_mainWindow(mainWindow) , m_interface(new KTextEditor::MainWindow(this)) { connect(mainWindow, &Sublime::MainWindow::viewAdded, this, [this] (Sublime::View *view) { if (auto kteView = toKteView(view)) { emit m_interface->viewCreated(kteView); } }); connect(mainWindow, &Sublime::MainWindow::activeViewChanged, this, [this] (Sublime::View *view) { emit m_interface->viewChanged(toKteView(view)); }); } MainWindow::~MainWindow() = default; QWidget *MainWindow::createToolView(KTextEditor::Plugin* plugin, const QString &identifier, KTextEditor::MainWindow::ToolViewPosition pos, const QIcon &icon, const QString &text) { auto factory = new ToolViewFactory(text, icon, identifier, pos); Core::self()->uiController()->addToolView(text, factory); connect(plugin, &QObject::destroyed, this, [=] { Core::self()->uiController()->removeToolView(factory); }); return factory->container(); } KXMLGUIFactory *MainWindow::guiFactory() const { return m_mainWindow->guiFactory(); } QWidget *MainWindow::window() const { return m_mainWindow; } QList MainWindow::views() const { QList views; foreach (auto area, m_mainWindow->areas()) { foreach (auto view, area->views()) { if (auto kteView = toKteView(view)) { views << kteView; } } } return views; } KTextEditor::View *MainWindow::activeView() const { return toKteView(m_mainWindow->activeView()); } QObject *MainWindow::pluginView(const QString &id) const { return m_pluginViews.value(id); } KTextEditor::MainWindow *MainWindow::interface() const { return m_interface; } void MainWindow::addPluginView(const QString &id, QObject *view) { m_pluginViews.insert(id, view); emit m_interface->pluginViewCreated(id, view); } void MainWindow::removePluginView(const QString &id) { auto view = m_pluginViews.take(id).data(); delete view; emit m_interface->pluginViewDeleted(id, view); } Plugin::Plugin(KTextEditor::Plugin *plugin, QObject *parent) : IPlugin({}, parent) , m_plugin(plugin) , m_tracker(new ObjectListTracker(ObjectListTracker::CleanupWhenDone, this)) { } Plugin::~Plugin() = default; void Plugin::unload() { if (auto mainWindow = KTextEditor::Editor::instance()->application()->activeMainWindow()) { auto integration = dynamic_cast(mainWindow->parent()); if (integration) { integration->removePluginView(pluginId()); } } m_tracker->deleteAll(); delete m_plugin; } KXMLGUIClient *Plugin::createGUIForMainWindow(Sublime::MainWindow* window) { auto ret = IPlugin::createGUIForMainWindow(window); auto mainWindow = dynamic_cast(window); Q_ASSERT(mainWindow); auto wrapper = mainWindow->kateWrapper(); auto view = m_plugin->createView(wrapper->interface()); wrapper->addPluginView(pluginId(), view); // ensure that unloading the plugin kills all views m_tracker->append(view); return ret; } KTextEditor::Plugin *Plugin::interface() const { return m_plugin.data(); } QString Plugin::pluginId() const { return Core::self()->pluginController()->pluginInfo(this).pluginId(); } void initialize() { auto app = new KTextEditor::Application(new Application(Core::self())); KTextEditor::Editor::instance()->setApplication(app); } } #include "ktexteditorpluginintegration.moc" diff --git a/shell/ktexteditorpluginintegration.h b/shell/ktexteditorpluginintegration.h index 6eaf142b3c..b62e0fb6b3 100644 --- a/shell/ktexteditorpluginintegration.h +++ b/shell/ktexteditorpluginintegration.h @@ -1,111 +1,111 @@ /* Copyright 2015 Milian Wolff 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 KDEVPLATFORM_KTEXTEDITOR_PLUGIN_INTEGRATION_H #define KDEVPLATFORM_KTEXTEDITOR_PLUGIN_INTEGRATION_H #include #include #include #include #include #include namespace KDevelop { class ObjectListTracker; class MainWindow; } namespace KTextEditorIntegration { class Application : public QObject { Q_OBJECT public: explicit Application(QObject *parent = nullptr); - ~Application(); + ~Application() override; public slots: KTextEditor::MainWindow *activeMainWindow() const; QList mainWindows() const; KTextEditor::Plugin *plugin(const QString &id) const; }; class MainWindow : public QObject { Q_OBJECT public: explicit MainWindow(KDevelop::MainWindow *mainWindow); - ~MainWindow(); + ~MainWindow() override; public slots: QWidget *createToolView(KTextEditor::Plugin *plugin, const QString &identifier, KTextEditor::MainWindow::ToolViewPosition pos, const QIcon &icon, const QString &text); KXMLGUIFactory *guiFactory() const; QWidget *window() const; QList views() const; KTextEditor::View *activeView() const; QObject *pluginView(const QString &id) const; public: KTextEditor::MainWindow *interface() const; void addPluginView(const QString &id, QObject *pluginView); void removePluginView(const QString &id); private: KDevelop::MainWindow *m_mainWindow; KTextEditor::MainWindow *m_interface; QHash> m_pluginViews; }; class Plugin : public KDevelop::IPlugin { Q_OBJECT public: explicit Plugin(KTextEditor::Plugin *plugin, QObject *parent = nullptr); - ~Plugin(); + ~Plugin() override; KXMLGUIClient* createGUIForMainWindow(Sublime::MainWindow *window) override; void unload() override; KTextEditor::Plugin *interface() const; QString pluginId() const; private: QPointer m_plugin; // view objects and toolviews that should get deleted when the plugin gets unloaded KDevelop::ObjectListTracker *m_tracker; }; void initialize(); } #endif diff --git a/shell/languagecontroller.h b/shell/languagecontroller.h index f540005139..7bc185af15 100644 --- a/shell/languagecontroller.h +++ b/shell/languagecontroller.h @@ -1,84 +1,84 @@ /*************************************************************************** * Copyright 2006 Adam Treat * * Copyright 2007 Alexander Dymo * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_LANGUAGECONTROLLER_H #define KDEVPLATFORM_LANGUAGECONTROLLER_H #include #include "shellexport.h" namespace KParts { class Part; } namespace KDevelop { class ILanguageSupport; class KDEVPLATFORMSHELL_EXPORT LanguageController : public ILanguageController { Q_OBJECT public: explicit LanguageController(QObject *parent); - virtual ~LanguageController(); + ~LanguageController() override; void initialize(); //After this was called, no more languages will be returned void cleanup(); /** @copydoc ILanguageController::activeLanguages() */ - virtual QList activeLanguages() override; + QList activeLanguages() override; /** @copydoc ILanguageController::language() */ - virtual ILanguageSupport* language(const QString &name) const override; + ILanguageSupport* language(const QString &name) const override; /** @copydoc ILanguageController::languageForUrl() */ - virtual QList languagesForUrl(const QUrl &url) override; + QList languagesForUrl(const QUrl &url) override; /** @copydoc ILanguageController::backgroundParser() */ - Q_SCRIPTABLE virtual BackgroundParser *backgroundParser() const override; + Q_SCRIPTABLE BackgroundParser *backgroundParser() const override; - virtual StaticAssistantsManager *staticAssistantsManager() const override; + StaticAssistantsManager *staticAssistantsManager() const override; - virtual QList loadedLanguages() const override; + QList loadedLanguages() const override; - virtual ICompletionSettings *completionSettings() const override; + ICompletionSettings *completionSettings() const override; - virtual ProblemModelSet* problemModelSet() const override; + ProblemModelSet* problemModelSet() const override; QList languagesForMimetype(const QString& mime); QList mimetypesForLanguageName(const QString& languageName); protected: /** * functions for unit tests * @see TestLanguageController */ void addLanguageSupport(KDevelop::ILanguageSupport* languageSupport, const QStringList& mimetypes); private: struct LanguageControllerPrivate *d; Q_PRIVATE_SLOT(d, void documentActivated(KDevelop::IDocument *document)) }; } #endif diff --git a/shell/launchconfiguration.h b/shell/launchconfiguration.h index 2669775da5..2c0d7f7cf3 100644 --- a/shell/launchconfiguration.h +++ b/shell/launchconfiguration.h @@ -1,102 +1,102 @@ /* This file is part of KDevelop Copyright 2009 Andreas Pakulat 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 KDEVPLATFORM_LAUNCHCONFIGURATION_H #define KDEVPLATFORM_LAUNCHCONFIGURATION_H #include #include #include "shellexport.h" class QString; namespace KDevelop { class LaunchConfigurationType; class IProject; /** * @copydoc KDevelop::ILaunchConfiguration */ class KDEVPLATFORMSHELL_EXPORT LaunchConfiguration : public QObject, public ILaunchConfiguration { Q_OBJECT public: explicit LaunchConfiguration( KConfigGroup, IProject* = 0, QObject* = 0 ); - virtual ~LaunchConfiguration(); + ~LaunchConfiguration() override; static QString LaunchConfigurationNameEntry(); static QString LaunchConfigurationTypeEntry(); /** * Change the name of this launch configuration * @param name the new name for the launch configuration */ void setName( const QString& name ); /** * Changes the type of this launch configuration. Note that * this removes all existing config values from this configuration * @param type the id of the new type */ void setType( const QString& typeId ); /** * @copydoc KDevelop::ILaunchConfiguration::config() */ - virtual const KConfigGroup config() const override; + const KConfigGroup config() const override; /** * @copydoc KDevelop::ILaunchConfiguration::type() */ - virtual LaunchConfigurationType* type() const override; + LaunchConfigurationType* type() const override; /** * @copydoc KDevelop::ILaunchConfiguration::name() */ - virtual QString name() const override; + QString name() const override; /** * @copydoc KDevelop::ILaunchConfiguration::project() */ - virtual IProject* project() const override; + IProject* project() const override; void save(); QString configGroupName() const; QString launcherForMode( const QString& mode ) const; void setLauncherForMode( const QString& mode, const QString& id ); KConfigGroup config() override; signals: void nameChanged( LaunchConfiguration* ); void typeChanged( LaunchConfigurationType* ); private: KConfigGroup baseGroup; IProject* m_project; LaunchConfigurationType* m_type; }; } #endif diff --git a/shell/launchconfigurationdialog.h b/shell/launchconfigurationdialog.h index 5609f98f9b..8a1ebfb071 100644 --- a/shell/launchconfigurationdialog.h +++ b/shell/launchconfigurationdialog.h @@ -1,166 +1,166 @@ /* This file is part of KDevelop Copyright 2009 Andreas Pakulat 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 KDEVPLATFORM_LAUNCHCONFIGURATIONDIALOG_H #define KDEVPLATFORM_LAUNCHCONFIGURATIONDIALOG_H #include #include #include #include #include #include "ui_launchconfigurationdialog.h" class QItemSelection; namespace Ui { class LaunchConfigTypePage; } namespace KDevelop { class ILauncher; class LaunchConfigurationPageFactory; class ILaunchMode; class LaunchConfigurationType; class LaunchConfiguration; class LaunchConfigurationPage; class ILaunchConfiguration; class IProject; class LaunchConfigurationModelDelegate : public QStyledItemDelegate { public: LaunchConfigurationModelDelegate(); - virtual QWidget* createEditor ( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const override; - virtual void setEditorData ( QWidget* editor, const QModelIndex& index ) const override; - virtual void setModelData ( QWidget* editor, QAbstractItemModel* model, const QModelIndex& index ) const override; + QWidget* createEditor ( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const override; + void setEditorData ( QWidget* editor, const QModelIndex& index ) const override; + void setModelData ( QWidget* editor, QAbstractItemModel* model, const QModelIndex& index ) const override; }; class LaunchConfigurationsModel : public QAbstractItemModel { Q_OBJECT public: explicit LaunchConfigurationsModel(QObject* parent = 0); - virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override; - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; - virtual QModelIndex parent(const QModelIndex& child) const override; - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - virtual Qt::ItemFlags flags(const QModelIndex& index) const override; - virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex& child) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; void createConfiguration( const QModelIndex& ); void deleteConfiguration( const QModelIndex& index ); LaunchConfiguration* configForIndex( const QModelIndex& ) const; ILaunchMode* modeForIndex( const QModelIndex& idx ) const; QModelIndex indexForConfig( LaunchConfiguration* ) const; void addConfiguration(KDevelop::ILaunchConfiguration* launch, const QModelIndex& idx); KDevelop::IProject* projectForIndex(const QModelIndex& idx); private: class TreeItem { public: TreeItem() : parent(0) {} virtual ~TreeItem() {} TreeItem* parent; int row; QList children; }; class ProjectItem : public TreeItem { public: IProject* project; }; class LaunchItem : public TreeItem { public: LaunchConfiguration* launch; }; class LaunchModeItem : public TreeItem { public: ILaunchMode* mode; }; class GenericPageItem : public TreeItem { public: QString text; }; void addItemForLaunchConfig( LaunchConfiguration* l ); void addLaunchModeItemsForLaunchConfig ( KDevelop::LaunchConfigurationsModel::LaunchItem* l ); QList topItems; public: ProjectItem* findItemForProject( IProject* ); }; class LaunchConfigPagesContainer : public QWidget { Q_OBJECT public: explicit LaunchConfigPagesContainer( const QList &, QWidget* parent = 0 ); void setLaunchConfiguration( LaunchConfiguration* ); void save(); signals: void changed(); private: LaunchConfiguration* config; QList pages; }; class LaunchConfigurationDialog : public QDialog, public Ui::LaunchConfigurationDialog { Q_OBJECT public: explicit LaunchConfigurationDialog(QWidget* parent = 0 ); - virtual QSize sizeHint() const override; + QSize sizeHint() const override; private slots: void deleteConfiguration(); void createConfiguration(); void addConfiguration(KDevelop::ILaunchConfiguration*); void selectionChanged(QItemSelection,QItemSelection); void modelChanged(QModelIndex,QModelIndex); void pageChanged(); void saveConfig(); void updateNameLabel( LaunchConfiguration* l ); void createEmptyLauncher(); void launchModeChanged(int index); private: void saveConfig( const QModelIndex& ); LaunchConfigurationsModel* model; QMap typeWidgets; QMap launcherWidgets; bool currentPageChanged; private slots: void doTreeContextMenu(QPoint point); void renameSelected(); }; } #endif diff --git a/shell/loadedpluginsdialog.cpp b/shell/loadedpluginsdialog.cpp index e0e070baef..4b343cd513 100644 --- a/shell/loadedpluginsdialog.cpp +++ b/shell/loadedpluginsdialog.cpp @@ -1,311 +1,311 @@ /************************************************************************** * Copyright 2009 Andreas Pakulat * * Copyright 2010 Niko Sams * * * * 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 Library 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 "loadedpluginsdialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "core.h" #include "plugincontroller.h" #define MARGIN 5 namespace { KPluginMetaData pluginInfo(KDevelop::IPlugin* plugin) { return KDevelop::Core::self()->pluginControllerInternal()->pluginInfo(plugin); }; QString displayName(KDevelop::IPlugin* plugin) { const auto name = pluginInfo(plugin).name(); return !name.isEmpty() ? name : plugin->componentName(); } bool sortPlugins(KDevelop::IPlugin* l, KDevelop::IPlugin* r) { return displayName(l) < displayName(r); } } class PluginsModel : public QAbstractListModel { public: enum ExtraRoles { DescriptionRole = Qt::UserRole+1 }; PluginsModel(QObject* parent = 0) : QAbstractListModel(parent) { m_plugins = KDevelop::Core::self()->pluginControllerInternal()->loadedPlugins(); std::sort(m_plugins.begin(), m_plugins.end(), sortPlugins); } KDevelop::IPlugin *pluginForIndex(const QModelIndex& index) const { if (!index.isValid()) return 0; if (index.parent().isValid()) return 0; if (index.column() != 0) return 0; if (index.row() >= m_plugins.count()) return 0; return m_plugins[index.row()]; } - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override { KDevelop::IPlugin* plugin = pluginForIndex(index); if (!plugin) return QVariant(); switch (role) { case Qt::DisplayRole: return displayName(plugin); case DescriptionRole: return pluginInfo(plugin).description(); case Qt::DecorationRole: return pluginInfo(plugin).iconName(); default: return QVariant(); }; } - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override + int rowCount(const QModelIndex& parent = QModelIndex()) const override { if (!parent.isValid()) { return m_plugins.count(); } return 0; } private: QList m_plugins; }; class LoadedPluginsDelegate : public KWidgetItemDelegate { Q_OBJECT public: LoadedPluginsDelegate(QAbstractItemView *itemView, QObject *parent = 0) : KWidgetItemDelegate(itemView, parent) , pushButton(new QPushButton) { pushButton->setIcon(QIcon::fromTheme("dialog-information")); // only for getting size matters } - ~LoadedPluginsDelegate() + ~LoadedPluginsDelegate() override { delete pushButton; } - virtual QList createItemWidgets(const QModelIndex &/*index*/) const override + QList createItemWidgets(const QModelIndex &/*index*/) const override { return QList(); } QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override { int i = 5; int j = 1; QFont font = titleFont(option.font); QFontMetrics fmTitle(font); return QSize(qMax(fmTitle.width(index.model()->data(index, Qt::DisplayRole).toString()), option.fontMetrics.width(index.model()->data(index, PluginsModel::DescriptionRole).toString())) + KIconLoader::SizeMedium + MARGIN * i + pushButton->sizeHint().width() * j, qMax(KIconLoader::SizeMedium + MARGIN * 2, fmTitle.height() + option.fontMetrics.height() + MARGIN * 2)); } void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { if (!index.isValid()) { return; } painter->save(); QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, 0); int iconSize = option.rect.height() - MARGIN * 2; QPixmap pixmap = KIconLoader::global()->loadIcon(index.model()->data(index, Qt::DecorationRole).toString(), KIconLoader::Desktop, iconSize, KIconLoader::DefaultState); painter->drawPixmap(QRect(dependantLayoutValue(MARGIN + option.rect.left(), iconSize, option.rect.width()), MARGIN + option.rect.top(), iconSize, iconSize), pixmap, QRect(0, 0, iconSize, iconSize)); QRect contentsRect(dependantLayoutValue(MARGIN * 2 + iconSize + option.rect.left(), option.rect.width() - MARGIN * 3 - iconSize, option.rect.width()), MARGIN + option.rect.top(), option.rect.width() - MARGIN * 3 - iconSize, option.rect.height() - MARGIN * 2); int lessHorizontalSpace = MARGIN * 2 + pushButton->sizeHint().width(); contentsRect.setWidth(contentsRect.width() - lessHorizontalSpace); if (option.state & QStyle::State_Selected) { painter->setPen(option.palette.highlightedText().color()); } if (itemView()->layoutDirection() == Qt::RightToLeft) { contentsRect.translate(lessHorizontalSpace, 0); } painter->save(); painter->save(); QFont font = titleFont(option.font); QFontMetrics fmTitle(font); painter->setFont(font); painter->drawText(contentsRect, Qt::AlignLeft | Qt::AlignTop, fmTitle.elidedText(index.model()->data(index, Qt::DisplayRole).toString(), Qt::ElideRight, contentsRect.width())); painter->restore(); painter->drawText(contentsRect, Qt::AlignLeft | Qt::AlignBottom, option.fontMetrics.elidedText(index.model()->data(index, PluginsModel::DescriptionRole).toString(), Qt::ElideRight, contentsRect.width())); painter->restore(); painter->restore(); } QList createItemWidgets() const { QPushButton *button = new QPushButton(); button->setIcon(QIcon::fromTheme("dialog-information")); setBlockedEventTypes(button, QList() << QEvent::MouseButtonPress << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick); connect(button, &QPushButton::clicked, this, &LoadedPluginsDelegate::info); return QList() << button; } void updateItemWidgets(const QList widgets, const QStyleOptionViewItem &option, const QPersistentModelIndex &index) const override { Q_UNUSED(index); if ( widgets.isEmpty() ) { qDebug() << "Fixme: missing button?"; return; } QPushButton *aboutPushButton = static_cast(widgets[0]); QSize aboutPushButtonSizeHint = aboutPushButton->sizeHint(); aboutPushButton->resize(aboutPushButtonSizeHint); aboutPushButton->move(dependantLayoutValue(option.rect.width() - MARGIN - aboutPushButtonSizeHint.width(), aboutPushButtonSizeHint.width(), option.rect.width()), option.rect.height() / 2 - aboutPushButtonSizeHint.height() / 2); } int dependantLayoutValue(int value, int width, int totalWidth) const { if (itemView()->layoutDirection() == Qt::LeftToRight) { return value; } return totalWidth - width - value; } QFont titleFont(const QFont &baseFont) const { QFont retFont(baseFont); retFont.setBold(true); return retFont; } private Q_SLOTS: void info() { PluginsModel *m = static_cast(itemView()->model()); KDevelop::IPlugin *p = m->pluginForIndex(focusedIndex()); if (p) { // TODO KF5: Port // const K4AboutData *aboutData = p->componentData().aboutData(); // if (!aboutData->programName().isEmpty()) { // Be sure the about data is not completely empty // KAboutApplicationDialog aboutPlugin(aboutData, itemView()); // aboutPlugin.exec(); // return; // } } } private: QPushButton *pushButton; }; class PluginsView : public QListView { public: PluginsView(QWidget* parent = 0) :QListView(parent) { setModel(new PluginsModel()); setItemDelegate(new LoadedPluginsDelegate(this)); setVerticalScrollMode(QListView::ScrollPerPixel); } - virtual ~PluginsView() + ~PluginsView() override { // explicitly delete the delegate here since otherwise // we get spammed by warnings that the QPushButton we return // in createItemWidgets is deleted before the delegate // *sigh* - even dfaure says KWidgetItemDelegate is a crude hack delete itemDelegate(); } - virtual QSize sizeHint() const override + QSize sizeHint() const override { QSize ret = QListView::sizeHint(); ret.setWidth(qMax(ret.width(), sizeHintForColumn(0) + 30)); return ret; } }; LoadedPluginsDialog::LoadedPluginsDialog( QWidget* parent ) : QDialog( parent ) { setWindowTitle(i18n("Loaded Plugins")); QVBoxLayout* vbox = new QVBoxLayout(this); KTitleWidget* title = new KTitleWidget(this); title->setPixmap(QIcon::fromTheme(KAboutData::applicationData().programIconName()), KTitleWidget::ImageLeft); title->setText(i18n("Plugins loaded for %1", KAboutData::applicationData().displayName())); vbox->addWidget(title); vbox->addWidget(new PluginsView()); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close); connect(buttonBox, &QDialogButtonBox::accepted, this, &LoadedPluginsDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &LoadedPluginsDialog::reject); buttonBox->button(QDialogButtonBox::Close)->setDefault(true); vbox->addWidget(buttonBox); } #include "moc_loadedpluginsdialog.cpp" #include "loadedpluginsdialog.moc" diff --git a/shell/mainwindow.h b/shell/mainwindow.h index e0cf3d1104..9de56909e7 100644 --- a/shell/mainwindow.h +++ b/shell/mainwindow.h @@ -1,115 +1,115 @@ /* This file is part of the KDevelop project Copyright 2003 Falk Brettschneider Copyright 2003 John Firebaugh Copyright 2003 Amilcar do Carmo Lucas Copyright 2004, 2007 Alexander Dymo Copyright 2006 Adam Treat 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 KDEVPLATFORM_MAINWINDOW_H #define KDEVPLATFORM_MAINWINDOW_H #include #include #include "shellexport.h" namespace KTextEditor { class View; } namespace KTextEditorIntegration { class MainWindow; } namespace KDevelop { class IDocument; /** KDevelop main window. Provides methods to control the main window of an application. */ class KDEVPLATFORMSHELL_EXPORT MainWindow: public Sublime::MainWindow { friend class UiController; Q_OBJECT Q_CLASSINFO( "D-Bus Interface", "org.kdevelop.MainWindow" ) public: explicit MainWindow( Sublime::Controller *parent = 0, Qt::WindowFlags flags = KDE_DEFAULT_WINDOWFLAGS ); - virtual ~MainWindow(); + ~MainWindow() override; /*! @p status must implement KDevelop::IStatus */ void registerStatus(QObject* status); KTextEditorIntegration::MainWindow *kateWrapper() const; public Q_SLOTS: /*! Shows an error message in the status bar. @p message The message @p timeout The timeout in milliseconds how long to show the message */ void showErrorMessage(const QString& message, int timeout); virtual Q_SCRIPTABLE void ensureVisible(); virtual Q_SCRIPTABLE QString windowTitle() { return Sublime::MainWindow::windowTitle(); } - virtual void setVisible( bool visible ) override; + void setVisible( bool visible ) override; void configureShortcuts(); - virtual void loadSettings() override; + void loadSettings() override; Q_SIGNALS: void finishedLoading(); protected: //FIXME DOCUMENT!!! queryClose() must call all of the Core cleanup() methods! - virtual bool queryClose() override; + bool queryClose() override; //reimplemented from KXMLGUIBuilder to support visible menubar separators QAction *createCustomElement(QWidget *parent, int index, const QDomElement &element) override; virtual void initialize(); virtual void cleanup(); - virtual void initializeStatusBar() override; + void initializeStatusBar() override; void dragEnterEvent( QDragEnterEvent* ) override; void dropEvent( QDropEvent* ) override; void applyMainWindowSettings(const KConfigGroup& config) override; void createGUI(KParts::Part* part); protected Q_SLOTS: - virtual void tabContextMenuRequested(Sublime::View* , QMenu* ) override; - virtual void tabToolTipRequested(Sublime::View* view, Sublime::Container* container, int tab) override; - virtual void dockBarContextMenuRequested(Qt::DockWidgetArea, const QPoint&) override; - virtual void newTabRequested() override; + void tabContextMenuRequested(Sublime::View* , QMenu* ) override; + void tabToolTipRequested(Sublime::View* view, Sublime::Container* container, int tab) override; + void dockBarContextMenuRequested(Qt::DockWidgetArea, const QPoint&) override; + void newTabRequested() override; private Q_SLOTS: void updateCaption(); void updateTabColor(IDocument* doc); void updateAllTabColors(); void shortcutsChanged(); private: class MainWindowPrivate *d; friend class MainWindowPrivate; }; } #endif diff --git a/shell/mainwindow_p.h b/shell/mainwindow_p.h index 3c300d26be..47e94af54c 100644 --- a/shell/mainwindow_p.h +++ b/shell/mainwindow_p.h @@ -1,156 +1,156 @@ /* This file is part of the KDevelop project Copyright 2002 Falk Brettschneider Copyright 2003 John Firebaugh Copyright 2006 Adam Treat Copyright 2006, 2007 Alexander Dymo 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 KDEVPLATFORM_MAINWINDOW_PRIVATE_H #define KDEVPLATFORM_MAINWINDOW_PRIVATE_H #include #include #include #include #include class KActionCollection; class QMenu; namespace Sublime { class View; class Container; } namespace KParts { class Part; } namespace KTextEditor { class View; } namespace KTextEditorIntegration { class MainWindow; } namespace KDevelop { class IPlugin; class MainWindow; class StatusBar; class MainWindowPrivate: public QObject { Q_OBJECT public: explicit MainWindowPrivate(MainWindow *mainWindow); - ~MainWindowPrivate(); + ~MainWindowPrivate() override; QPointer centralPlugin; void setupActions(); void setupGui(); void setupStatusBar(); void registerStatus(QObject*); void tabContextMenuRequested(Sublime::View *view, QMenu* menu); void tabToolTipRequested(Sublime::View* view, Sublime::Container* container, int tab); void dockBarContextMenuRequested(Qt::DockWidgetArea area, const QPoint& position); public Q_SLOTS: void addPlugin( KDevelop::IPlugin *plugin ); void removePlugin( KDevelop::IPlugin *plugin ); void activePartChanged(KParts::Part *part); void mergeView(Sublime::View *view); void changeActiveView(Sublime::View *view); void xmlguiclientDestroyed(QObject* obj); //actions void fileNew(); void gotoNextWindow(); void gotoPreviousWindow(); void selectPrevItem(); void selectNextItem(); void viewAddNewToolView(); void newWindow(); void splitHorizontal(); void splitVertical(); void split(Qt::Orientation orientation); void toggleFullScreen(bool fullScreen); void gotoNextSplit(); void gotoPreviousSplit(); void newToolbarConfig(); void settingsDialog(); void quitAll(); // void fixToolbar(); ///Returns true if we're currently changing the active view through changeActiveView() bool changingActiveView() const ; void configureNotifications(); void showAboutPlatform(); void showLoadedPlugins(); void toggleArea(bool b); void showErrorMessage(QString message, int timeout); void pluginDestroyed(QObject*); /// the following slots always activate the m_tabView before calling the normal slot above /// @see m_tabView /// @see tabContextMenuRequested void contextMenuFileNew(); void contextMenuSplitHorizontal(); void contextMenuSplitVertical(); /// reload all open documents void reloadAll(); KTextEditorIntegration::MainWindow *kateWrapper() const; private: KActionCollection *actionCollection(); MainWindow *m_mainWindow; StatusBar* m_statusBar; QWidget* lastXMLGUIClientView; QPointer m_workingSetCornerWidget; QMap m_pluginCustomClients; bool m_changingActiveView; /// the view of the tab that got it's context menu connected Sublime::View* m_tabView; QPair > m_tabTooltip; KTextEditorIntegration::MainWindow* m_kateWrapper; }; } #endif diff --git a/shell/openprojectpage.h b/shell/openprojectpage.h index c6fc9d6e74..d85aaec421 100644 --- a/shell/openprojectpage.h +++ b/shell/openprojectpage.h @@ -1,53 +1,53 @@ /*************************************************************************** * Copyright (C) 2008 by Andreas Pakulat #include class QUrl; class KFileWidget; namespace KDevelop { class OpenProjectPage : public QWidget { Q_OBJECT public: explicit OpenProjectPage( const QUrl& startUrl, QWidget* parent = 0 ); QMap projectFilters() const; void setUrl(const QUrl& url); signals: void urlSelected(const QUrl&); void accepted(); protected: - virtual void showEvent(QShowEvent*) override; + void showEvent(QShowEvent*) override; private slots: void highlightFile(const QUrl&); void opsEntered(const QUrl& item); void comboTextChanged(const QString&); void dirChanged(const QUrl& url); private: QUrl getAbsoluteUrl(const QString&) const; KFileWidget* fileWidget; QMap m_projectFilters; }; } #endif diff --git a/shell/partcontroller.h b/shell/partcontroller.h index 5c6d9d6b0a..0acf2f2f65 100644 --- a/shell/partcontroller.h +++ b/shell/partcontroller.h @@ -1,111 +1,111 @@ /*************************************************************************** * Copyright 2006 Adam Treat * * Copyright 2007 Alexander Dymo * * Copyright 2015 Kevin Funk * * * * 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 Library 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. * ***************************************************************************/ #ifndef __KDEVPARTCONTROLLER_H__ #define __KDEVPARTCONTROLLER_H__ #include #include #include #include #include "core.h" namespace KParts { class Part; class PartManager; class ReadOnlyPart; class ReadWritePart; } namespace KTextEditor { class Document; class Editor; class View; } class QMimeType; Q_DECLARE_METATYPE(KSharedConfigPtr) namespace KDevelop { class KDEVPLATFORMSHELL_EXPORT PartController : public IPartController { friend class Core; friend class CorePrivate; Q_OBJECT public: PartController(Core *core, QWidget *toplevel); - virtual ~PartController(); + ~PartController() override; bool showTextEditorStatusBar() const; KTextEditor::Document* createTextPart( const QString &encoding = QString() ); - virtual KTextEditor::Editor* editorPart() const override; + KTextEditor::Editor* editorPart() const override; bool canCreatePart( const QUrl &url ); using IPartController::createPart; KParts::Part* createPart( const QUrl &url, const QString& prefName = QString() ); KParts::Part* createPart( const QString &mimeType, const QString &partType, const QString &className, const QString &preferredName = QString() ); KParts::ReadOnlyPart* activeReadOnly() const; KParts::ReadWritePart* activeReadWrite() const; KParts::ReadOnlyPart* readOnly( KParts::Part *part ) const; KParts::ReadWritePart* readWrite( KParts::Part *part ) const; bool isTextType(const QMimeType& mimeType); virtual void setActiveView( KTextEditor::View * view ); virtual KTextEditor::View * activeView(); virtual KTextEditor::Document * createDocument(); virtual bool closeDocument( KTextEditor::Document * doc ); virtual KTextEditor::View * createView( KTextEditor::Document * doc ); virtual bool closeView( KTextEditor::View * view ); public Q_SLOTS: void setShowTextEditorStatusBar(bool show); protected: virtual void loadSettings( bool projectIsLoaded ); virtual void saveSettings( bool projectIsLoaded ); virtual void initialize(); virtual void cleanup(); private: void setupActions(); class PartControllerPrivate* const d; }; } #endif diff --git a/shell/partdocument.h b/shell/partdocument.h index d84fba2753..3696b86bdb 100644 --- a/shell/partdocument.h +++ b/shell/partdocument.h @@ -1,88 +1,88 @@ /*************************************************************************** * Copyright 2007 Alexander Dymo * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_PARTDOCUMENT_H #define KDEVPLATFORM_PARTDOCUMENT_H #include #include #include "shellexport.h" namespace KParts { class Part; } namespace KDevelop { /** The generic document which represents KParts. This document is used by shell when more specific document classes are incapable of loading the url. This document loads one KPart (read-only or read-write) per view and sets part widget to be a view widget. */ class KDEVPLATFORMSHELL_EXPORT PartDocument: public Sublime::UrlDocument, public KDevelop::IDocument { Q_OBJECT public: PartDocument(const QUrl &url, ICore* core, const QString& preferredPart = QString() ); - virtual ~PartDocument(); + ~PartDocument() override; - virtual QUrl url() const override; + QUrl url() const override; void setUrl(const QUrl& newUrl); - virtual QWidget *createViewWidget(QWidget *parent = 0) override; - virtual KParts::Part *partForView(QWidget *view) const override; + QWidget *createViewWidget(QWidget *parent = 0) override; + KParts::Part *partForView(QWidget *view) const override; - virtual QMimeType mimeType() const override; - virtual KTextEditor::Document* textDocument() const override; - virtual bool save(DocumentSaveMode mode = Default) override; - virtual void reload() override; + QMimeType mimeType() const override; + KTextEditor::Document* textDocument() const override; + bool save(DocumentSaveMode mode = Default) override; + void reload() override; ///Closes and deletes the document. Asks the user before if needed. - virtual bool close(DocumentSaveMode mode = Default) override; - virtual bool isActive() const override; - virtual DocumentState state() const override; + bool close(DocumentSaveMode mode = Default) override; + bool isActive() const override; + DocumentState state() const override; - virtual void setPrettyName(QString name) override; + void setPrettyName(QString name) override; - virtual void activate(Sublime::View *activeView, KParts::MainWindow *mainWindow) override; + void activate(Sublime::View *activeView, KParts::MainWindow *mainWindow) override; - virtual KTextEditor::Cursor cursorPosition() const override; - virtual void setCursorPosition(const KTextEditor::Cursor &cursor) override; - virtual void setTextSelection(const KTextEditor::Range &range) override; + KTextEditor::Cursor cursorPosition() const override; + void setCursorPosition(const KTextEditor::Cursor &cursor) override; + void setTextSelection(const KTextEditor::Range &range) override; //Overridden from Sublime::Document - virtual bool closeDocument(bool silent) override; - virtual bool askForCloseFeedback() override; + bool closeDocument(bool silent) override; + bool askForCloseFeedback() override; protected: /** Gives us access to the KParts */ QMap partForView() const; /** Lets us override the createViewWidget method safely */ void addPartForView(QWidget* widget, KParts::Part* part); private: class PartDocumentPrivate * const d; }; } #endif diff --git a/shell/plugincontroller.h b/shell/plugincontroller.h index 620e945518..d5900a3f45 100644 --- a/shell/plugincontroller.h +++ b/shell/plugincontroller.h @@ -1,185 +1,185 @@ /* This file is part of the KDE project Copyright 2007 Andreas Pakulat Copyright 2004, 2007 Alexander Dymo Copyright 2006 Matt Rogers 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 KDEVPLATFORM_PLUGINCONTROLLER_H #define KDEVPLATFORM_PLUGINCONTROLLER_H #include #include #include "shellexport.h" namespace KDevelop { class Core; class CorePrivate; class IPlugin; class PluginControllerPrivate; /** * The KDevelop plugin controller. * The Plugin controller is responsible for querying, loading and unloading * available plugins. */ class KDEVPLATFORMSHELL_EXPORT PluginController: public IPluginController { Q_OBJECT friend class Core; friend class CorePrivate; public: explicit PluginController(Core *core); - virtual ~PluginController(); + ~PluginController() override; /** * Get the plugin instance based on the ID. The ID should be whatever is * in X-KDE-PluginInfo-Name */ IPlugin* plugin( const QString& ); /** * Get the plugin info for a loaded plugin */ KPluginMetaData pluginInfo( const IPlugin* ) const override; /** * Find the KPluginMetaData structure for the given @p pluginId. */ KPluginMetaData infoForPluginId(const QString &pluginId) const override; /** * Get a list of currently loaded plugins */ QList loadedPlugins() const override; /** * Returns a uniquely specified plugin. If it isn't already loaded, it will be. * @param pluginName the name of the plugin, as given in the X-KDE-PluginInfo-Name property * @returns a pointer to the plugin instance or 0 */ IPlugin * loadPlugin( const QString & pluginName ) override; /** * @brief Unloads the plugin specified by @p plugin * * @param plugin The name of the plugin as specified by the * X-KDE-PluginInfo-Name key of the .desktop file for the plugin */ bool unloadPlugin( const QString & plugin ) override; enum PluginDeletion { Now, Later }; /** * retrieve all plugin infos */ QVector allPluginInfos() const; /** * loads not-yet-loaded plugins and unloads plugins * depending on the configuration in the session\ */ void updateLoadedPlugins(); /** * Queries for the plugin which supports given extension interface. * * All already loaded plugins will be queried and the first one to support the extension interface * will be returned. Any plugin can be an extension, only "ServiceTypes=..." entry is * required in .desktop file for that plugin. * * @param extension The extension interface * @param pluginname The name of the plugin to load if multiple plugins for the extension exist, corresponds to the X-KDE-PluginInfo-Name * @return A KDevelop extension plugin for given service type or 0 if no plugin supports it */ IPlugin *pluginForExtension(const QString &extension, const QString &pluginName = {}, const QVariantMap& constraints = QVariantMap()) override; QList allPluginsForExtension(const QString &extension, const QVariantMap& constraints = QVariantMap()) override; QStringList allPluginNames(); QVector queryExtensionPlugins(const QString& extension, const QVariantMap& constraints = QVariantMap()) const override; QList queryPluginsForContextMenuExtensions( KDevelop::Context* context ) const override; QStringList projectPlugins(); void loadProjectPlugins(); void unloadProjectPlugins(); void resetToDefaults(); bool isEnabled(const KPluginMetaData& info) const; private: /** * Directly unload the given \a plugin, either deleting it now or \a deletion. * * \param plugin plugin to unload * \param deletion if true, delete the plugin later, if false, delete it now. */ bool unloadPlugin(IPlugin* plugin, PluginDeletion deletion); /** * @internal * * The internal method for loading plugins. * Called by @ref loadPlugin directly or through the queue for async plugin * loading. */ IPlugin* loadPluginInternal( const QString &pluginId ); /** * Check whether the plugin identified by @p info has unresolved dependencies. * * Assume a plugin depends on the interfaces Foo and Bar. Then, all available enabled * plugins are queried to check whether any fulfills the interfaces. If any of the * interfaces is not found, then it is inserted into @p missing and this method returns * true. Otherwise, @p missing is empty and this method returns true, indicating that all * dependencies can be fulfilled. * * @return true when there are unresolved dependencies, false otherwise. */ bool hasUnresolvedDependencies( const KPluginMetaData& info, QStringList& missing ) const; bool loadDependencies(const KPluginMetaData&, QString& failedPlugin); void loadOptionalDependencies(const KPluginMetaData& info); void cleanup(); virtual void initialize(); private: class PluginControllerPrivate* const d; }; } #endif diff --git a/shell/problemmodel.h b/shell/problemmodel.h index 0933a8049d..0e4810d52f 100644 --- a/shell/problemmodel.h +++ b/shell/problemmodel.h @@ -1,182 +1,182 @@ /* * KDevelop Problem Reporter * * Copyright 2007 Hamish Rodda * Copyright 2015 Laszlo Kis-Adam * * 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. */ #ifndef PROBLEMMODEL_H #define PROBLEMMODEL_H #include #include #include #include struct ProblemModelPrivate; namespace KDevelop { class IDocument; class ProblemStore; /** * @brief Wraps a ProblemStore and adds the QAbstractItemModel interface, so the it can be used in a model/view architecture. * * By default ProblemModel instantiates a FilteredProblemStore, with the following features on: * \li ScopeFilter * \li SeverityFilter * \li Grouping * \li CanByPassScopeFilter * * Has to following columns: * \li Error * \li Source * \li File * \li Line * \li Column * \li LastColumn * * Possible ProblemModel features * \li NoFeatures * \li CanDoFullUpdate * \li CanShowImports * \li ScopeFilter * \li SeverityFilter * \li Grouping * \li CanByPassScopeFilter * * Scope, severity, grouping, imports can be set using the slots named after these features. * * Usage example: * @code * IProblem::Ptr problem(new DetectedProblem); * problem->setDescription(QStringLiteral("Problem")); * ProblemModel *model = new ProblemModel(nullptr); * model->addProblem(problem); * model->rowCount(); // returns 1 * QModelIndex idx = model->index(0, 0); * model->data(index); // "Problem" * @endcode * */ class KDEVPLATFORMSHELL_EXPORT ProblemModel : public QAbstractItemModel { Q_OBJECT public: /// List of supportable features enum FeatureCode { NoFeatures = 0, /// No features :( CanDoFullUpdate = 1, /// Reload/Reparse problems CanShowImports = 2, /// Show problems from imported files. E.g.: Header files in C/C++ ScopeFilter = 4, /// Filter problems by scope. E.g.: current document, open documents, etc SeverityFilter = 8, /// Filter problems by severity. E.g.: hint, warning, error, etc Grouping = 16, /// Can group problems CanByPassScopeFilter = 32 /// Can bypass scope filter }; Q_DECLARE_FLAGS(Features, FeatureCode) explicit ProblemModel(QObject *parent, ProblemStore *store = NULL); - virtual ~ProblemModel(); + ~ProblemModel() override; enum Columns { Error, Source, File, Line, Column, LastColumn }; enum Roles { ProblemRole = Qt::UserRole + 1, SeverityRole }; - virtual int columnCount(const QModelIndex & parent = QModelIndex()) const override; - virtual QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const override; - virtual QModelIndex parent(const QModelIndex & index) const override; - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; - virtual int rowCount(const QModelIndex & parent = QModelIndex()) const override; - virtual QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override; + int columnCount(const QModelIndex & parent = QModelIndex()) const override; + QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex & index) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + int rowCount(const QModelIndex & parent = QModelIndex()) const override; + QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override; IProblem::Ptr problemForIndex(const QModelIndex& index) const; /// Adds a new problem to the model void addProblem(const IProblem::Ptr &problem); /// Clears the problems, then adds a new set of them void setProblems(const QVector &problems); /// Clears the problems void clearProblems(); /// Retrieve the supported features Features features() const; /// Set the supported features void setFeatures(Features features); public slots: /// Show imports virtual void setShowImports(bool){} /// Sets the scope filter. Uses int to be able to use QSignalMapper virtual void setScope(int scope); /// Sets the severity filter. Uses int to be able to use QSignalMapper virtual void setSeverity(int severity); void setGrouping(int grouping); /** * Force a full problem update. * E.g.: Reparse the source code. * Obviously it doesn't make sense for run-time problem checkers. */ virtual void forceFullUpdate(){} protected slots: /// Triggered when problems change virtual void onProblemsChanged(){} private slots: /// Triggered when the current document changes virtual void setCurrentDocument(IDocument* doc); /// Triggered before the problems are rebuilt void onBeginRebuild(); /// Triggered once the problems have been rebuilt void onEndRebuild(); protected: ProblemStore *store() const; private: QScopedPointer d; }; Q_DECLARE_OPERATORS_FOR_FLAGS(ProblemModel::Features) } #endif // PROBLEMMODEL_H diff --git a/shell/problemmodelset.h b/shell/problemmodelset.h index d235de4179..8effe8d852 100644 --- a/shell/problemmodelset.h +++ b/shell/problemmodelset.h @@ -1,96 +1,96 @@ /* * Copyright 2015 Laszlo Kis-Adam * * 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. */ #ifndef PROBLEMMODELSET_H #define PROBLEMMODELSET_H #include #include #include class QAbstractItemModel; namespace KDevelop { class ProblemModel; /// Struct that handles the model and it's name as one unit, stored in ProblemModelSet struct ModelData { QString name; ProblemModel *model; }; struct ProblemModelSetPrivate; /** * @brief Stores name/model pairs and emits signals when they are added/removed. * * Typically it's used from plugins, which maintains a reference to the model added. * Therefore It assumes that models get removed, so it doesn't delete! * * Usage example: * @code * ProblemModelSet *set = new ProblemModelSet(); * ProblemModel *model = new ProblemModel(nullptr); * set->addModel(QStringLiteral("MODEL"), model); // added() signal is emitted * set->models().count(); // returns 1 * set->findModel(QStringLiteral("MODEL")); // returns the model just added * set->removeModel(QStringLiteral("MODEL")); // removed() signal is emitted * @endcode * */ class KDEVPLATFORMSHELL_EXPORT ProblemModelSet : public QObject { Q_OBJECT public: explicit ProblemModelSet(QObject *parent = nullptr); - ~ProblemModelSet(); + ~ProblemModelSet() override; /// Adds a model void addModel(const QString &name, ProblemModel *model); /// Finds a model ProblemModel* findModel(const QString &name) const; /// Removes a model void removeModel(const QString &name); /// Retrieves a list of models stored QVector models() const; signals: /// Emitted when a new model is added void added(const ModelData &model); /// Emitted when a model is removed void removed(const QString &name); private: QScopedPointer d; }; } Q_DECLARE_TYPEINFO(KDevelop::ModelData, Q_MOVABLE_TYPE); #endif diff --git a/shell/problemstore.h b/shell/problemstore.h index 7d6d8e2abe..4209e8043b 100644 --- a/shell/problemstore.h +++ b/shell/problemstore.h @@ -1,148 +1,148 @@ /* * Copyright 2015 Laszlo Kis-Adam * * 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. */ #ifndef PROBLEMSTORE_H #define PROBLEMSTORE_H #include #include #include #include #include struct ProblemStorePrivate; namespace KDevelop { class WatchedDocumentSet; class ProblemStoreNode; /** * @brief Stores and handles problems. Does no ordering or filtering, those should be done in subclasses. * * Used to store problems that are ordered, filtered somewhere else. For example: DUChain problems gathered by ProblemReporter. * Stores the problems in ProblemStoreNodes. * When implementing a subclass, first and foremost the rebuild method needs to be implemented, which is called every time there's a change in scope and severity filter. * If grouping is desired then also the setGrouping method must be implemented. * ProblemStore depending on settings uses CurrentDocumentSet, OpenDocumentSet, CurrentProjectSet, or AllProjectSet for scope support (NOTE: Filtering still has to be implemented in either a subclass, or somewhere else). * When the scope changes it emits the changed() signal. * * Scope set / query methods: * \li setScope() * \li scope() * * Valid scope settings: * \li CurrentDocument * \li OpenDocuments * \li CurrentProject * \li AllProjects * \li BypassScopeFilter * * Usage example: * @code * QVector problems; * // Add 4 problems * ... * ProblemStore *store = new ProblemStore(); * store->setProblems(problems); * store->count(); // Returns 4 * * ProblemStoreNode *node = store->findNode(0); // Returns the node with the first problem * @endcode * */ class KDEVPLATFORMSHELL_EXPORT ProblemStore : public QObject { Q_OBJECT public: explicit ProblemStore(QObject *parent = nullptr); - virtual ~ProblemStore(); + ~ProblemStore() override; /// Adds a problem virtual void addProblem(const IProblem::Ptr &problem); /// Clears the current problems, and adds new ones from a list virtual void setProblems(const QVector &problems); /// Finds the specified node virtual const ProblemStoreNode* findNode(int row, ProblemStoreNode *parent = nullptr) const; /// Returns the number of problems virtual int count(ProblemStoreNode *parent = nullptr) const; /// Clears the problems virtual void clear(); /// Rebuild the problems list, if applicable. It does nothing in the base class. virtual void rebuild(); /// Specifies the severity filter virtual void setSeverity(int severity); /// Retrives the severity filter settings int severity() const; /// Retrieves the currently watched document set WatchedDocumentSet* documents() const; /// Sets the scope filter void setScope(int scope); /// Returns the current scope int scope() const; /// Sets the grouping method virtual void setGrouping(int grouping); /// Sets whether we should bypass the scope filter virtual void setBypassScopeFilter(bool bypass); /// Sets the currently shown document (in the editor, it's triggered by the IDE) void setCurrentDocument(const IndexedString &doc); /// Retrives the path of the current document const KDevelop::IndexedString& currentDocument() const; signals: /// Emitted when the problems change void changed(); /// Emitted before the problemlist is rebuilt void beginRebuild(); /// Emitted once the problemlist has been rebuilt void endRebuild(); private slots: /// Triggered when the watched document set changes. E.g.:document closed, new one added, etc virtual void onDocumentSetChanged(); protected: ProblemStoreNode* rootNode(); private: QScopedPointer d; }; } #endif diff --git a/shell/progresswidget/overlaywidget.h b/shell/progresswidget/overlaywidget.h index 1632ce07dd..b22412d960 100644 --- a/shell/progresswidget/overlaywidget.h +++ b/shell/progresswidget/overlaywidget.h @@ -1,60 +1,60 @@ /*************************************************************************** * Copyright (c) 2004 David Faure * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_OVERLAYWIDGET_H #define KDEVPLATFORM_OVERLAYWIDGET_H #include class QResizeEvent; class QEvent; namespace KDevelop { /** * This is a widget that can align itself with another one, without using a layout, * so that it can actually be on top of other widgets. * Currently the only supported type of alignment is "right aligned, on top of the other widget". */ class OverlayWidget : public QWidget { Q_OBJECT public: OverlayWidget( QWidget* alignWidget, QWidget* parent, const char* name = 0 ); - ~OverlayWidget(); + ~OverlayWidget() override; QWidget * alignWidget() { return mAlignWidget; } void setAlignWidget( QWidget * alignWidget ); protected: void resizeEvent( QResizeEvent* ev ) override; bool eventFilter( QObject* o, QEvent* e) override; private: void reposition(); private: QWidget * mAlignWidget; }; } // namespace #endif /* OVERLAYWIDGET_H */ diff --git a/shell/progresswidget/progressdialog.h b/shell/progresswidget/progressdialog.h index 340160f9f6..d46ead5ddf 100644 --- a/shell/progresswidget/progressdialog.h +++ b/shell/progresswidget/progressdialog.h @@ -1,139 +1,139 @@ /*************************************************************************** * Copyright (c) 2004 Till Adam * * based on imapprogressdialog.cpp ,which is * * Copyright (c) 2002-2003 Klar�vdalens Datakonsult AB * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_PROGRESSDIALOG_H #define KDEVPLATFORM_PROGRESSDIALOG_H #include "overlaywidget.h" #include #include #include class QProgressBar; class QFrame; class QLabel; class QPushButton; namespace KDevelop { class ProgressItem; class TransactionItem; class SSLLabel; class TransactionItemView : public QScrollArea { Q_OBJECT public: explicit TransactionItemView( QWidget * parent = 0, const char * name = 0 ); - virtual ~TransactionItemView() {} + ~TransactionItemView() override {} TransactionItem *addTransactionItem( ProgressItem *item, bool first ); QSize sizeHint() const override; QSize minimumSizeHint() const override; public Q_SLOTS: void slotItemCompleted(TransactionItem * item); protected: - virtual void resizeEvent ( QResizeEvent *event ) override; + void resizeEvent ( QResizeEvent *event ) override; private: QWidget *mBigBox; }; class TransactionItem : public QWidget { Q_OBJECT public: TransactionItem( QWidget *parent, ProgressItem *item, bool first ); - ~TransactionItem(); + ~TransactionItem() override; void hideHLine(); void setProgress( int progress ); void setLabel( const QString & ); // the given text is interpreted as RichText, so you might need to // Qt::escape() it before passing void setStatus( const QString & ); void setTotalSteps( int totalSteps ); ProgressItem *item() const { return mItem; } void addSubTransaction( ProgressItem *item ); // The progressitem is deleted immediately, we take 5s to go out, // so better not use mItem during this time. void setItemComplete() { mItem = 0; } public Q_SLOTS: void slotItemCanceled(); protected: QProgressBar *mProgress; QPushButton *mCancelButton; QLabel *mItemLabel; QLabel *mItemStatus; QFrame *mFrame; ProgressItem *mItem; }; class ProgressDialog : public OverlayWidget { Q_OBJECT public: ProgressDialog( QWidget *alignWidget, QWidget *parent, const char *name = 0 ); - ~ProgressDialog(); + ~ProgressDialog() override; void setVisible( bool b ) override; public Q_SLOTS: void slotToggleVisibility(); protected Q_SLOTS: void slotTransactionAdded( KDevelop::ProgressItem *item ); void slotTransactionCompleted( KDevelop::ProgressItem *item ); void slotTransactionCanceled( KDevelop::ProgressItem *item ); void slotTransactionProgress( KDevelop::ProgressItem *item, unsigned int progress ); void slotTransactionStatus( KDevelop::ProgressItem *item, const QString & ); void slotTransactionLabel( KDevelop::ProgressItem *item, const QString & ); void slotTransactionUsesBusyIndicator( KDevelop::ProgressItem *, bool ); void slotClose(); void slotShow(); void slotHide(); Q_SIGNALS: void visibilityChanged( bool ); protected: - virtual void closeEvent( QCloseEvent * ) override; + void closeEvent( QCloseEvent * ) override; TransactionItemView *mScrollView; QMap mTransactionsToListviewItems; bool mWasLastShown; }; } // namespace KDevelop #endif // __KDevelop_PROGRESSDIALOG_H__ diff --git a/shell/progresswidget/progressmanager.h b/shell/progresswidget/progressmanager.h index 4e39d54b08..62f9e8232c 100644 --- a/shell/progresswidget/progressmanager.h +++ b/shell/progresswidget/progressmanager.h @@ -1,479 +1,479 @@ /*************************************************************************** * (C) 2004 Till Adam * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_PROGRESSMANAGER_H #define KDEVPLATFORM_PROGRESSMANAGER_H #include #include #include #include #include #include namespace Akonadi { class AgentInstance; } namespace KDevelop { class ProgressItem; class ProgressManager; typedef QMap ProgressItemMap; class ProgressItem : public QObject { Q_OBJECT friend class ProgressManager; public: /** * @return The id string which uniquely identifies the operation * represented by this item. */ const QString &id() const { return mId; } /** * @return The parent item of this one, if there is one. */ ProgressItem *parent() const { return mParent.data(); } /** * @return The user visible string to be used to represent this item. */ const QString &label() const { return mLabel; } /** * @param v Set the user visible string identifying this item. */ void setLabel( const QString &v ); /** * @return The string to be used for showing this item's current status. */ const QString &status() const { return mStatus; } /** * Set the string to be used for showing this item's current status. * @param v The status string. */ void setStatus( const QString &v ); /** * @return Whether this item can be canceled. */ bool canBeCanceled() const { return mCanBeCanceled; } /** * @return Whether this item uses secure communication * (Account uses ssl, for example.). */ bool usesCrypto() const { return mUsesCrypto; } /** * Set whether this item uses crypted communication, so listeners * can display a nice crypto icon. * @param v The value. */ void setUsesCrypto( bool v ); /** * @return whether this item uses a busy indicator instead of real progress display */ bool usesBusyIndicator() const { return mUsesBusyIndicator; } /** * Sets whether this item uses a busy indicator instead of real progress for its progress bar. * If it uses a busy indicator, you are still responsible for calling setProgress() from time to * time to update the busy indicator. */ void setUsesBusyIndicator( bool useBusyIndicator ); /** * @return The current progress value of this item in percent. */ unsigned int progress() const { return mProgress; } /** * Set the progress (percentage of completion) value of this item. * @param v The percentage value. */ void setProgress( unsigned int v ); /** * Tell the item it has finished. This will emit progressItemCompleted() * result in the destruction of the item after all slots connected to this * signal have executed. This is the only way to get rid of an item and * needs to be called even if the item is canceled. Don't use the item * after this has been called on it. */ void setComplete(); /** * Reset the progress value of this item to 0 and the status string to * the empty string. */ void reset() { setProgress( 0 ); setStatus( QString() ); mCompleted = 0; } void cancel(); // Often needed values for calculating progress. void setTotalItems( unsigned int v ) { mTotal = v; } unsigned int totalItems() const { return mTotal; } void setCompletedItems( unsigned int v ) { mCompleted = v; } void incCompletedItems( unsigned int v = 1 ) { mCompleted += v; } unsigned int completedItems() const { return mCompleted; } /** * Recalculate progress according to total/completed items and update. */ void updateProgress() { setProgress( mTotal? mCompleted * 100 / mTotal : 0 ); } void addChild( ProgressItem *kiddo ); void removeChild( ProgressItem *kiddo ); bool canceled() const { return mCanceled; } void setBusy( bool busy ); Q_SIGNALS: /** * Emitted when a new ProgressItem is added. * @param The ProgressItem that was added. */ void progressItemAdded( KDevelop::ProgressItem * ); /** * Emitted when the progress value of an item changes. * @param The item which got a new value. * @param The value, for convenience. */ void progressItemProgress( KDevelop::ProgressItem *, unsigned int ); /** * Emitted when a progress item was completed. The item will be * deleted afterwards, so slots connected to this are the last * chance to work with this item. * @param The completed item. */ void progressItemCompleted( KDevelop::ProgressItem * ); /** * Emitted when an item was canceled. It will _not_ go away immediately, * only when the owner sets it complete, which will usually happen. Can be * used to visually indicate the canceled status of an item. Should be used * by the owner of the item to make sure it is set completed even if it is * canceled. There is a ProgressManager::slotStandardCancelHandler which * simply sets the item completed and can be used if no other work needs to * be done on cancel. * @param The canceled item; */ void progressItemCanceled( KDevelop::ProgressItem * ); /** * Emitted when the status message of an item changed. Should be used by * progress dialogs to update the status message for an item. * @param The updated item. * @param The new message. */ void progressItemStatus( KDevelop::ProgressItem *, const QString & ); /** * Emitted when the label of an item changed. Should be used by * progress dialogs to update the label of an item. * @param The updated item. * @param The new label. */ void progressItemLabel( KDevelop::ProgressItem *, const QString & ); /** * Emitted when the crypto status of an item changed. Should be used by * progress dialogs to update the crypto indicator of an item. * @param The updated item. * @param The new state. */ void progressItemUsesCrypto( KDevelop::ProgressItem *, bool ); /** * Emitted when the busy indicator state of an item changes. Should be used * by progress dialogs so that they can adjust the display of the progress bar * to the new mode. * @param item The updated item * @param value True if the item uses a busy indicator now, false otherwise */ void progressItemUsesBusyIndicator( KDevelop::ProgressItem *item, bool value ); protected: /* Only to be used by our good friend the ProgressManager */ ProgressItem( ProgressItem *parent, const QString &id, const QString &label, const QString &status, bool isCancellable, bool usesCrypto ); - virtual ~ProgressItem(); + ~ProgressItem() override; private: QString mId; QString mLabel; QString mStatus; QPointer mParent; bool mCanBeCanceled; unsigned int mProgress; ProgressItemMap mChildren; unsigned int mTotal; unsigned int mCompleted; bool mWaitingForKids; bool mCanceled; bool mUsesCrypto; bool mUsesBusyIndicator; bool mCompletedCalled; }; struct ProgressManagerPrivate; /** * The ProgressManager singleton keeps track of all ongoing transactions * and notifies observers (progress dialogs) when their progress percent value * changes, when they are completed (by their owner), and when they are canceled. * Each ProgressItem emits those signals individually and the singleton * broadcasts them. Use the ::createProgressItem() statics to acquire an item * and then call ->setProgress( int percent ) on it every time you want to * update the item and ->setComplete() when the operation is done. This will * delete the item. Connect to the item's progressItemCanceled() signal to be * notified when the user cancels the transaction using one of the observing * progress dialogs or by calling item->cancel() in some other way. The owner * is responsible for calling setComplete() on the item, even if it is canceled. * Use the standardCancelHandler() slot if that is all you want to do on cancel. * * Note that if you request an item with a certain id and there is already * one with that id, there will not be a new one created but the existing * one will be returned. This is convenient for accessing items that are * needed regularly without the to store a pointer to them or to add child * items to parents by id. */ class ProgressManager : public QObject { Q_OBJECT friend struct ProgressManagerPrivate; public: - virtual ~ProgressManager(); + ~ProgressManager() override; /** * @return The singleton instance of this class. */ static ProgressManager *instance(); /** * Use this to acquire a unique id number which can be used to discern * an operation from all others going on at the same time. Use that * number as the id string for your progressItem to ensure it is unique. * @return */ static QString getUniqueID() { return QString::number( ++uID ); } /** * Creates a ProgressItem with a unique id and the given label. * This is the simplest way to acquire a progress item. It will not * have a parent and will be set to be cancellable and not using crypto. */ static ProgressItem *createProgressItem( const QString &label ) { return instance()->createProgressItemImpl( 0, getUniqueID(), label, QString(), true, false ); } /** * Creates a new progressItem with the given parent, id, label and initial * status. * * @param parent Specify an already existing item as the parent of this one. * @param id Used to identify this operation for cancel and progress info. * @param label The text to be displayed by progress handlers * @param status Additional text to be displayed for the item. * @param canBeCanceled can the user cancel this operation? * @param usesCrypto does the operation use secure transports (SSL) * Cancelling the parent will cancel the children as well (if they can be * canceled) and ongoing children prevent parents from finishing. * @return The ProgressItem representing the operation. */ static ProgressItem *createProgressItem( ProgressItem *parent, const QString &id, const QString &label, const QString &status = QString(), bool canBeCanceled = true, bool usesCrypto = false ) { return instance()->createProgressItemImpl( parent, id, label, status, canBeCanceled, usesCrypto ); } /** * Use this version if you have the id string of the parent and want to * add a subjob to it. */ static ProgressItem *createProgressItem( const QString &parent, const QString &id, const QString &label, const QString &status = QString(), bool canBeCanceled = true, bool usesCrypto = false ) { return instance()->createProgressItemImpl( parent, id, label, status, canBeCanceled, usesCrypto ); } /** * Version without a parent. */ static ProgressItem *createProgressItem( const QString &id, const QString &label, const QString &status = QString(), bool canBeCanceled = true, bool usesCrypto = false ) { return instance()->createProgressItemImpl( 0, id, label, status, canBeCanceled, usesCrypto ); } /** * Version for Akonadi agents. * This connects all the proper signals so that you do not have to * worry about updating the progress or reacting to progressItemCanceled(). */ static ProgressItem *createProgressItem( ProgressItem *parent, const Akonadi::AgentInstance &agent, const QString &id, const QString &label, const QString &status = QString(), bool canBeCanceled = true, bool usesCrypto = false ) { return instance()->createProgressItemForAgent( parent, agent, id, label, status, canBeCanceled, usesCrypto ); } /** * @return true when there are no more progress items. */ bool isEmpty() const { return mTransactions.isEmpty(); } /** * @return the only top level progressitem when there's only one. * Returns 0 if there is no item, or more than one top level item. * Since this is used to calculate the overall progress, it will also return * 0 if there is an item which uses a busy indicator, since that will invalidate * the overall progress. */ ProgressItem *singleItem() const; /** * Ask all listeners to show the progress dialog, because there is * something that wants to be shown. */ static void emitShowProgressDialog() { instance()->emitShowProgressDialogImpl(); } Q_SIGNALS: /** @see ProgressItem::progressItemAdded() */ void progressItemAdded( KDevelop::ProgressItem * ); /** @see ProgressItem::progressItemProgress() */ void progressItemProgress( KDevelop::ProgressItem *, unsigned int ); /** @see ProgressItem::progressItemCompleted() */ void progressItemCompleted( KDevelop::ProgressItem * ); /** @see ProgressItem::progressItemCanceled() */ void progressItemCanceled( KDevelop::ProgressItem * ); /** @see ProgressItem::progressItemStatus() */ void progressItemStatus( KDevelop::ProgressItem *, const QString & ); /** @see ProgressItem::progressItemLabel() */ void progressItemLabel( KDevelop::ProgressItem *, const QString & ); /** @see ProgressItem::progressItemUsesCrypto() */ void progressItemUsesCrypto( KDevelop::ProgressItem *, bool ); /** @see ProgressItem::progressItemUsesBusyIndicator */ void progressItemUsesBusyIndicator( KDevelop::ProgressItem*, bool ); /** * Emitted when an operation requests the listeners to be shown. * Use emitShowProgressDialog() to trigger it. */ void showProgressDialog(); public Q_SLOTS: /** * Calls setCompleted() on the item, to make sure it goes away. * Provided for convenience. * @param item the canceled item. */ void slotStandardCancelHandler( KDevelop::ProgressItem *item ); /** * Aborts all running jobs. Bound to "Esc" */ void slotAbortAll(); private Q_SLOTS: void slotTransactionCompleted( KDevelop::ProgressItem *item ); private: ProgressManager(); // prevent unsolicited copies ProgressManager( const ProgressManager & ); virtual ProgressItem *createProgressItemImpl( ProgressItem *parent, const QString &id, const QString &label, const QString &status, bool cancellable, bool usesCrypto ); virtual ProgressItem *createProgressItemImpl( const QString &parent, const QString &id, const QString &label, const QString &status, bool cancellable, bool usesCrypto ); ProgressItem *createProgressItemForAgent( ProgressItem *parent, const Akonadi::AgentInstance &instance, const QString &id, const QString &label, const QString &status, bool cancellable, bool usesCrypto ); void emitShowProgressDialogImpl(); QHash< QString, ProgressItem* > mTransactions; static unsigned int uID; }; } #endif // __KDevelop_PROGRESSMANAGER_H__ diff --git a/shell/progresswidget/statusbarprogresswidget.h b/shell/progresswidget/statusbarprogresswidget.h index 95d846f7e7..c1464a70cb 100644 --- a/shell/progresswidget/statusbarprogresswidget.h +++ b/shell/progresswidget/statusbarprogresswidget.h @@ -1,95 +1,95 @@ #ifndef KDEVPLATFORM_STATUSBARPROGRESSWIDGET_H #define KDEVPLATFORM_STATUSBARPROGRESSWIDGET_H /*************************************************************************** * (C) 2004 Till Adam * * Don Sanders * * David Faure * * Copyright 2004 David Faure * * * * 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 Library 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. * ***************************************************************************/ /** * A specialized progress widget class, heavily based on * kio_littleprogress_dlg (it looks similar) */ #include class QBoxLayout; class QEvent; class QProgressBar; class QPushButton; class QStackedWidget; class QBoxLayout; class QLabel; class QTimer; namespace KDevelop { class ProgressItem; class ProgressDialog; class StatusbarProgressWidget : public QFrame { Q_OBJECT public: StatusbarProgressWidget( ProgressDialog* progressDialog, QWidget* parent, bool button = true ); public Q_SLOTS: void slotClean(); void slotProgressItemAdded( KDevelop::ProgressItem *i ); void slotProgressItemCompleted( KDevelop::ProgressItem *i ); void slotProgressItemProgress( KDevelop::ProgressItem *i, unsigned int value ); protected Q_SLOTS: void slotProgressDialogVisible( bool ); void slotShowItemDelayed(); void slotBusyIndicator(); void updateBusyMode(); protected: void setMode(); void connectSingleItem(); void activateSingleItemMode(); - virtual bool eventFilter( QObject *, QEvent * ) override; + bool eventFilter( QObject *, QEvent * ) override; private: QProgressBar* m_pProgressBar; QLabel* m_pLabel; QPushButton* m_pButton; enum Mode { None, /*Label,*/ Progress }; uint mode; bool m_bShowButton; QBoxLayout *box; QStackedWidget *stack; ProgressItem *mCurrentItem; ProgressDialog* mProgressDialog; QTimer *mDelayTimer; QTimer *mBusyTimer; QTimer *mCleanTimer; }; } // namespace #endif diff --git a/shell/project.cpp b/shell/project.cpp index 309a961696..a7880c1a4c 100644 --- a/shell/project.cpp +++ b/shell/project.cpp @@ -1,652 +1,652 @@ /* This file is part of the KDE project Copyright 2001 Matthias Hoelzer-Kluepfel Copyright 2002-2003 Roberto Raggi Copyright 2002 Simon Hausmann Copyright 2003 Jens Dagerbo Copyright 2003 Mario Scalas Copyright 2003-2004 Alexander Dymo Copyright 2006 Matt Rogers Copyright 2007 Andreas Pakulat 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 "project.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "core.h" #include "mainwindow.h" #include "projectcontroller.h" #include "uicontroller.h" #include "debug.h" namespace KDevelop { class ProjectProgress : public QObject, public IStatus { Q_OBJECT Q_INTERFACES(KDevelop::IStatus) public: ProjectProgress(); - virtual ~ProjectProgress(); - virtual QString statusName() const override; + ~ProjectProgress() override; + QString statusName() const override; /*! Show indeterminate mode progress bar */ void setBuzzy(); /*! Hide progress bar */ void setDone(); QString projectName; private Q_SLOTS: void slotClean(); Q_SIGNALS: void clearMessage(KDevelop::IStatus*) override; void showMessage(KDevelop::IStatus*,const QString & message, int timeout = 0) override; void showErrorMessage(const QString & message, int timeout = 0) override; void hideProgress(KDevelop::IStatus*) override; void showProgress(KDevelop::IStatus*,int minimum, int maximum, int value) override; private: QTimer* m_timer; }; ProjectProgress::ProjectProgress() { m_timer = new QTimer(this); m_timer->setSingleShot( true ); m_timer->setInterval( 1000 ); connect(m_timer, &QTimer::timeout,this, &ProjectProgress::slotClean); } ProjectProgress::~ProjectProgress() { } QString ProjectProgress::statusName() const { return i18n("Loading Project %1", projectName); } void ProjectProgress::setBuzzy() { qCDebug(SHELL) << "showing busy progress" << statusName(); // show an indeterminate progressbar emit showProgress(this, 0,0,0); emit showMessage(this, i18nc("%1: Project name", "Loading %1", projectName)); } void ProjectProgress::setDone() { qCDebug(SHELL) << "showing done progress" << statusName(); // first show 100% bar for a second, then hide. emit showProgress(this, 0,1,1); m_timer->start(); } void ProjectProgress::slotClean() { emit hideProgress(this); emit clearMessage(this); } class ProjectPrivate { public: Path projectPath; Path projectFile; Path developerFile; QString developerTempFile; QTemporaryFile projectTempFile; IPlugin* manager; QPointer vcsPlugin; ProjectFolderItem* topItem; QString name; KSharedConfigPtr m_cfg; IProject *project; QSet fileSet; bool loading; bool fullReload; bool scheduleReload; ProjectProgress* progress; void reloadDone(KJob* job) { progress->setDone(); loading = false; ProjectController* projCtrl = Core::self()->projectControllerInternal(); if (job->error() == 0 && !Core::self()->shuttingDown()) { if(fullReload) projCtrl->projectModel()->appendRow(topItem); if (scheduleReload) { scheduleReload = false; project->reloadModel(); } } else { projCtrl->abortOpeningProject(project); } } QList itemsForPath( const IndexedString& path ) const { if ( path.isEmpty() ) { return QList(); } if (!topItem->model()) { // this gets hit when the project has not yet been added to the model // i.e. during import phase // TODO: should we handle this somehow? // possible idea: make the item<->path hash per-project return QList(); } Q_ASSERT(topItem->model()); QList items = topItem->model()->itemsForPath(path); QList::iterator it = items.begin(); while(it != items.end()) { if ((*it)->project() != project) { it = items.erase(it); } else { ++it; } } return items; } void importDone( KJob* job) { progress->setDone(); ProjectController* projCtrl = Core::self()->projectControllerInternal(); if(job->error() == 0 && !Core::self()->shuttingDown()) { loading=false; projCtrl->projectModel()->appendRow(topItem); projCtrl->projectImportingFinished( project ); } else { projCtrl->abortOpeningProject(project); } } void initProject(const Path& projectFile_) { // helper method for open() projectFile = projectFile_; } bool initProjectFiles() { KIO::StatJob* statJob = KIO::stat( projectFile.toUrl(), KIO::HideProgressInfo ); if ( !statJob->exec() ) //be sync for right now { KMessageBox::sorry( Core::self()->uiControllerInternal()->defaultMainWindow(), i18n( "Unable to load the project file %1.
" "The project has been removed from the session.", projectFile.pathOrUrl() ) ); return false; } // developerfile == dirname(projectFileUrl) ."/.kdev4/". basename(projectfileUrl) developerFile = projectFile; developerFile.setLastPathSegment( ".kdev4" ); developerFile.addPath( projectFile.lastPathSegment() ); statJob = KIO::stat( developerFile.toUrl(), KIO::HideProgressInfo ); if( !statJob->exec() ) { // the developerfile does not exist yet, check if its folder exists // the developerfile itself will get created below QUrl dir = developerFile.parent().toUrl(); statJob = KIO::stat( dir, KIO::HideProgressInfo ); if( !statJob->exec() ) { KIO::SimpleJob* mkdirJob = KIO::mkdir( dir ); if( !mkdirJob->exec() ) { KMessageBox::sorry( Core::self()->uiController()->activeMainWindow(), i18n("Unable to create hidden dir (%1) for developer file", dir.toDisplayString(QUrl::PreferLocalFile) ) ); return false; } } } projectTempFile.open(); auto copyJob = KIO::file_copy(projectFile.toUrl(), QUrl::fromLocalFile(projectTempFile.fileName()), -1, KIO::Overwrite); KJobWidgets::setWindow(copyJob, Core::self()->uiController()->activeMainWindow()); if (!copyJob->exec()) { qCDebug(SHELL) << "Job failed:" << copyJob->errorString(); KMessageBox::sorry( Core::self()->uiController()->activeMainWindow(), i18n("Unable to get project file: %1", projectFile.pathOrUrl() ) ); return false; } if(developerFile.isLocalFile()) { developerTempFile = developerFile.toLocalFile(); } else { QTemporaryFile tmp; tmp.open(); developerTempFile = tmp.fileName(); auto job = KIO::file_copy(developerFile.toUrl(), QUrl::fromLocalFile(developerTempFile), -1, KIO::HideProgressInfo | KIO::Overwrite); KJobWidgets::setWindow(job, Core::self()->uiController()->activeMainWindow()); job->exec(); } return true; } KConfigGroup initKConfigObject() { // helper method for open() qCDebug(SHELL) << "Creating KConfig object for project files" << developerTempFile << projectTempFile.fileName(); m_cfg = KSharedConfig::openConfig( developerTempFile ); m_cfg->addConfigSources( QStringList() << projectTempFile.fileName() ); KConfigGroup projectGroup( m_cfg, "Project" ); return projectGroup; } bool projectNameUsed(const KConfigGroup& projectGroup) { // helper method for open() name = projectGroup.readEntry( "Name", projectFile.lastPathSegment() ); progress->projectName = name; if( Core::self()->projectController()->isProjectNameUsed( name ) ) { KMessageBox::sorry( Core::self()->uiControllerInternal()->defaultMainWindow(), i18n( "Could not load %1, a project with the same name '%2' is already open.", projectFile.pathOrUrl(), name ) ); qWarning() << "Trying to open a project with a name thats already used by another open project"; return true; } return false; } IProjectFileManager* fetchFileManager(const KConfigGroup& projectGroup) { if (manager) { IProjectFileManager* iface = 0; iface = manager->extension(); Q_ASSERT(iface); return iface; } // helper method for open() QString managerSetting = projectGroup.readEntry( "Manager", "KDevGenericManager" ); //Get our importer IPluginController* pluginManager = Core::self()->pluginController(); manager = pluginManager->pluginForExtension( "org.kdevelop.IProjectFileManager", managerSetting ); IProjectFileManager* iface = 0; if ( manager ) iface = manager->extension(); else { KMessageBox::sorry( Core::self()->uiControllerInternal()->defaultMainWindow(), i18n( "Could not load project management plugin %1.", managerSetting ) ); manager = 0; return 0; } if (iface == 0) { KMessageBox::sorry( Core::self()->uiControllerInternal()->defaultMainWindow(), i18n( "project importing plugin (%1) does not support the IProjectFileManager interface.", managerSetting ) ); delete manager; manager = 0; } return iface; } void loadVersionControlPlugin(KConfigGroup& projectGroup) { // helper method for open() IPluginController* pluginManager = Core::self()->pluginController(); if( projectGroup.hasKey( "VersionControlSupport" ) ) { QString vcsPluginName = projectGroup.readEntry("VersionControlSupport", ""); if( !vcsPluginName.isEmpty() ) { vcsPlugin = pluginManager->pluginForExtension( "org.kdevelop.IBasicVersionControl", vcsPluginName ); } } else { foreach( IPlugin* p, pluginManager->allPluginsForExtension( "org.kdevelop.IBasicVersionControl" ) ) { IBasicVersionControl* iface = p->extension(); if( iface && iface->isVersionControlled( topItem->path().toUrl() ) ) { vcsPlugin = p; projectGroup.writeEntry("VersionControlSupport", pluginManager->pluginInfo(p).pluginId()); projectGroup.sync(); } } } } bool importTopItem(IProjectFileManager* fileManager) { if (!fileManager) { return false; } topItem = fileManager->import( project ); if( !topItem ) { KMessageBox::sorry( Core::self()->uiControllerInternal()->defaultMainWindow(), i18n("Could not open project") ); return false; } return true; } }; Project::Project( QObject *parent ) : IProject( parent ) , d( new ProjectPrivate ) { QDBusConnection::sessionBus().registerObject( "/org/kdevelop/Project", this, QDBusConnection::ExportScriptableSlots ); d->project = this; d->manager = 0; d->topItem = 0; d->loading = false; d->scheduleReload = false; d->progress = new ProjectProgress; Core::self()->uiController()->registerStatus( d->progress ); } Project::~Project() { delete d->progress; delete d; } QString Project::name() const { return d->name; } QString Project::developerTempFile() const { return d->developerTempFile; } QString Project::projectTempFile() const { return d->projectTempFile.fileName(); } KSharedConfigPtr Project::projectConfiguration() const { return d->m_cfg; } Path Project::path() const { return d->projectPath; } void Project::reloadModel() { if (d->loading) { d->scheduleReload = true; return; } d->loading = true; d->fileSet.clear(); // delete topItem and remove it from model ProjectModel* model = Core::self()->projectController()->projectModel(); model->removeRow( d->topItem->row() ); d->topItem = 0; IProjectFileManager* iface = d->manager->extension(); if (!d->importTopItem(iface)) { d->loading = false; d->scheduleReload = false; return; } KJob* importJob = iface->createImportJob(d->topItem ); setReloadJob(importJob); d->fullReload = true; Core::self()->runController()->registerJob( importJob ); } void Project::setReloadJob(KJob* job) { d->loading = true; d->fullReload = false; d->progress->setBuzzy(); connect(job, &KJob::finished, this, [&] (KJob* job) { d->reloadDone(job); }); } bool Project::open( const Path& projectFile ) { d->initProject(projectFile); if (!d->initProjectFiles()) return false; KConfigGroup projectGroup = d->initKConfigObject(); if (d->projectNameUsed(projectGroup)) return false; d->projectPath = d->projectFile.parent(); IProjectFileManager* iface = d->fetchFileManager(projectGroup); if (!iface) return false; Q_ASSERT(d->manager); emit aboutToOpen(this); if (!d->importTopItem(iface) ) { return false; } d->loading=true; d->loadVersionControlPlugin(projectGroup); d->progress->setBuzzy(); KJob* importJob = iface->createImportJob(d->topItem ); connect( importJob, &KJob::result, this, [&] (KJob* job) { d->importDone(job); } ); Core::self()->runController()->registerJob( importJob ); return true; } void Project::close() { Q_ASSERT(d->topItem); if (d->topItem->row() == -1) { qWarning() << "Something went wrong. ProjectFolderItem detached. Project closed during reload?"; return; } Core::self()->projectController()->projectModel()->removeRow( d->topItem->row() ); if (!d->developerFile.isLocalFile()) { auto copyJob = KIO::file_copy(QUrl::fromLocalFile(d->developerTempFile), d->developerFile.toUrl()); KJobWidgets::setWindow(copyJob, Core::self()->uiController()->activeMainWindow()); if (!copyJob->exec()) { qCDebug(SHELL) << "Job failed:" << copyJob->errorString(); KMessageBox::sorry(Core::self()->uiController()->activeMainWindow(), i18n("Could not store developer specific project configuration.\n" "Attention: The project settings you changed will be lost.")); } } } bool Project::inProject( const IndexedString& path ) const { if (d->fileSet.contains( path )) { return true; } return !d->itemsForPath( path ).isEmpty(); } QList< ProjectBaseItem* > Project::itemsForPath(const IndexedString& path) const { return d->itemsForPath(path); } QList< ProjectFileItem* > Project::filesForPath(const IndexedString& file) const { QList items; foreach(ProjectBaseItem* item, d->itemsForPath( file ) ) { if( item->type() == ProjectBaseItem::File ) items << dynamic_cast( item ); } return items; } QList Project::foldersForPath(const IndexedString& folder) const { QList items; foreach(ProjectBaseItem* item, d->itemsForPath( folder ) ) { if( item->type() == ProjectBaseItem::Folder || item->type() == ProjectBaseItem::BuildFolder ) items << dynamic_cast( item ); } return items; } IProjectFileManager* Project::projectFileManager() const { return d->manager->extension(); } IBuildSystemManager* Project::buildSystemManager() const { return d->manager->extension(); } IPlugin* Project::managerPlugin() const { return d->manager; } void Project::setManagerPlugin( IPlugin* manager ) { d->manager = manager; } Path Project::projectFile() const { return d->projectFile; } Path Project::developerFile() const { return d->developerFile; } ProjectFolderItem* Project::projectItem() const { return d->topItem; } IPlugin* Project::versionControlPlugin() const { return d->vcsPlugin.data(); } void Project::addToFileSet( ProjectFileItem* file ) { if (d->fileSet.contains(file->indexedPath())) { return; } d->fileSet.insert( file->indexedPath() ); emit fileAddedToSet( file ); } void Project::removeFromFileSet( ProjectFileItem* file ) { QSet::iterator it = d->fileSet.find(file->indexedPath()); if (it == d->fileSet.end()) { return; } d->fileSet.erase( it ); emit fileRemovedFromSet( file ); } QSet Project::fileSet() const { return d->fileSet; } bool Project::isReady() const { return !d->loading; } } // namespace KDevelop #include "project.moc" #include "moc_project.cpp" diff --git a/shell/project.h b/shell/project.h index 4bb3117816..184041734c 100644 --- a/shell/project.h +++ b/shell/project.h @@ -1,143 +1,143 @@ /* This file is part of the KDE project Copyright 2001 Matthias Hoelzer-Kluepfel Copyright 2001-2002 Bernd Gehrmann Copyright 2002-2003 Roberto Raggi Copyright 2002 Simon Hausmann Copyright 2003 Jens Dagerbo Copyright 2003 Mario Scalas Copyright 2003-2004 Alexander Dymo Copyright 2006 Matt Rogers Copyright 2007 Andreas Pakulat 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 KDEVPLATFORM_SHELLPROJECT_H #define KDEVPLATFORM_SHELLPROJECT_H #include #include #include "shellexport.h" template class QList; class KJob; namespace KDevelop { class IProjectFileManager; class IBuildSystemManager; class ProjectFileItem; class PersistentHash; /** * \brief Object which represents a KDevelop project * * Provide better descriptions */ class KDEVPLATFORMSHELL_EXPORT Project : public IProject { Q_OBJECT public: /** * Constructs a project. * * @param parent The parent object for the plugin. */ explicit Project(QObject *parent = 0); - virtual ~Project(); + ~Project() override; - virtual QList< ProjectBaseItem* > itemsForPath(const IndexedString& path) const override; - virtual QList< ProjectFileItem* > filesForPath(const IndexedString& file) const override; - virtual QList< ProjectFolderItem* > foldersForPath(const IndexedString& folder) const override; + QList< ProjectBaseItem* > itemsForPath(const IndexedString& path) const override; + QList< ProjectFileItem* > filesForPath(const IndexedString& file) const override; + QList< ProjectFolderItem* > foldersForPath(const IndexedString& folder) const override; QString projectTempFile() const; QString developerTempFile() const; Path developerFile() const; - virtual void reloadModel() override; - virtual Path projectFile() const override; - virtual KSharedConfigPtr projectConfiguration() const override; + void reloadModel() override; + Path projectFile() const override; + KSharedConfigPtr projectConfiguration() const override; - virtual void addToFileSet( ProjectFileItem* file ) override; - virtual void removeFromFileSet( ProjectFileItem* file ) override; - virtual QSet fileSet() const override; + void addToFileSet( ProjectFileItem* file ) override; + void removeFromFileSet( ProjectFileItem* file ) override; + QSet fileSet() const override; - virtual bool isReady() const override; + bool isReady() const override; - virtual Path path() const override; + Path path() const override; - virtual Q_SCRIPTABLE QString name() const override; + Q_SCRIPTABLE QString name() const override; public Q_SLOTS: /** * @brief Open a project * * This method opens a project and starts the process of loading the * data for the project from disk. * * @param projectFile The path pointing to the location of the project * file to load * * The project name is taken from the Name key in the project file in * the 'General' group */ bool open(const Path &projectFile); /** This method is invoked when the project needs to be closed. */ void close(); IProjectFileManager* projectFileManager() const override; IBuildSystemManager* buildSystemManager() const override; IPlugin* versionControlPlugin() const override; IPlugin* managerPlugin() const override; /** * Set the manager plugin for the project. */ void setManagerPlugin( IPlugin* manager ); ProjectFolderItem* projectItem() const override; /** * Check if the url specified by @a url is part of the project. * @a url can be either a relative url (to the project directory) or * an absolute url. * * @param url the url to check * * @return true if the url @a url is a part of the project. */ bool inProject(const IndexedString &url) const override; - virtual void setReloadJob(KJob* job) override; + void setReloadJob(KJob* job) override; signals: /** * Internal signal to make IProjectController::projectAboutToOpen useful. */ void aboutToOpen(KDevelop::IProject*); private: Q_PRIVATE_SLOT(d, void importDone(KJob*)) Q_PRIVATE_SLOT(d, void reloadDone(KJob*)) class ProjectPrivate* const d; }; } // namespace KDevelop #endif diff --git a/shell/projectcontroller.h b/shell/projectcontroller.h index 188184c681..25fb3a6bd9 100644 --- a/shell/projectcontroller.h +++ b/shell/projectcontroller.h @@ -1,169 +1,169 @@ /* This file is part of KDevelop Copyright 2006 Adam Treat Copyright 2007 Andreas Pakulat 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 KDEVPLATFORM_PROJECTCONTROLLER_H #define KDEVPLATFORM_PROJECTCONTROLLER_H #include #include #include #include "shellexport.h" namespace Sublime { class Area; } namespace KIO { class Job; } namespace KDevelop { class IProject; class Core; class Context; class ContextMenuExtension; class IPlugin; class KDEVPLATFORMSHELL_EXPORT IProjectDialogProvider : public QObject { Q_OBJECT public: IProjectDialogProvider(); - virtual ~IProjectDialogProvider(); + ~IProjectDialogProvider() override; public Q_SLOTS: /** * Displays some UI to ask the user for the project location. * * @param fetch will tell the UI that the user might want to fetch the project first * @param startUrl tells where to look first */ virtual QUrl askProjectConfigLocation(bool fetch, const QUrl& startUrl = QUrl()) = 0; virtual bool userWantsReopen() = 0; }; class KDEVPLATFORMSHELL_EXPORT ProjectController : public IProjectController { Q_OBJECT Q_CLASSINFO( "D-Bus Interface", "org.kdevelop.ProjectController" ) friend class Core; friend class CorePrivate; friend class ProjectPreferences; public: explicit ProjectController( Core* core ); - virtual ~ProjectController(); + ~ProjectController() override; - virtual IProject* projectAt( int ) const override; - virtual int projectCount() const override; - virtual QList projects() const override; + IProject* projectAt( int ) const override; + int projectCount() const override; + QList projects() const override; - virtual ProjectBuildSetModel* buildSetModel() override; - virtual ProjectModel* projectModel() override; - virtual ProjectChangesModel* changesModel() override; + ProjectBuildSetModel* buildSetModel() override; + ProjectModel* projectModel() override; + ProjectChangesModel* changesModel() override; virtual QItemSelectionModel* projectSelectionModel(); - virtual IProject* findProjectByName( const QString& name ) override; + IProject* findProjectByName( const QString& name ) override; IProject* findProjectForUrl( const QUrl& ) const override; void addProject(IProject*); // IProject* currentProject() const; - virtual bool isProjectNameUsed( const QString& name ) const override; + bool isProjectNameUsed( const QString& name ) const override; void setDialogProvider(IProjectDialogProvider*); QUrl projectsBaseDirectory() const override; QString prettyFileName(const QUrl& url, FormattingOptions format = FormatHtml) const override; QString prettyFilePath(const QUrl& url, FormattingOptions format = FormatHtml) const override; ContextMenuExtension contextMenuExtension( KDevelop::Context* ctx ); public Q_SLOTS: - virtual void openProjectForUrl( const QUrl &sourceUrl ) override; + void openProjectForUrl( const QUrl &sourceUrl ) override; virtual void fetchProject(); - virtual void openProject( const QUrl &KDev4ProjectFile = QUrl() ) override; + void openProject( const QUrl &KDev4ProjectFile = QUrl() ) override; virtual void abortOpeningProject( IProject* ); void projectImportingFinished( IProject* ); - virtual void closeProject( IProject* ) override; - virtual void configureProject( IProject* ) override; + void closeProject( IProject* ) override; + void configureProject( IProject* ) override; - virtual void reparseProject( IProject* project, bool forceUpdate = false ) override; + void reparseProject( IProject* project, bool forceUpdate = false ) override; void eventuallyOpenProjectFile(KIO::Job*,KIO::UDSEntryList); void openProjectForUrlSlot(bool); // void changeCurrentProject( ProjectBaseItem* ); void openProjects(const QList& projects); void commitCurrentProject(); // Maps the given path from the source to the equivalent path within the build directory // of the corresponding project. If the path is already in the build directory and fallbackRoot is true, // then it is mapped to the root of the build directory. // If reverse is true, maps the opposite direction, from build to source. [ Used in kdevplatform_shell_environment.sh ] Q_SCRIPTABLE QString mapSourceBuild( const QString& path, bool reverse = false, bool fallbackRoot = true ) const; protected: virtual void loadSettings( bool projectIsLoaded ); virtual void saveSettings( bool projectIsLoaded ); virtual void initialize(); private: //FIXME Do not load all of this just for the project being opened... //void legacyLoading(); void setupActions(); void cleanup(); // helper methods for closeProject() void unloadUnusedProjectPlugins(IProject* proj); void disableProjectCloseAction(); void closeAllOpenedFiles(IProject* proj); void initializePluginCleanup(IProject* proj); private: Q_PRIVATE_SLOT(d, void projectConfig( QObject* ) ) Q_PRIVATE_SLOT(d, void unloadAllProjectPlugins() ) Q_PRIVATE_SLOT(d, void updateActionStates( KDevelop::Context* ) ) Q_PRIVATE_SLOT(d, void closeSelectedProjects() ) Q_PRIVATE_SLOT(d, void openProjectConfig() ) Q_PRIVATE_SLOT(d, void areaChanged(Sublime::Area*) ) class ProjectControllerPrivate* const d; friend class ProjectControllerPrivate; }; class ProjectDialogProvider : public IProjectDialogProvider { Q_OBJECT public: explicit ProjectDialogProvider(ProjectControllerPrivate* const p); - virtual ~ProjectDialogProvider(); + ~ProjectDialogProvider() override; ProjectControllerPrivate* const d; public Q_SLOTS: - virtual QUrl askProjectConfigLocation(bool fetch, const QUrl& sta) override; - virtual bool userWantsReopen() override; + QUrl askProjectConfigLocation(bool fetch, const QUrl& sta) override; + bool userWantsReopen() override; }; } #endif diff --git a/shell/projectinfopage.h b/shell/projectinfopage.h index 45b374a830..f78f4bbba3 100644 --- a/shell/projectinfopage.h +++ b/shell/projectinfopage.h @@ -1,43 +1,43 @@ /*************************************************************************** * Copyright (C) 2008 by Andreas Pakulat namespace Ui { class ProjectInfoPage; } namespace KDevelop { class ProjectInfoPage : public QWidget { Q_OBJECT public: explicit ProjectInfoPage( QWidget* parent = 0 ); - virtual ~ProjectInfoPage(); + ~ProjectInfoPage() override; void setProjectName( const QString& ); void setProjectManager( const QString& ); signals: void projectNameChanged( const QString& ); void projectManagerChanged( const QString& ); private slots: void changeProjectManager( int ); private: Ui::ProjectInfoPage* page_ui; }; } #endif diff --git a/shell/projectsourcepage.h b/shell/projectsourcepage.h index a2700d1cc2..e1d13938a9 100644 --- a/shell/projectsourcepage.h +++ b/shell/projectsourcepage.h @@ -1,65 +1,65 @@ /*************************************************************************** * Copyright (C) 2010 by Aleix Pol Gonzalez * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_PROJECTSOURCEPAGE_H #define KDEVPLATFORM_PROJECTSOURCEPAGE_H #include class KJob; class QUrl; namespace Ui { class ProjectSourcePage; } namespace KDevelop { class VcsJob; class IProjectProvider; class IProjectProviderWidget; class IPlugin; class IBasicVersionControl; class VcsLocationWidget; class ProjectSourcePage : public QWidget { Q_OBJECT public: explicit ProjectSourcePage(const QUrl& initial, QWidget* parent = 0); - virtual ~ProjectSourcePage(); + ~ProjectSourcePage() override; QUrl workingDir() const; private slots: void setSourceIndex(int index); void checkoutVcsProject(); void projectReceived(KJob* job); void reevaluateCorrection(); void progressChanged(KJob*, unsigned long); void infoMessage(KJob*, const QString& text, const QString& rich); void locationChanged(); void projectChanged(const QString& name); signals: void isCorrect(bool); private: void setStatus(const QString& message); void clearStatus(); KDevelop::IBasicVersionControl* vcsPerIndex(int index); KDevelop::IProjectProvider* providerPerIndex(int index); KDevelop::VcsJob* jobPerCurrent(); Ui::ProjectSourcePage* m_ui; QList m_plugins; KDevelop::VcsLocationWidget* m_locationWidget; KDevelop::IProjectProviderWidget* m_providerWidget; }; } #endif // KDEVPLATFORM_PROJECTSOURCEPAGE_H diff --git a/shell/runcontroller.cpp b/shell/runcontroller.cpp index a8b6cd0342..0487fbeb02 100644 --- a/shell/runcontroller.cpp +++ b/shell/runcontroller.cpp @@ -1,1027 +1,1027 @@ /* This file is part of KDevelop Copyright 2007-2008 Hamish Rodda Copyright 2008 Aleix Pol 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 "runcontroller.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "core.h" #include "plugincontroller.h" #include "uicontroller.h" #include "projectcontroller.h" #include "mainwindow.h" #include "launchconfiguration.h" #include "launchconfigurationdialog.h" #include "debug.h" #include #include #include #include using namespace KDevelop; namespace { namespace Strings { QString LaunchConfigurationsGroup() { return QStringLiteral("Launch"); } QString LaunchConfigurationsListEntry() { return QStringLiteral("Launch Configurations"); } QString CurrentLaunchConfigProjectEntry() { return QStringLiteral("Current Launch Config Project"); } QString CurrentLaunchConfigNameEntry() { return QStringLiteral("Current Launch Config GroupName"); } QString ConfiguredFromProjectItemEntry() { return QStringLiteral("Configured from ProjectItem"); } } } typedef QPair Target; Q_DECLARE_METATYPE(Target) //TODO: Doesn't handle add/remove of launch configs in the dialog or renaming of configs //TODO: Doesn't auto-select launch configs opened from projects class DebugMode : public ILaunchMode { public: DebugMode() {} - virtual QIcon icon() const override { return QIcon::fromTheme("tools-report-bug"); } - virtual QString id() const override { return "debug"; } - virtual QString name() const override { return i18n("Debug"); } + QIcon icon() const override { return QIcon::fromTheme("tools-report-bug"); } + QString id() const override { return "debug"; } + QString name() const override { return i18n("Debug"); } }; class ProfileMode : public ILaunchMode { public: ProfileMode() {} - virtual QIcon icon() const override { return QIcon::fromTheme("office-chart-area"); } - virtual QString id() const override { return "profile"; } - virtual QString name() const override { return i18n("Profile"); } + QIcon icon() const override { return QIcon::fromTheme("office-chart-area"); } + QString id() const override { return "profile"; } + QString name() const override { return i18n("Profile"); } }; class ExecuteMode : public ILaunchMode { public: ExecuteMode() {} - virtual QIcon icon() const override { return QIcon::fromTheme("system-run"); } - virtual QString id() const override { return "execute"; } - virtual QString name() const override { return i18n("Execute"); } + QIcon icon() const override { return QIcon::fromTheme("system-run"); } + QString id() const override { return "execute"; } + QString name() const override { return i18n("Execute"); } }; class RunController::RunControllerPrivate { public: QItemDelegate* delegate; IRunController::State state; RunController* q; QHash jobs; QAction* stopAction; KActionMenu* stopJobsMenu; QAction* runAction; QAction* dbgAction; KSelectAction* currentTargetAction; QMap launchConfigurationTypes; QList launchConfigurations; QMap launchModes; QSignalMapper* launchChangeMapper; QSignalMapper* launchAsMapper; QMap > launchAsInfo; KDevelop::ProjectBaseItem* contextItem; DebugMode* debugMode; ExecuteMode* executeMode; ProfileMode* profileMode; bool hasLaunchConfigType( const QString& typeId ) { return launchConfigurationTypes.contains( typeId ); } void saveCurrentLaunchAction() { if (!currentTargetAction) return; if( currentTargetAction->currentAction() ) { KConfigGroup grp = Core::self()->activeSession()->config()->group( Strings::LaunchConfigurationsGroup() ); LaunchConfiguration* l = static_cast( currentTargetAction->currentAction()->data().value() ); grp.writeEntry( Strings::CurrentLaunchConfigProjectEntry(), l->project() ? l->project()->name() : "" ); grp.writeEntry( Strings::CurrentLaunchConfigNameEntry(), l->configGroupName() ); grp.sync(); } } void configureLaunches() { LaunchConfigurationDialog dlg; dlg.exec(); } QString launchActionText( LaunchConfiguration* l ) { QString label; if( l->project() ) { label = QStringLiteral("%1 : %2").arg( l->project()->name()).arg(l->name()); } else { label = l->name(); } return label; } void launchAs( int id ) { //qCDebug(SHELL) << "Launching id:" << id; QPair info = launchAsInfo[id]; //qCDebug(SHELL) << "fetching type and mode:" << info.first << info.second; LaunchConfigurationType* type = launchConfigurationTypeForId( info.first ); ILaunchMode* mode = q->launchModeForId( info.second ); //qCDebug(SHELL) << "got mode and type:" << type << type->id() << mode << mode->id(); if( type && mode ) { ILauncher* launcher = 0; foreach (ILauncher *l, type->launchers()) { //qCDebug(SHELL) << "available launcher" << l << l->id() << l->supportedModes(); if (l->supportedModes().contains(mode->id())) { launcher = l; break; } } if (launcher) { QStringList itemPath = Core::self()->projectController()->projectModel()->pathFromIndex(contextItem->index()); ILaunchConfiguration* ilaunch = 0; foreach (LaunchConfiguration *l, launchConfigurations) { QStringList path = l->config().readEntry(Strings::ConfiguredFromProjectItemEntry(), QStringList()); if (l->type() == type && path == itemPath) { qCDebug(SHELL) << "already generated ilaunch" << path; ilaunch = l; break; } } if (!ilaunch) { ilaunch = q->createLaunchConfiguration( type, qMakePair( mode->id(), launcher->id() ), contextItem->project(), contextItem->text() ); LaunchConfiguration* launch = dynamic_cast( ilaunch ); type->configureLaunchFromItem( launch->config(), contextItem ); launch->config().writeEntry(Strings::ConfiguredFromProjectItemEntry(), itemPath); //qCDebug(SHELL) << "created config, launching"; } else { //qCDebug(SHELL) << "reusing generated config, launching"; } q->setDefaultLaunch(ilaunch); q->execute( mode->id(), ilaunch ); } } } void updateCurrentLaunchAction() { if (!currentTargetAction) return; KConfigGroup launchGrp = Core::self()->activeSession()->config()->group( Strings::LaunchConfigurationsGroup() ); QString currentLaunchProject = launchGrp.readEntry( Strings::CurrentLaunchConfigProjectEntry(), "" ); QString currentLaunchName = launchGrp.readEntry( Strings::CurrentLaunchConfigNameEntry(), "" ); LaunchConfiguration* l = 0; if( currentTargetAction->currentAction() ) { l = static_cast( currentTargetAction->currentAction()->data().value() ); } else if( !launchConfigurations.isEmpty() ) { l = launchConfigurations.at( 0 ); } if( l && ( ( !currentLaunchProject.isEmpty() && ( !l->project() || l->project()->name() != currentLaunchProject ) ) || l->configGroupName() != currentLaunchName ) ) { foreach( QAction* a, currentTargetAction->actions() ) { LaunchConfiguration* l = static_cast( qvariant_cast( a->data() ) ); if( currentLaunchName == l->configGroupName() && ( ( currentLaunchProject.isEmpty() && !l->project() ) || ( l->project() && l->project()->name() == currentLaunchProject ) ) ) { a->setChecked( true ); break; } } } if( !currentTargetAction->currentAction() ) { qCDebug(SHELL) << "oops no current action, using first if list is non-empty"; if( !currentTargetAction->actions().isEmpty() ) { currentTargetAction->actions().first()->setChecked( true ); } } } void addLaunchAction( LaunchConfiguration* l ) { if (!currentTargetAction) return; QAction* action = currentTargetAction->addAction(launchActionText( l )); action->setData(qVariantFromValue(l)); } void readLaunchConfigs( KSharedConfigPtr cfg, IProject* prj ) { KConfigGroup group(cfg, Strings::LaunchConfigurationsGroup()); QStringList configs = group.readEntry( Strings::LaunchConfigurationsListEntry(), QStringList() ); foreach( const QString& cfg, configs ) { KConfigGroup grp = group.group( cfg ); if( launchConfigurationTypeForId( grp.readEntry( LaunchConfiguration::LaunchConfigurationTypeEntry(), "" ) ) ) { q->addLaunchConfiguration( new LaunchConfiguration( grp, prj ) ); } } } LaunchConfigurationType* launchConfigurationTypeForId( const QString& id ) { QMap::iterator it = launchConfigurationTypes.find( id ); if( it != launchConfigurationTypes.end() ) { return it.value(); } else { qWarning() << "couldn't find type for id:" << id << ". Known types:" << launchConfigurationTypes.keys(); } return 0; } }; RunController::RunController(QObject *parent) : IRunController(parent) , d(new RunControllerPrivate) { setObjectName("RunController"); QDBusConnection::sessionBus().registerObject("/org/kdevelop/RunController", this, QDBusConnection::ExportScriptableSlots); // TODO: need to implement compile only if needed before execute // TODO: need to implement abort all running programs when project closed d->currentTargetAction = 0; d->state = Idle; d->q = this; d->delegate = new RunDelegate(this); d->launchChangeMapper = new QSignalMapper( this ); d->launchAsMapper = 0; d->contextItem = 0; d->executeMode = 0; d->debugMode = 0; d->profileMode = 0; if(!(Core::self()->setupFlags() & Core::NoUi)) { // Note that things like registerJob() do not work without the actions, it'll simply crash. setupActions(); } } RunController::~RunController() { delete d; } void KDevelop::RunController::launchChanged( LaunchConfiguration* l ) { foreach( QAction* a, d->currentTargetAction->actions() ) { if( static_cast( a->data().value() ) == l ) { a->setText( d->launchActionText( l ) ); break; } } } void RunController::cleanup() { delete d->executeMode; d->executeMode = 0; delete d->profileMode; d->profileMode = 0; delete d->debugMode; d->debugMode = 0; stopAllProcesses(); d->saveCurrentLaunchAction(); } void RunController::initialize() { d->executeMode = new ExecuteMode(); addLaunchMode( d->executeMode ); d->profileMode = new ProfileMode(); addLaunchMode( d->profileMode ); d->debugMode = new DebugMode; addLaunchMode( d->debugMode ); d->readLaunchConfigs( Core::self()->activeSession()->config(), 0 ); foreach (IProject* project, Core::self()->projectController()->projects()) { slotProjectOpened(project); } connect(Core::self()->projectController(), &IProjectController::projectOpened, this, &RunController::slotProjectOpened); connect(Core::self()->projectController(), &IProjectController::projectClosing, this, &RunController::slotProjectClosing); connect(Core::self()->projectController(), &IProjectController::projectConfigurationChanged, this, &RunController::slotRefreshProject); if( (Core::self()->setupFlags() & Core::NoUi) == 0 ) { // Only do this in GUI mode d->updateCurrentLaunchAction(); } } KJob* RunController::execute(const QString& runMode, ILaunchConfiguration* launch) { if( !launch ) { qCDebug(SHELL) << "execute called without launch config!"; return 0; } LaunchConfiguration *run = dynamic_cast(launch); //TODO: Port to launch framework, probably needs to be part of the launcher //if(!run.dependencies().isEmpty()) // ICore::self()->documentController()->saveAllDocuments(IDocument::Silent); //foreach(KJob* job, run.dependencies()) //{ // jobs.append(job); //} qCDebug(SHELL) << "mode:" << runMode; QString launcherId = run->launcherForMode( runMode ); qCDebug(SHELL) << "launcher id:" << launcherId; ILauncher* launcher = run->type()->launcherForId( launcherId ); if( !launcher ) { KMessageBox::error( qApp->activeWindow(), i18n("The current launch configuration does not support the '%1' mode.", runMode), ""); return 0; } KJob* launchJob = launcher->start(runMode, run); registerJob(launchJob); return launchJob; } void RunController::setupActions() { QAction* action; // TODO not multi-window friendly, FIXME KActionCollection* ac = Core::self()->uiControllerInternal()->defaultMainWindow()->actionCollection(); action = new QAction(i18n("Configure Launches..."), this); ac->addAction("configure_launches", action); action->setMenuRole(QAction::NoRole); // OSX: Be explicit about role, prevent hiding due to conflict with "Preferences..." menu item action->setStatusTip(i18n("Open Launch Configuration Dialog")); action->setToolTip(i18nc("@info:tooltip", "Open Launch Configuration Dialog")); action->setWhatsThis(i18nc("@info:whatsthis", "Opens a dialog to setup new launch configurations, or to change the existing ones.")); connect(action, &QAction::triggered, this, [&] { d->configureLaunches(); }); d->runAction = new QAction( QIcon::fromTheme("system-run"), i18n("Execute Launch"), this); d->runAction->setIconText( i18nc("Short text for 'Execute launch' used in the toolbar", "Execute") ); ac->setDefaultShortcut( d->runAction, Qt::SHIFT + Qt::Key_F9); d->runAction->setToolTip(i18nc("@info:tooltip", "Execute current launch")); d->runAction->setStatusTip(i18n("Execute current launch")); d->runAction->setWhatsThis(i18nc("@info:whatsthis", "Executes the target or the program specified in currently active launch configuration.")); ac->addAction("run_execute", d->runAction); connect(d->runAction, &QAction::triggered, this, &RunController::slotExecute); d->dbgAction = new QAction( QIcon::fromTheme("debug-run"), i18n("Debug Launch"), this); ac->setDefaultShortcut( d->dbgAction, Qt::Key_F9); d->dbgAction->setIconText( i18nc("Short text for 'Debug launch' used in the toolbar", "Debug") ); d->dbgAction->setToolTip(i18nc("@info:tooltip", "Debug current launch")); d->dbgAction->setStatusTip(i18n("Debug current launch")); d->dbgAction->setWhatsThis(i18nc("@info:whatsthis", "Executes the target or the program specified in currently active launch configuration inside a Debugger.")); ac->addAction("run_debug", d->dbgAction); connect(d->dbgAction, &QAction::triggered, this, &RunController::slotDebug); Core::self()->uiControllerInternal()->area(0, "code")->addAction(d->dbgAction); // TODO: at least get a profile target, it's sad to have the menu entry without a profiler // QAction* profileAction = new QAction( QIcon::fromTheme(""), i18n("Profile Launch"), this); // profileAction->setToolTip(i18nc("@info:tooltip", "Profile current launch")); // profileAction->setStatusTip(i18n("Profile current launch")); // profileAction->setWhatsThis(i18nc("@info:whatsthis", "Executes the target or the program specified in currently active launch configuration inside a Profiler.")); // ac->addAction("run_profile", profileAction); // connect(profileAction, SIGNAL(triggered(bool)), this, SLOT(slotProfile())); action = d->stopAction = new QAction( QIcon::fromTheme("process-stop"), i18n("Stop All Jobs"), this); action->setIconText(i18nc("Short text for 'Stop All Jobs' used in the toolbar", "Stop All")); // Ctrl+Escape would be nicer, but thats taken by the ksysguard desktop shortcut ac->setDefaultShortcut( action, QKeySequence("Ctrl+Shift+Escape")); action->setToolTip(i18nc("@info:tooltip", "Stop all currently running jobs")); action->setWhatsThis(i18nc("@info:whatsthis", "Requests that all running jobs are stopped.")); action->setEnabled(false); ac->addAction("run_stop_all", action); connect(action, &QAction::triggered, this, &RunController::stopAllProcesses); Core::self()->uiControllerInternal()->area(0, "debug")->addAction(action); action = d->stopJobsMenu = new KActionMenu( QIcon::fromTheme("process-stop"), i18n("Stop"), this); action->setIconText(i18nc("Short text for 'Stop' used in the toolbar", "Stop")); action->setToolTip(i18nc("@info:tooltip", "Menu allowing to stop individual jobs")); action->setWhatsThis(i18nc("@info:whatsthis", "List of jobs that can be stopped individually.")); action->setEnabled(false); ac->addAction("run_stop_menu", action); d->currentTargetAction = new KSelectAction( i18n("Current Launch Configuration"), this); d->currentTargetAction->setToolTip(i18nc("@info:tooltip", "Current launch configuration")); d->currentTargetAction->setStatusTip(i18n("Current launch Configuration")); d->currentTargetAction->setWhatsThis(i18nc("@info:whatsthis", "Select which launch configuration to run when run is invoked.")); ac->addAction("run_default_target", d->currentTargetAction); } LaunchConfigurationType* RunController::launchConfigurationTypeForId( const QString& id ) { return d->launchConfigurationTypeForId( id ); } void KDevelop::RunController::slotProjectOpened(KDevelop::IProject * project) { d->readLaunchConfigs( project->projectConfiguration(), project ); d->updateCurrentLaunchAction(); } void KDevelop::RunController::slotProjectClosing(KDevelop::IProject * project) { if (!d->currentTargetAction) return; foreach (QAction* action, d->currentTargetAction->actions()) { LaunchConfiguration* l = static_cast(qvariant_cast(action->data())); if ( project == l->project() ) { l->save(); d->launchConfigurations.removeAll(l); delete l; bool wasSelected = action->isChecked(); delete action; if (wasSelected && !d->currentTargetAction->actions().isEmpty()) d->currentTargetAction->actions().first()->setChecked(true); } } } void KDevelop::RunController::slotRefreshProject(KDevelop::IProject* project) { slotProjectClosing(project); slotProjectOpened(project); } void RunController::slotDebug() { if(d->launchConfigurations.isEmpty()) { LaunchConfigurationDialog d; d.exec(); } if(!d->launchConfigurations.isEmpty()) executeDefaultLaunch( "debug" ); } void RunController::slotProfile() { if(d->launchConfigurations.isEmpty()) { LaunchConfigurationDialog d; d.exec(); } if(!d->launchConfigurations.isEmpty()) executeDefaultLaunch( "profile" ); } void RunController::slotExecute() { if(d->launchConfigurations.isEmpty()) { LaunchConfigurationDialog d; d.exec(); } if(!d->launchConfigurations.isEmpty()) executeDefaultLaunch( "execute" ); } LaunchConfiguration* KDevelop::RunController::defaultLaunch() const { QAction* projectAction = d->currentTargetAction->currentAction(); if( projectAction ) return static_cast(qvariant_cast(projectAction->data())); return 0; } void KDevelop::RunController::registerJob(KJob * job) { if (!job) return; if (!(job->capabilities() & KJob::Killable)) { // see e.g. https://bugs.kde.org/show_bug.cgi?id=314187 qWarning() << "non-killable job" << job << "registered - this might lead to crashes on shutdown."; } if (!d->jobs.contains(job)) { QAction* stopJobAction = 0; if (Core::self()->setupFlags() != Core::NoUi) { stopJobAction = new QAction(job->objectName().isEmpty() ? i18n("<%1> Unnamed job", job->staticMetaObject.className()) : job->objectName(), this); stopJobAction->setData(QVariant::fromValue(static_cast(job))); d->stopJobsMenu->addAction(stopJobAction); connect (stopJobAction, &QAction::triggered, this, &RunController::slotKillJob); job->setUiDelegate( new KDialogJobUiDelegate() ); } d->jobs.insert(job, stopJobAction); connect( job, &KJob::finished, this, &RunController::finished ); connect( job, &KJob::destroyed, this, &RunController::jobDestroyed ); IRunController::registerJob(job); emit jobRegistered(job); } job->start(); checkState(); } void KDevelop::RunController::unregisterJob(KJob * job) { IRunController::unregisterJob(job); Q_ASSERT(d->jobs.contains(job)); // Delete the stop job action QAction *action = d->jobs.take(job); if (action) action->deleteLater(); checkState(); emit jobUnregistered(job); } void KDevelop::RunController::checkState() { bool running = false; foreach (KJob* job, d->jobs.keys()) { if (!job->isSuspended()) { running = true; break; } } if ( ( d->state != Running ? false : true ) == running ) { d->state = running ? Running : Idle; emit runStateChanged(d->state); } if (Core::self()->setupFlags() != Core::NoUi) { d->stopAction->setEnabled(running); d->stopJobsMenu->setEnabled(running); } } void KDevelop::RunController::stopAllProcesses() { // composite jobs might remove child jobs, see also: // https://bugs.kde.org/show_bug.cgi?id=258904 // foreach already iterates over a copy foreach (KJob* job, d->jobs.keys()) { // now we check the real list whether it was deleted if (!d->jobs.contains(job)) continue; if (job->capabilities() & KJob::Killable) { job->kill(KJob::EmitResult); } else { qWarning() << "cannot stop non-killable job: " << job; } } } void KDevelop::RunController::slotKillJob() { QAction* action = dynamic_cast(sender()); Q_ASSERT(action); KJob* job = static_cast(qvariant_cast(action->data())); if (job->capabilities() & KJob::Killable) job->kill(); } void KDevelop::RunController::finished(KJob * job) { unregisterJob(job); switch (job->error()) { case KJob::NoError: case KJob::KilledJobError: case OutputJob::FailedShownError: break; default: { ///WARNING: do *not* use a nested event loop here, it might cause /// random crashes later on, see e.g.: /// https://bugs.kde.org/show_bug.cgi?id=309811 auto dialog = new QDialog(qApp->activeWindow()); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setWindowTitle(i18n("Process Error")); auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Close, dialog); KMessageBox::createKMessageBox(dialog, buttonBox, QMessageBox::Warning, job->errorString(), QStringList(), QString(), 0, KMessageBox::NoExec); dialog->show(); } } } void RunController::jobDestroyed(QObject* job) { KJob* kjob = static_cast(job); if (d->jobs.contains(kjob)) { qWarning() << "job destroyed without emitting finished signal!"; unregisterJob(kjob); } } void KDevelop::RunController::suspended(KJob * job) { Q_UNUSED(job); checkState(); } void KDevelop::RunController::resumed(KJob * job) { Q_UNUSED(job); checkState(); } QList< KJob * > KDevelop::RunController::currentJobs() const { return d->jobs.keys(); } QList RunController::launchConfigurations() const { QList configs; foreach (LaunchConfiguration *config, launchConfigurationsInternal()) configs << config; return configs; } QList RunController::launchConfigurationsInternal() const { return d->launchConfigurations; } QList RunController::launchConfigurationTypes() const { return d->launchConfigurationTypes.values(); } void RunController::addConfigurationType( LaunchConfigurationType* type ) { if( !d->launchConfigurationTypes.contains( type->id() ) ) { d->launchConfigurationTypes.insert( type->id(), type ); } } void RunController::removeConfigurationType( LaunchConfigurationType* type ) { foreach( LaunchConfiguration* l, d->launchConfigurations ) { if( l->type() == type ) { d->launchConfigurations.removeAll( l ); delete l; } } d->launchConfigurationTypes.remove( type->id() ); } void KDevelop::RunController::addLaunchMode(KDevelop::ILaunchMode* mode) { if( !d->launchModes.contains( mode->id() ) ) { d->launchModes.insert( mode->id(), mode ); } } QList< KDevelop::ILaunchMode* > KDevelop::RunController::launchModes() const { return d->launchModes.values(); } void KDevelop::RunController::removeLaunchMode(KDevelop::ILaunchMode* mode) { d->launchModes.remove( mode->id() ); } KDevelop::ILaunchMode* KDevelop::RunController::launchModeForId(const QString& id) const { QMap::iterator it = d->launchModes.find( id ); if( it != d->launchModes.end() ) { return it.value(); } return 0; } void KDevelop::RunController::addLaunchConfiguration(KDevelop::LaunchConfiguration* l) { if( !d->launchConfigurations.contains( l ) ) { d->addLaunchAction( l ); d->launchConfigurations << l; if( !d->currentTargetAction->currentAction() ) { if( !d->currentTargetAction->actions().isEmpty() ) { d->currentTargetAction->actions().first()->setChecked( true ); } } connect( l, &LaunchConfiguration::nameChanged, this, &RunController::launchChanged ); } } void KDevelop::RunController::removeLaunchConfiguration(KDevelop::LaunchConfiguration* l) { KConfigGroup launcherGroup; if( l->project() ) { launcherGroup = l->project()->projectConfiguration()->group( Strings::LaunchConfigurationsGroup() ); } else { launcherGroup = Core::self()->activeSession()->config()->group( Strings::LaunchConfigurationsGroup() ); } QStringList configs = launcherGroup.readEntry( Strings::LaunchConfigurationsListEntry(), QStringList() ); configs.removeAll( l->configGroupName() ); launcherGroup.deleteGroup( l->configGroupName() ); launcherGroup.writeEntry( Strings::LaunchConfigurationsListEntry(), configs ); launcherGroup.sync(); foreach( QAction* a, d->currentTargetAction->actions() ) { if( static_cast( a->data().value() ) == l ) { bool wasSelected = a->isChecked(); d->currentTargetAction->removeAction( a ); if( wasSelected && !d->currentTargetAction->actions().isEmpty() ) { d->currentTargetAction->actions().first()->setChecked( true ); } break; } } d->launchConfigurations.removeAll( l ); delete l; } void KDevelop::RunController::executeDefaultLaunch(const QString& runMode) { auto dl = defaultLaunch(); if( !dl ) { qWarning() << "no default launch!"; return; } execute( runMode, dl ); } void RunController::setDefaultLaunch(ILaunchConfiguration* l) { foreach( QAction* a, d->currentTargetAction->actions() ) { if( static_cast( a->data().value() ) == l ) { a->setChecked(true); break; } } } bool launcherNameExists(const QString& name) { foreach(ILaunchConfiguration* config, Core::self()->runControllerInternal()->launchConfigurations()) { if(config->name()==name) return true; } return false; } QString makeUnique(const QString& name) { if(launcherNameExists(name)) { for(int i=2; ; i++) { QString proposed = QStringLiteral("%1 (%2)").arg(name).arg(i); if(!launcherNameExists(proposed)) { return proposed; } } } return name; } ILaunchConfiguration* RunController::createLaunchConfiguration ( LaunchConfigurationType* type, const QPair& launcher, IProject* project, const QString& name ) { KConfigGroup launchGroup; if( project ) { launchGroup = project->projectConfiguration()->group( Strings::LaunchConfigurationsGroup() ); } else { launchGroup = Core::self()->activeSession()->config()->group( Strings::LaunchConfigurationsGroup() ); } QStringList configs = launchGroup.readEntry( Strings::LaunchConfigurationsListEntry(), QStringList() ); uint num = 0; QString baseName = "Launch Configuration"; while( configs.contains( QStringLiteral( "%1 %2" ).arg( baseName ).arg( num ) ) ) { num++; } QString groupName = QStringLiteral( "%1 %2" ).arg( baseName ).arg( num ); KConfigGroup launchConfigGroup = launchGroup.group( groupName ); QString cfgName = name; if( name.isEmpty() ) { cfgName = i18n("New %1 Launcher", type->name() ); cfgName = makeUnique(cfgName); } launchConfigGroup.writeEntry(LaunchConfiguration::LaunchConfigurationNameEntry(), cfgName ); launchConfigGroup.writeEntry(LaunchConfiguration::LaunchConfigurationTypeEntry(), type->id() ); launchConfigGroup.sync(); configs << groupName; launchGroup.writeEntry( Strings::LaunchConfigurationsListEntry(), configs ); launchGroup.sync(); LaunchConfiguration* l = new LaunchConfiguration( launchConfigGroup, project ); l->setLauncherForMode( launcher.first, launcher.second ); Core::self()->runControllerInternal()->addLaunchConfiguration( l ); return l; } QItemDelegate * KDevelop::RunController::delegate() const { return d->delegate; } ContextMenuExtension RunController::contextMenuExtension ( Context* ctx ) { delete d->launchAsMapper; d->launchAsMapper = new QSignalMapper( this ); connect( d->launchAsMapper, static_cast(&QSignalMapper::mapped), this, [&] (int id) { d->launchAs(id); } ); d->launchAsInfo.clear(); d->contextItem = 0; ContextMenuExtension ext; if( ctx->type() == Context::ProjectItemContext ) { KDevelop::ProjectItemContext* prjctx = dynamic_cast( ctx ); if( prjctx->items().count() == 1 ) { ProjectBaseItem* itm = prjctx->items().at( 0 ); int i = 0; foreach( ILaunchMode* mode, d->launchModes.values() ) { KActionMenu* menu = new KActionMenu( i18n("%1 As...", mode->name() ), this ); foreach( LaunchConfigurationType* type, launchConfigurationTypes() ) { bool hasLauncher = false; foreach( ILauncher* launcher, type->launchers() ) { if( launcher->supportedModes().contains( mode->id() ) ) { hasLauncher = true; } } if( hasLauncher && type->canLaunch(itm) ) { d->launchAsInfo[i] = qMakePair( type->id(), mode->id() ); QAction* act = new QAction( d->launchAsMapper ); act->setText( type->name() ); qCDebug(SHELL) << "Setting up mapping for:" << i << "for action" << act->text() << "in mode" << mode->name(); d->launchAsMapper->setMapping( act, i ); connect( act, &QAction::triggered, d->launchAsMapper, static_cast(&QSignalMapper::map) ); menu->addAction(act); i++; } } if( menu->menu()->actions().count() > 0 ) { ext.addAction( ContextMenuExtension::RunGroup, menu); } } if( ext.actions( ContextMenuExtension::RunGroup ).count() > 0 ) { d->contextItem = itm; } } } return ext; } RunDelegate::RunDelegate( QObject* parent ) : QItemDelegate(parent), runProviderBrush( KColorScheme::View, KColorScheme::PositiveText ), errorBrush( KColorScheme::View, KColorScheme::NegativeText ) { } void RunDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const { QStyleOptionViewItem opt = option; QVariant status = index.data(Qt::UserRole+1); // if( status.isValid() && status.canConvert() ) // { // IRunProvider::OutputTypes type = status.value(); // if( type == IRunProvider::RunProvider ) // { // opt.palette.setBrush( QPalette::Text, runProviderBrush.brush( option.palette ) ); // } else if( type == IRunProvider::StandardError ) // { // opt.palette.setBrush( QPalette::Text, errorBrush.brush( option.palette ) ); // } // } QItemDelegate::paint(painter, opt, index); } #include "moc_runcontroller.cpp" diff --git a/shell/runcontroller.h b/shell/runcontroller.h index 189287e04c..7fecf68c6d 100644 --- a/shell/runcontroller.h +++ b/shell/runcontroller.h @@ -1,164 +1,164 @@ /* This file is part of KDevelop Copyright 2007-2008 Hamish Rodda 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 KDEVPLATFORM_RUNCONTROLLER_H #define KDEVPLATFORM_RUNCONTROLLER_H #include #include #include #include #include "shellexport.h" class QStyleOptionViewItem; class QPainter; class QModelIndex; class KStatefulBrush; namespace KDevelop { class Context; class ContextMenuExtension; class IPlugin; class IProject; class LaunchConfiguration; class LaunchConfigurationType; class KDEVPLATFORMSHELL_EXPORT RunController : public IRunController { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kdevelop.RunController") public: explicit RunController(QObject *parent); - ~RunController(); + ~RunController() override; - virtual void registerJob(KJob *job) override; - virtual void unregisterJob(KJob *job) override; - virtual QList currentJobs() const override; + void registerJob(KJob *job) override; + void unregisterJob(KJob *job) override; + QList currentJobs() const override; KJob* execute(const QString& launchMode, ILaunchConfiguration* launch) override; QList launchModes() const override; /** * @copydoc IRunController::addLaunchMode */ - virtual void addLaunchMode( ILaunchMode* mode ) override; + void addLaunchMode( ILaunchMode* mode ) override; /** * @copydoc IRunController::removeLaunchMode */ - virtual void removeLaunchMode( ILaunchMode* mode ) override; + void removeLaunchMode( ILaunchMode* mode ) override; /** * @copydoc IRunController::launchModeForId() */ - virtual KDevelop::ILaunchMode* launchModeForId(const QString& id) const override; + KDevelop::ILaunchMode* launchModeForId(const QString& id) const override; void initialize(); void cleanup(); QItemDelegate* delegate() const; void addLaunchConfiguration( LaunchConfiguration* l ); void removeLaunchConfiguration( LaunchConfiguration* l ); QList launchConfigurationsInternal() const; - virtual QList launchConfigurations() const override; + QList launchConfigurations() const override; /** * @copydoc IRunController::launchConfigurationTypes() */ - virtual QList launchConfigurationTypes() const override; + QList launchConfigurationTypes() const override; /** * @copydoc IRunController::addConfigurationType() */ - virtual void addConfigurationType( LaunchConfigurationType* type ) override; + void addConfigurationType( LaunchConfigurationType* type ) override; /** * @copydoc IRunController::removeConfigurationType() */ - virtual void removeConfigurationType( LaunchConfigurationType* type ) override; + void removeConfigurationType( LaunchConfigurationType* type ) override; /** * Find the launch configuration type for the given @p id. * @returns the launch configuration type having the id, or 0 if no such type is known */ LaunchConfigurationType* launchConfigurationTypeForId( const QString& ) override; - virtual ILaunchConfiguration* createLaunchConfiguration ( LaunchConfigurationType* type, + ILaunchConfiguration* createLaunchConfiguration ( LaunchConfigurationType* type, const QPair& launcher, IProject* project = 0, const QString& name = QString() ) override; void setDefaultLaunch(ILaunchConfiguration* l); LaunchConfiguration* defaultLaunch() const; ContextMenuExtension contextMenuExtension( KDevelop::Context* ctx ); public Q_SLOTS: - virtual Q_SCRIPTABLE void executeDefaultLaunch(const QString& runMode) override; + Q_SCRIPTABLE void executeDefaultLaunch(const QString& runMode) override; - virtual Q_SCRIPTABLE void stopAllProcesses() override; + Q_SCRIPTABLE void stopAllProcesses() override; protected Q_SLOTS: - virtual void finished(KJob *job) override; - virtual void suspended(KJob *job) override; - virtual void resumed(KJob *job) override; + void finished(KJob *job) override; + void suspended(KJob *job) override; + void resumed(KJob *job) override; private Q_SLOTS: void slotRefreshProject(KDevelop::IProject* project); void slotExecute(); void slotDebug(); void slotProfile(); void slotProjectOpened(KDevelop::IProject* project); void slotProjectClosing(KDevelop::IProject* project); void slotKillJob(); void launchChanged(LaunchConfiguration*); void jobDestroyed(QObject* job); private: void setupActions(); void checkState(); Q_PRIVATE_SLOT(d, void configureLaunches()) Q_PRIVATE_SLOT(d, void launchAs(int)) class RunControllerPrivate; RunControllerPrivate* const d; }; class RunDelegate : public QItemDelegate { Q_OBJECT public: explicit RunDelegate( QObject* = 0 ); void paint(QPainter*, const QStyleOptionViewItem&, const QModelIndex&) const override; private: KStatefulBrush runProviderBrush; KStatefulBrush errorBrush; }; } #endif diff --git a/shell/savedialog.h b/shell/savedialog.h index 804222014a..9243c0fe48 100644 --- a/shell/savedialog.h +++ b/shell/savedialog.h @@ -1,49 +1,49 @@ /* This file is part of the KDE project Copyright (C) 2002 Harald Fernengel Copyright (C) 2008 Hamish Rodda 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 KDEVPLATFORM_SAVEDIALOG_H #define KDEVPLATFORM_SAVEDIALOG_H #include class QListWidget; namespace KDevelop { class IDocument; class KSaveSelectDialog : public QDialog { Q_OBJECT public: KSaveSelectDialog( const QList& files, QWidget * parent ); - virtual ~KSaveSelectDialog(); + ~KSaveSelectDialog() override; private Q_SLOTS: void save(); private: QListWidget* m_listWidget; }; } #endif diff --git a/shell/selectioncontroller.h b/shell/selectioncontroller.h index d82ffce322..e95389a983 100644 --- a/shell/selectioncontroller.h +++ b/shell/selectioncontroller.h @@ -1,64 +1,64 @@ /* This file is part of KDevelop Copyright 2009 Andreas Pakulat 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 KDEVPLATFORM_SELECTIONCONTROLLER_H #define KDEVPLATFORM_SELECTIONCONTROLLER_H #include #include "shellexport.h" namespace KDevelop { class Context; /** * The main controller for running processes. */ class KDEVPLATFORMSHELL_EXPORT SelectionController : public ISelectionController { Q_OBJECT public: ///Constructor. explicit SelectionController(QObject *parent); - ~SelectionController(); + ~SelectionController() override; /** * Provides the current selection, note that this might be 0 */ - virtual Context* currentSelection() override; + Context* currentSelection() override; void initialize(); void cleanup(); public Q_SLOTS: /** * updates the current selection * @param context the new selection */ - virtual void updateSelection( Context* context ) override; + void updateSelection( Context* context ) override; private: class SelectionControllerPrivate* const d; }; } #endif // KDEVPLATFORM_SELECTIONCONTROLLER_H diff --git a/shell/session.h b/shell/session.h index 0dc1f1e69a..d227c9d33d 100644 --- a/shell/session.h +++ b/shell/session.h @@ -1,89 +1,89 @@ /* This file is part of KDevelop Copyright 2008 Andreas Pakulat 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 KDEVPLATFORM_SESSION_H #define KDEVPLATFORM_SESSION_H #include "shellexport.h" #include #include #include #include #include namespace KDevelop { struct SessionInfo { QString name; QUuid uuid; QString description; QList projects; QString path; KSharedConfigPtr config; }; class KDEVPLATFORMSHELL_EXPORT Session : public ISession { Q_OBJECT public: static const QString cfgSessionNameEntry; static const QString cfgSessionDescriptionEntry; static const QString cfgSessionProjectsEntry; static const QString cfgSessionOptionsGroup; explicit Session( const QString& id, QObject * parent = 0 ); - virtual ~Session(); + ~Session() override; - virtual QUrl pluginDataArea( const IPlugin* ) override; - virtual KSharedConfigPtr config() override; + QUrl pluginDataArea( const IPlugin* ) override; + KSharedConfigPtr config() override; - virtual QList containedProjects() const override; - virtual void setContainedProjects( const QList& projects ) override; + QList containedProjects() const override; + void setContainedProjects( const QList& projects ) override; - virtual QString name() const override; + QString name() const override; void setName( const QString& ); - virtual QUuid id() const override; + QUuid id() const override; - virtual QString description() const override; + QString description() const override; - virtual bool isTemporary() const override; - virtual void setTemporary(bool temp) override; + bool isTemporary() const override; + void setTemporary(bool temp) override; QString path() const; /** * Generates a @ref SessionInfo by a session @p id. * @param mkdir Whether to create a session directory if one does not exist. */ static SessionInfo parse( const QString& id, bool mkdir = false ); private: class SessionPrivate* const d; friend class SessionPrivate; }; } Q_DECLARE_METATYPE( KDevelop::Session* ) #endif diff --git a/shell/sessioncontroller.cpp b/shell/sessioncontroller.cpp index 1dfa2da481..58433de411 100644 --- a/shell/sessioncontroller.cpp +++ b/shell/sessioncontroller.cpp @@ -1,684 +1,684 @@ /* This file is part of KDevelop Copyright 2008 Andreas Pakulat Copyright 2010 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 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 "sessioncontroller.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "session.h" #include "core.h" #include "uicontroller.h" #include "sessiondialog.h" #include "shellextension.h" #include "sessionlock.h" #include "sessionchooserdialog.h" #include "debug.h" #include #include #include #include #include namespace KDevelop { namespace { int argc = 0; char** argv = 0; }; void SessionController::setArguments(int _argc, char** _argv) { argc = _argc; argv = _argv; } static QStringList standardArguments() { QStringList ret; for(int a = 0; a < argc; ++a) { QString arg = QString::fromLocal8Bit(argv[a]); if(arg.startsWith("-graphicssystem") || arg.startsWith("-style")) { ret << '-' + arg; if(a+1 < argc) ret << QString::fromLocal8Bit(argv[a+1]); } } return ret; } class SessionControllerPrivate : public QObject { Q_OBJECT public: SessionControllerPrivate( SessionController* s ) : q(s) , activeSession(0) , grp(0) { } - ~SessionControllerPrivate() { + ~SessionControllerPrivate() override { } Session* findSessionForName( const QString& name ) const { foreach( Session* s, sessionActions.keys() ) { if( s->name() == name ) return s; } return 0; } Session* findSessionForId(QString idString) { QUuid id(idString); foreach( Session* s, sessionActions.keys() ) { if( s->id() == id) return s; } return 0; } void newSession() { qsrand(QDateTime::currentDateTime().toTime_t()); Session* session = new Session( QUuid::createUuid().toString() ); KProcess::startDetached(ShellExtension::getInstance()->binaryPath(), QStringList() << "-s" << session->id().toString() << standardArguments()); delete session; #if 0 //Terminate this instance of kdevelop if the user agrees foreach(Sublime::MainWindow* window, Core::self()->uiController()->controller()->mainWindows()) window->close(); #endif } void configureSessions() { SessionDialog dlg(ICore::self()->uiController()-> activeMainWindow()); dlg.exec(); } void deleteCurrentSession() { int choice = KMessageBox::warningContinueCancel(Core::self()->uiController()->activeMainWindow(), i18n("The current session and all contained settings will be deleted. The projects will stay unaffected. Do you really want to continue?")); if(choice == KMessageBox::Continue) { q->deleteSessionFromDisk(sessionLock); q->emitQuitSession(); } } void renameSession() { QDialog dialog; dialog.setWindowTitle(i18n("Rename Session")); auto mainLayout = new QVBoxLayout(&dialog); QGroupBox box; QHBoxLayout layout(&box); box.setTitle(i18n("New Session Name")); QLineEdit edit; layout.addWidget(&edit); mainLayout->addWidget(&box); auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); auto okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return); connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); mainLayout->addWidget(buttonBox); edit.setText(q->activeSession()->name()); edit.setFocus(); if(dialog.exec() == QDialog::Accepted) { static_cast(q->activeSession())->setName(edit.text()); } } bool loadSessionExternally( Session* s ) { Q_ASSERT( s ); KProcess::startDetached(ShellExtension::getInstance()->binaryPath(), QStringList() << "-s" << s->id().toString() << standardArguments()); return true; } TryLockSessionResult activateSession( Session* s ) { Q_ASSERT( s ); activeSession = s; TryLockSessionResult result = SessionController::tryLockSession( s->id().toString()); if( !result.lock ) { activeSession = 0; return result; } Q_ASSERT(s->id().toString() == result.lock->id()); sessionLock = result.lock; KConfigGroup grp = KSharedConfig::openConfig()->group( SessionController::cfgSessionGroup() ); grp.writeEntry( SessionController::cfgActiveSessionEntry(), s->id().toString() ); grp.sync(); if (Core::self()->setupFlags() & Core::NoUi) return result; QHash::iterator it = sessionActions.find(s); Q_ASSERT( it != sessionActions.end() ); (*it)->setCheckable(true); (*it)->setChecked(true); for(it = sessionActions.begin(); it != sessionActions.end(); ++it) { if(it.key() != s) (*it)->setCheckable(false); } return result; } void loadSessionFromAction( QAction* a ) { foreach( Session* s, sessionActions.keys() ) { if( s->id() == QUuid( a->data().toString() ) && s != activeSession ) { loadSessionExternally( s ); break; } } } void addSession( Session* s ) { if (Core::self()->setupFlags() & Core::NoUi) { sessionActions[s] = 0; return; } QAction* a = new QAction( grp ); a->setText( s->description() ); a->setCheckable( false ); a->setData( s->id().toString() ); sessionActions[s] = a; q->actionCollection()->addAction( "session_"+s->id().toString(), a ); q->unplugActionList( "available_sessions" ); q->plugActionList( "available_sessions", grp->actions() ); connect( s, &Session::sessionUpdated, this, &SessionControllerPrivate::sessionUpdated ); sessionUpdated( s ); } SessionController* q; QHash sessionActions; ISession* activeSession; QActionGroup* grp; ISessionLock::Ptr sessionLock; static QString sessionBaseDirectory() { return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +'/'+ qApp->applicationName() + "/sessions/"; } QString ownSessionDirectory() const { Q_ASSERT(activeSession); return q->sessionDirectory( activeSession->id().toString() ); } private slots: void sessionUpdated( KDevelop::ISession* s ) { sessionActions[static_cast( s )]->setText( KStringHandler::rsqueeze(s->description()) ); } }; SessionController::SessionController( QObject *parent ) : QObject( parent ), d(new SessionControllerPrivate(this)) { setObjectName("SessionController"); setComponentName(QStringLiteral("kdevsession"), QStringLiteral("KDevSession")); setXMLFile("kdevsessionui.rc"); QDBusConnection::sessionBus().registerObject( "/org/kdevelop/SessionController", this, QDBusConnection::ExportScriptableSlots ); if (Core::self()->setupFlags() & Core::NoUi) return; QAction* action = actionCollection()->addAction( "new_session", this, SLOT(newSession()) ); action->setText( i18nc("@action:inmenu", "Start New Session") ); action->setToolTip( i18nc("@info:tooltip", "Start a new KDevelop instance with an empty session") ); action->setIcon(QIcon::fromTheme("window-new")); action = actionCollection()->addAction( "rename_session", this, SLOT(renameSession()) ); action->setText( i18n("Rename Current Session...") ); action->setIcon(QIcon::fromTheme("edit-rename")); action = actionCollection()->addAction( "delete_session", this, SLOT(deleteCurrentSession()) ); action->setText( i18n("Delete Current Session...") ); action->setIcon(QIcon::fromTheme("edit-delete")); action = actionCollection()->addAction( "quit", this, SIGNAL(quitSession()) ); action->setText( i18n("Quit") ); action->setMenuRole( QAction::NoRole ); // OSX: prevent QT from hiding this due to conflict with 'Quit KDevelop...' actionCollection()->setDefaultShortcut( action, Qt::CTRL | Qt::Key_Q ); action->setIcon(QIcon::fromTheme("application-exit")); #if 0 action = actionCollection()->addAction( "configure_sessions", this, SLOT(configureSessions()) ); action->setText( i18n("Configure Sessions...") ); action->setToolTip( i18n("Create/Delete/Activate Sessions") ); action->setWhatsThis( i18n( "Shows a dialog to Create/Delete Sessions and set a new active session." ) ); #endif d->grp = new QActionGroup( this ); connect( d->grp, &QActionGroup::triggered, this, [&] (QAction* a) { d->loadSessionFromAction(a); } ); } SessionController::~SessionController() { delete d; } void SessionController::startNewSession() { d->newSession(); } void SessionController::cleanup() { if (d->activeSession) { Q_ASSERT(d->activeSession->id().toString() == d->sessionLock->id()); if (d->activeSession->isTemporary()) { deleteSessionFromDisk(d->sessionLock); } d->activeSession = 0; } d->sessionLock.clear(); qDeleteAll(d->sessionActions); d->sessionActions.clear(); } void SessionController::initialize( const QString& session ) { QDir sessiondir( SessionControllerPrivate::sessionBaseDirectory() ); foreach( const QString& s, sessiondir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot ) ) { QUuid id( s ); if( id.isNull() ) continue; // Only create sessions for directories that represent proper uuid's Session* ses = new Session( id.toString(), this ); //Delete sessions that have no name and are empty if( ses->containedProjects().isEmpty() && ses->name().isEmpty() && (session.isEmpty() || (ses->id().toString() != session && ses->name() != session)) ) { TryLockSessionResult result = tryLockSession(s); if (result.lock) { deleteSessionFromDisk(result.lock); } delete ses; } else { d->addSession( ses ); } } loadDefaultSession( session ); } ISession* SessionController::activeSession() const { return d->activeSession; } ISessionLock::Ptr SessionController::activeSessionLock() const { return d->sessionLock; } void SessionController::loadSession( const QString& nameOrId ) { d->loadSessionExternally( session( nameOrId ) ); } QList SessionController::sessionNames() const { QStringList l; foreach( const Session* s, d->sessionActions.keys() ) { l << s->name(); } return l; } QList< const KDevelop::Session* > SessionController::sessions() const { QList< const KDevelop::Session* > ret; foreach( const Session* s, d->sessionActions.keys() ) { ret << s; } return ret; } Session* SessionController::createSession( const QString& name ) { Session* s; if(name.startsWith('{')) { s = new Session( QUuid(name).toString() ); }else{ qsrand(QDateTime::currentDateTime().toTime_t()); s = new Session( QUuid::createUuid().toString() ); s->setName( name ); } d->addSession( s ); return s; } void SessionController::deleteSession( const ISessionLock::Ptr& lock ) { Session* s = session(lock->id()); QHash::iterator it = d->sessionActions.find(s); Q_ASSERT( it != d->sessionActions.end() ); unplugActionList( "available_sessions" ); actionCollection()->removeAction(*it); if (d->grp) { // happens in unit tests d->grp->removeAction(*it); plugActionList( "available_sessions", d->grp->actions() ); } if (s == d->activeSession) { d->activeSession = nullptr; } deleteSessionFromDisk(lock); emit sessionDeleted( s->id().toString() ); d->sessionActions.remove(s); delete s; } void SessionController::deleteSessionFromDisk( const ISessionLock::Ptr& lock ) { qCDebug(SHELL) << "Deleting session:" << lock->id(); QDir(sessionDirectory(lock->id())).removeRecursively(); ItemRepositoryRegistry::deleteRepositoryFromDisk( lock ); } void SessionController::loadDefaultSession( const QString& session ) { QString load = session; if (load.isEmpty()) { KConfigGroup grp = KSharedConfig::openConfig()->group( cfgSessionGroup() ); load = grp.readEntry( cfgActiveSessionEntry(), "default" ); } // Iteratively try to load the session, asking user what to do in case of failure // If showForceOpenDialog() returns empty string, stop trying Session* s = 0; do { s = this->session( load ); if( !s ) { s = createSession( load ); } TryLockSessionResult result = d->activateSession( s ); if( result.lock ) { Q_ASSERT(d->activeSession == s); Q_ASSERT(d->sessionLock = result.lock); break; } load = handleLockedSession( s->name(), s->id().toString(), result.runInfo ); } while( !load.isEmpty() ); } Session* SessionController::session( const QString& nameOrId ) const { Session* ret = d->findSessionForName( nameOrId ); if(ret) return ret; return d->findSessionForId( nameOrId ); } QString SessionController::cloneSession( const QString& nameOrid ) { Session* origSession = session( nameOrid ); qsrand(QDateTime::currentDateTime().toTime_t()); QUuid id = QUuid::createUuid(); auto copyJob = KIO::copy(QUrl::fromLocalFile(sessionDirectory(origSession->id().toString())), QUrl::fromLocalFile(sessionDirectory( id.toString()))); KJobWidgets::setWindow(copyJob, Core::self()->uiController()->activeMainWindow()); copyJob->exec(); Session* newSession = new Session( id.toString() ); newSession->setName( i18n( "Copy of %1", origSession->name() ) ); d->addSession(newSession); return newSession->name(); } void SessionController::plugActions() { unplugActionList( "available_sessions" ); plugActionList( "available_sessions", d->grp->actions() ); } QString SessionController::cfgSessionGroup() { return "Sessions"; } QString SessionController::cfgActiveSessionEntry() { return "Active Session ID"; } QList< SessionInfo > SessionController::availableSessionInfo() { QList< SessionInfo > available; foreach( const QString& sessionId, QDir( SessionControllerPrivate::sessionBaseDirectory() ).entryList( QDir::AllDirs ) ) { if( !QUuid( sessionId ).isNull() ) { available << Session::parse( sessionId ); } } return available; } QString SessionController::sessionDirectory(const QString& sessionId) { return SessionControllerPrivate::sessionBaseDirectory() + sessionId; } TryLockSessionResult SessionController::tryLockSession(const QString& id) { return SessionLock::tryLockSession(id, true); } bool SessionController::isSessionRunning(const QString& id) { return sessionRunInfo(id).isRunning; } SessionRunInfo SessionController::sessionRunInfo(const QString& id) { return SessionLock::tryLockSession(id, false).runInfo; } QString SessionController::showSessionChooserDialog(QString headerText, bool onlyRunning) { ///FIXME: move this code into sessiondialog.cpp QListView* view = new QListView; QLineEdit* filter = new QLineEdit; filter->setClearButtonEnabled( true ); filter->setPlaceholderText(i18n("Search")); QStandardItemModel* model = new QStandardItemModel(view); QSortFilterProxyModel *proxy = new QSortFilterProxyModel(model); proxy->setSourceModel(model); proxy->setFilterKeyColumn( 1 ); proxy->setFilterCaseSensitivity( Qt::CaseInsensitive ); connect(filter, &QLineEdit::textChanged, proxy, &QSortFilterProxyModel::setFilterFixedString); SessionChooserDialog dialog(view, proxy, filter); view->setEditTriggers(QAbstractItemView::NoEditTriggers); QVBoxLayout layout(dialog.mainWidget()); if(!headerText.isEmpty()) { QLabel* heading = new QLabel(headerText); QFont font = heading->font(); font.setBold(true); heading->setFont(font); layout.addWidget(heading); } model->setColumnCount(3); model->setHeaderData(0, Qt::Horizontal,i18n("Identity")); model->setHeaderData(1, Qt::Horizontal, i18n("Contents")); model->setHeaderData(2, Qt::Horizontal,i18n("State")); view->setModel(proxy); view->setModelColumn(1); QHBoxLayout* filterLayout = new QHBoxLayout(); filterLayout->addWidget(new QLabel(i18n("Filter:"))); filterLayout->addWidget(filter); layout.addLayout(filterLayout); layout.addWidget(view); filter->setFocus(); int row = 0; QString defaultSession = KSharedConfig::openConfig()->group( cfgSessionGroup() ).readEntry( cfgActiveSessionEntry(), "default" ); foreach(const KDevelop::SessionInfo& si, KDevelop::SessionController::availableSessionInfo()) { if ( si.name.isEmpty() && si.projects.isEmpty() ) { continue; } bool running = KDevelop::SessionController::isSessionRunning(si.uuid.toString()); if(onlyRunning && !running) continue; model->setItem(row, 0, new QStandardItem(si.uuid.toString())); model->setItem(row, 1, new QStandardItem(si.description)); model->setItem(row, 2, new QStandardItem); ++row; } model->sort(1); if(!onlyRunning) { model->setItem(row, 0, new QStandardItem); model->setItem(row, 1, new QStandardItem(QIcon::fromTheme("window-new"), i18n("Create New Session"))); } dialog.updateState(); dialog.mainWidget()->layout()->setContentsMargins(0,0,0,0); const QModelIndex defaultSessionIndex = model->match(model->index(0, 0), Qt::DisplayRole, defaultSession, 1, Qt::MatchExactly).value(0); view->selectionModel()->setCurrentIndex(proxy->mapFromSource(defaultSessionIndex), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); view->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); ///@todo We need a way to get a proper size-hint from the view, but unfortunately, that only seems possible after the view was shown. dialog.resize(QSize(900, 600)); if(dialog.exec() != QDialog::Accepted) { return QString(); } QModelIndex selected = view->selectionModel()->currentIndex(); if (!selected.isValid()) return QString(); const QString selectedSessionId = selected.sibling(selected.row(), 0).data().toString(); if (selectedSessionId.isEmpty()) { // "Create New Session" item selected, return a fresh UUID qsrand(QDateTime::currentDateTime().toTime_t()); return QUuid::createUuid().toString(); } return selectedSessionId; } QString SessionController::handleLockedSession( const QString& sessionName, const QString& sessionId, const SessionRunInfo& runInfo ) { return SessionLock::handleLockedSession(sessionName, sessionId, runInfo); } QString SessionController::sessionDir() { if( !activeSession() ) return QString(); return d->ownSessionDirectory(); } QString SessionController::sessionName() { if(!activeSession()) return QString(); return activeSession()->description(); } } #include "sessioncontroller.moc" #include "moc_sessioncontroller.cpp" diff --git a/shell/sessioncontroller.h b/shell/sessioncontroller.h index 198000c261..c2f8e60530 100644 --- a/shell/sessioncontroller.h +++ b/shell/sessioncontroller.h @@ -1,180 +1,180 @@ /* This file is part of KDevelop Copyright 2008 Andreas Pakulat Copyright 2013 Milian Wolff 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 KDEVPLATFORM_SESSIONCONTROLLER_H #define KDEVPLATFORM_SESSIONCONTROLLER_H #include "shellexport.h" #include "session.h" #include #include #include namespace KDevelop { struct SessionRunInfo { SessionRunInfo() : isRunning(false) , holderPid(-1) {} bool operator==(const SessionRunInfo& o) const { return isRunning == o.isRunning && holderPid == o.holderPid && holderApp == o.holderApp && holderHostname == o.holderHostname; } bool operator!=(const SessionRunInfo& o) const { return !(operator==(o)); } // if this is true, this session is currently running in an external process bool isRunning; // if the session is running, this contains the PID of its process qint64 holderPid; // if the session is running, this contains the name of its process QString holderApp; // if the session is running, this contains the host name where the process runs QString holderHostname; }; struct TryLockSessionResult { TryLockSessionResult(const ISessionLock::Ptr& _lock) : lock(_lock) {} TryLockSessionResult(const SessionRunInfo& _runInfo) : runInfo(_runInfo) {} // if this is non-null then the session was locked ISessionLock::Ptr lock; // otherwise this contains information about who is locking the session SessionRunInfo runInfo; }; class KDEVPLATFORMSHELL_EXPORT SessionController : public QObject, public KXMLGUIClient { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kdevelop.SessionController") public: explicit SessionController( QObject *parent = 0 ); - virtual ~SessionController(); + ~SessionController() override; void initialize( const QString& session ); void cleanup(); /// Returns whether the given session can be locked (i. e., is not locked currently). /// @param doLocking whether to really lock the session or just "dry-run" the locking process static TryLockSessionResult tryLockSession(const QString& id); /** * @return true when the given session is currently running, false otherwise */ static bool isSessionRunning(const QString& id); /** * @return information about whether the session @p id is running */ static SessionRunInfo sessionRunInfo(const QString& id); /// The application should call this on startup to tell the /// session-controller about the received arguments. /// Some of them may need to be passed to newly opened sessions. static void setArguments(int argc, char** argv); ///Finds a session by its name or by its UUID Session* session( const QString& nameOrId ) const; virtual ISession* activeSession() const; ISessionLock::Ptr activeSessionLock() const; QList sessionNames() const; Session* createSession( const QString& name ); QList sessions() const; void loadDefaultSession( const QString& session ); void startNewSession(); void loadSession( const QString& nameOrId ); void deleteSession( const ISessionLock::Ptr& lock ); static void deleteSessionFromDisk( const ISessionLock::Ptr& lock ); QString cloneSession( const QString& nameOrid ); /** * Path to session directory for the session with the given @p sessionId. */ static QString sessionDirectory( const QString& sessionId ); static QString cfgSessionGroup(); static QString cfgActiveSessionEntry(); static QList< SessionInfo > availableSessionInfo(); /** * Shows a dialog where the user can choose the session * @param headerText an additional text that will be shown at the top in a label * @param onlyRunning whether only currently running sessions should be shown * @return UUID on success, empty string in any other case */ static QString showSessionChooserDialog(QString headerText = QString(), bool onlyRunning = false); /// Should be called if session to be opened is locked. /// It attempts to bring existing instance's window up via a DBus call; if that succeeds, empty string is returned. /// Otherwise (if the app did not respond) it shows a dialog where the user may choose /// 1) to force-remove the lockfile and continue, /// 2) to select another session via \ref showSessionChooserDialog, /// 3) to quit the current (starting-up) instance. /// @param sessionName session name (for the message) /// @param sessionId current session GUID (to return if user chooses force-removal) /// @param runInfo the run information about the session /// @return new session GUID to try or an empty string if application startup shall be aborted static QString handleLockedSession( const QString& sessionName, const QString& currentSessionId, const SessionRunInfo& runInfo ); void plugActions(); void emitQuitSession() { emit quitSession(); } public Q_SLOTS: // Returns the pretty name of the currently active session (used in the shell integration) virtual Q_SCRIPTABLE QString sessionName(); // Returns the directory associated to the active session (used in the shell integration) virtual Q_SCRIPTABLE QString sessionDir(); Q_SIGNALS: void sessionLoaded( ISession* ); void sessionDeleted( const QString& id); void quitSession(); private: Q_PRIVATE_SLOT( d, void newSession() ) Q_PRIVATE_SLOT( d, void configureSessions() ) Q_PRIVATE_SLOT( d, void deleteCurrentSession() ) Q_PRIVATE_SLOT( d, void renameSession() ) Q_PRIVATE_SLOT( d, void loadSessionFromAction( QAction* ) ) class SessionControllerPrivate* const d; }; } #endif diff --git a/shell/sessiondialog.h b/shell/sessiondialog.h index 373e90ad2a..9d01a4a32c 100644 --- a/shell/sessiondialog.h +++ b/shell/sessiondialog.h @@ -1,76 +1,76 @@ /* This file is part of KDevelop Copyright 2008 Andreas Pakulat 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 KDEVPLATFORM_SESSIONDIALOG_H #define KDEVPLATFORM_SESSIONDIALOG_H #include #include namespace Ui { class SessionDialog; } class QModelIndex; class QItemSelection; class QVariant; namespace KDevelop { class Session; class SessionModel : public QAbstractListModel { Q_OBJECT public: explicit SessionModel( QObject* parent = 0 ); int rowCount( const QModelIndex& = QModelIndex() ) const override; QVariant data( const QModelIndex&, int = Qt::DisplayRole ) const override; QVariant headerData( int, Qt::Orientation, int = Qt::DisplayRole ) const override; bool setData( const QModelIndex&, const QVariant&, int = Qt::DisplayRole ) override; Qt::ItemFlags flags( const QModelIndex& ) const override; void deleteSessions( const QList& ); void activateSession( const QModelIndex& ); void addSession(); void cloneSession( const QModelIndex& ); }; class SessionDialog : public QDialog { Q_OBJECT public: explicit SessionDialog( QWidget* = 0 ); - virtual ~SessionDialog(); + ~SessionDialog() override; private Q_SLOTS: void createSession(); void deleteSession(); void activateSession(); void cloneSession(); void enableButtons( const QModelIndex&, const QModelIndex& ); void enableButtons( const QItemSelection&, const QItemSelection& ); void enableButtons(); private: Ui::SessionDialog* m_ui; SessionModel* m_model; }; } #endif diff --git a/shell/settings/bgpreferences.h b/shell/settings/bgpreferences.h index 3984317182..a12ac4c7e7 100644 --- a/shell/settings/bgpreferences.h +++ b/shell/settings/bgpreferences.h @@ -1,55 +1,55 @@ /* KDevelop Project Settings * * Copyright 2006 Matt Rogers * Copyright 2007 Hamish Rodda * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef KDEVPLATFORM_BGPREFERENCES_H #define KDEVPLATFORM_BGPREFERENCES_H #include namespace Ui { class BGPreferences; } namespace KDevelop { class BGPreferences : public ConfigPage { Q_OBJECT public: explicit BGPreferences(QWidget* parent); - virtual ~BGPreferences(); + ~BGPreferences() override; - virtual QString name() const override; - virtual QString fullName() const override; - virtual QIcon icon() const override; + QString name() const override; + QString fullName() const override; + QIcon icon() const override; - virtual void apply() override; - virtual void reset() override; + void apply() override; + void reset() override; private: Ui::BGPreferences *preferencesDialog; }; } #endif diff --git a/shell/settings/editstyledialog.h b/shell/settings/editstyledialog.h index f938e56ccd..36330fb982 100644 --- a/shell/settings/editstyledialog.h +++ b/shell/settings/editstyledialog.h @@ -1,72 +1,72 @@ /* This file is part of KDevelop * Copyright (C) 2008 Cédric Pasteur 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_EDITSTYLEDIALOG_H #define KDEVPLATFORM_EDITSTYLEDIALOG_H #include #include #include #include "ui_editstyledialog.h" namespace KTextEditor { class Document; class View; } namespace KDevelop { class ISourceFormatter; class SettingsWidget; class SourceFormatterStyle; } /** \short A simple dialog to add preview around a \ref SettingsWidget */ class EditStyleDialog : public QDialog { Q_OBJECT public: EditStyleDialog(KDevelop::ISourceFormatter* formatter, const QMimeType& mime, const KDevelop::SourceFormatterStyle&, QWidget* parent = 0); - virtual ~EditStyleDialog(); + ~EditStyleDialog() override; /** \return The string representing the style given by the \ref SettingsWidget. */ QString content(); protected: void init(); public slots: void updatePreviewText(const QString &text); private: KDevelop::ISourceFormatter* m_sourceFormatter; KTextEditor::View* m_view; KTextEditor::Document* m_document; KDevelop::SettingsWidget* m_settingsWidget; QMimeType m_mimeType; QWidget* m_content; Ui::EditStyle m_ui; KDevelop::SourceFormatterStyle m_style; }; #endif // KDEVPLATFORM_EDITSTYLEDIALOG_H diff --git a/shell/settings/environmentpreferences.h b/shell/settings/environmentpreferences.h index e5d950b59e..11939128b3 100644 --- a/shell/settings/environmentpreferences.h +++ b/shell/settings/environmentpreferences.h @@ -1,50 +1,50 @@ /* This file is part of KDevelop Copyright 2006 Adam Treat 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 KDEVPLATFORM_ENVIRONMENTPREFERENCES_H #define KDEVPLATFORM_ENVIRONMENTPREFERENCES_H #include namespace KDevelop { class EnvironmentPreferences : public ConfigPage { Q_OBJECT public: explicit EnvironmentPreferences(const QString& activeGroup = QString(), QWidget* parent = nullptr); - virtual ~EnvironmentPreferences(); + ~EnvironmentPreferences() override; - virtual QString name() const override; - virtual QString fullName() const override; - virtual QIcon icon() const override; + QString name() const override; + QString fullName() const override; + QIcon icon() const override; - virtual void apply() override; - virtual void reset() override; - virtual void defaults() override; + void apply() override; + void reset() override; + void defaults() override; private: class EnvironmentPreferencesPrivate *const d; }; } #endif diff --git a/shell/settings/languagepreferences.h b/shell/settings/languagepreferences.h index 6462f231d1..fad2a6a2ba 100644 --- a/shell/settings/languagepreferences.h +++ b/shell/settings/languagepreferences.h @@ -1,55 +1,55 @@ /* KDevelop Project Settings * * Copyright 2006 Matt Rogers * Copyright 2007 Hamish Rodda * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef KDEVPLATFORM_LANGUAGEPREFERENCESPREFERENCES_H #define KDEVPLATFORM_LANGUAGEPREFERENCESPREFERENCES_H #include namespace Ui { class LanguagePreferences; } namespace KDevelop { class LanguagePreferences : public ConfigPage { Q_OBJECT public: explicit LanguagePreferences(QWidget* parent); - virtual ~LanguagePreferences(); + ~LanguagePreferences() override; - virtual QString name() const override; - virtual QString fullName() const override; - virtual QIcon icon() const override; + QString name() const override; + QString fullName() const override; + QIcon icon() const override; - virtual void apply() override; + void apply() override; void notifySettingsChanged(); private: Ui::LanguagePreferences *preferencesDialog; }; } #endif diff --git a/shell/settings/pluginpreferences.h b/shell/settings/pluginpreferences.h index d71fa5e66c..b2e4971a30 100644 --- a/shell/settings/pluginpreferences.h +++ b/shell/settings/pluginpreferences.h @@ -1,54 +1,54 @@ /* KDevelop Project Settings * * Copyright 2008 Andreas Pakulat * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef KDEVPLATFORM_PLUGINPREFERENCES_H #define KDEVPLATFORM_PLUGINPREFERENCES_H #include #include #include class KPluginSelector; namespace KDevelop { class PluginPreferences : public ConfigPage { Q_OBJECT public: explicit PluginPreferences(QWidget*); - virtual QString name() const override { return i18n("Plugins"); }; - virtual QString fullName() const override { return i18n("Configure Plugins"); }; - virtual QIcon icon() const override { return QIcon::fromTheme("preferences-plugin"); } + QString name() const override { return i18n("Plugins"); }; + QString fullName() const override { return i18n("Configure Plugins"); }; + QIcon icon() const override { return QIcon::fromTheme("preferences-plugin"); } public Q_SLOTS: - virtual void apply() override; - virtual void reset() override; - virtual void defaults() override; + void apply() override; + void reset() override; + void defaults() override; private: KPluginSelector* selector; }; } #endif diff --git a/shell/settings/projectpreferences.h b/shell/settings/projectpreferences.h index 42f6fcddbc..74ed1b1228 100644 --- a/shell/settings/projectpreferences.h +++ b/shell/settings/projectpreferences.h @@ -1,56 +1,56 @@ /* KDevelop Project Settings * * Copyright 2006 Matt Rogers * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef KDEVPLATFORM_PROJECTPREFERENCES_H #define KDEVPLATFORM_PROJECTPREFERENCES_H #include namespace Ui { class ProjectPreferences; } namespace KDevelop { class ProjectPreferences : public ConfigPage { Q_OBJECT public: explicit ProjectPreferences(QWidget *parent); - virtual ~ProjectPreferences(); + ~ProjectPreferences() override; - virtual QString name() const override; - virtual QString fullName() const override; - virtual QIcon icon() const override; + QString name() const override; + QString fullName() const override; + QIcon icon() const override; - virtual void apply() override; + void apply() override; private slots: void slotSettingsChanged(); private: Ui::ProjectPreferences *preferencesDialog; }; } #endif diff --git a/shell/settings/sourceformattersettings.h b/shell/settings/sourceformattersettings.h index 59927fc48e..2448bc0d62 100644 --- a/shell/settings/sourceformattersettings.h +++ b/shell/settings/sourceformattersettings.h @@ -1,98 +1,98 @@ /* This file is part of KDevelop * Copyright (C) 2008 Cédric Pasteur 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_SOURCEFORMATTERSETTINGS_H #define KDEVPLATFORM_SOURCEFORMATTERSETTINGS_H #include #include #include #include "sourceformattercontroller.h" #include "ui_sourceformattersettings.h" class QListWidgetItem; namespace KTextEditor { class Document; class View; } namespace KDevelop { class ISourceFormatter; class SourceFormatterStyle; } struct LanguageSettings { LanguageSettings(); QList mimetypes; QSet formatters; // weak pointers to selected formatter and style, no ownership KDevelop::SourceFormatter* selectedFormatter; // Should never be zero KDevelop::SourceFormatterStyle* selectedStyle; // TODO: can this be zero? Assume that not }; /** \short The settings modulefor the Source formatter plugin. * It supports predefined and custom styles. A live preview of the style * is shown on the right side of the page.s */ class SourceFormatterSettings : public KDevelop::ConfigPage, public Ui::SourceFormatterSettingsUI { Q_OBJECT public: explicit SourceFormatterSettings(QWidget* parent = 0); - virtual ~SourceFormatterSettings(); + ~SourceFormatterSettings() override; - virtual QString name() const override; - virtual QString fullName() const override; - virtual QIcon icon() const override; + QString name() const override; + QString fullName() const override; + QIcon icon() const override; public slots: - virtual void reset() override; - virtual void apply() override; - virtual void defaults() override; + void reset() override; + void apply() override; + void defaults() override; private slots: void deleteStyle(); void editStyle(); void newStyle(); void selectLanguage( int ); void selectFormatter( int ); void selectStyle( int ); void styleNameChanged( QListWidgetItem* ); void somethingChanged(); private: void updatePreview(); QListWidgetItem* addStyle( const KDevelop::SourceFormatterStyle& s ); void enableStyleButtons(); // Language name -> language settings typedef QMap LanguageMap; LanguageMap languages; // formatter name -> formatter. Formatters owned by this typedef QMap FormatterMap; FormatterMap formatters; KTextEditor::Document* m_document; KTextEditor::View* m_view; }; #endif // KDEVPLATFORM_SOURCEFORMATTERSETTINGS_H diff --git a/shell/settings/templateconfig.h b/shell/settings/templateconfig.h index 0c4ce0c5f5..c509b8f681 100644 --- a/shell/settings/templateconfig.h +++ b/shell/settings/templateconfig.h @@ -1,49 +1,49 @@ /* * This file is part of KDevelop * Copyright 2012 Miha Čančula * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_TEMPLATECONFIG_H #define KDEVPLATFORM_TEMPLATECONFIG_H #include namespace Ui { class TemplateConfig; } class TemplateConfig : public KDevelop::ConfigPage { Q_OBJECT public: explicit TemplateConfig(QWidget* parent = 0); - virtual ~TemplateConfig(); + ~TemplateConfig() override; - virtual QString name() const override; - virtual QString fullName() const override; - virtual QIcon icon() const override; + QString name() const override; + QString fullName() const override; + QIcon icon() const override; - virtual void reset() override; - virtual void apply() override; - virtual void defaults() override; + void reset() override; + void apply() override; + void defaults() override; private: Ui::TemplateConfig* ui; }; #endif // KDEVPLATFORM_PLUGIN_TEMPLATECONFIG_H diff --git a/shell/settings/templatepage.h b/shell/settings/templatepage.h index 4476b9643d..25706f7fb7 100644 --- a/shell/settings/templatepage.h +++ b/shell/settings/templatepage.h @@ -1,56 +1,56 @@ /* * This file is part of KDevelop * Copyright 2012 Miha Čančula * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_TEMPLATEPAGE_H #define KDEVPLATFORM_TEMPLATEPAGE_H #include class QModelIndex; namespace KDevelop { class ITemplateProvider; } namespace Ui { class TemplatePage; } class TemplatePage : public QWidget { Q_OBJECT public: explicit TemplatePage(KDevelop::ITemplateProvider* provider, QWidget* parent = 0); - virtual ~TemplatePage(); + ~TemplatePage() override; private slots: void loadFromFile(); void getMoreTemplates(); void shareTemplates(); void currentIndexChanged(const QModelIndex& index); void extractTemplate(); private: KDevelop::ITemplateProvider* m_provider; Ui::TemplatePage* ui; }; #endif // KDEVPLATFORM_TEMPLATEPAGE_H diff --git a/shell/sourceformattercontroller.h b/shell/sourceformattercontroller.h index 607db3b659..c47fd5fbeb 100644 --- a/shell/sourceformattercontroller.h +++ b/shell/sourceformattercontroller.h @@ -1,165 +1,165 @@ /* This file is part of KDevelop Copyright 2009 Andreas Pakulat Copyright (C) 2008 Cédric Pasteur 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 KDEVPLATFORM_SOURCEFORMATTERCONTROLLER_H #define KDEVPLATFORM_SOURCEFORMATTERCONTROLLER_H #include #include #include #include #include #include #include #include #include #include "shellexport.h" namespace KTextEditor { class Document; } class QAction; namespace KDevelop { class Context; class ContextMenuExtension; class ProjectBaseItem; class IDocument; class ISourceFormatter; class IPlugin; struct SourceFormatter { KDevelop::ISourceFormatter* formatter; // style name -> style. style objects owned by this typedef QMap StyleMap; StyleMap styles; // Get a list of supported mime types from the style map. QSet supportedMimeTypes() const { QSet supported; for ( auto style: styles ) { for ( auto item: style->mimeTypes() ) { supported.insert(item.mimeType); } } return supported; } ~SourceFormatter() { qDeleteAll(styles); }; }; /** \short A singleton class managing all source formatter plugins */ class KDEVPLATFORMSHELL_EXPORT SourceFormatterController : public ISourceFormatterController, public KXMLGUIClient { Q_OBJECT public: static QString kateModeLineConfigKey(); static QString kateOverrideIndentationConfigKey(); static QString styleCaptionKey(); static QString styleContentKey(); static QString styleMimeTypesKey(); static QString styleSampleKey(); explicit SourceFormatterController(QObject *parent = 0); - virtual ~SourceFormatterController(); + ~SourceFormatterController() override; void initialize(); void cleanup(); //----------------- Public API defined in interfaces ------------------- /** \return The formatter corresponding to the language * of the document corresponding to the \arg url. */ ISourceFormatter* formatterForUrl(const QUrl &url) override; /** Loads and returns a source formatter for this mime type. * The language is then activated and the style is loaded. * The source formatter is then ready to use on a file. */ ISourceFormatter* formatterForMimeType(const QMimeType& mime) override; /** \return Whether this mime type is supported by any plugin. */ bool isMimeTypeSupported(const QMimeType& mime) override; /** * @brief Instantiate a Formatter for the given plugin and load its configuration. * * @param ifmt The ISourceFormatter interface of the plugin * @return KDevelop::SourceFormatter* the SourceFormatter instance for the plugin, including config items */ SourceFormatter* createFormatterForPlugin(KDevelop::ISourceFormatter* ifmt) const; /** * @brief Find the first formatter which supports a given mime type. */ ISourceFormatter* findFirstFormatterForMimeType(const QMimeType& mime) const; KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context); KDevelop::SourceFormatterStyle styleForMimeType(const QMimeType& mime) override; KConfigGroup sessionConfig() const; KConfigGroup globalConfig() const; void settingsChanged(); - virtual void disableSourceFormatting(bool disable) override; - virtual bool sourceFormattingEnabled() override; + void disableSourceFormatting(bool disable) override; + bool sourceFormattingEnabled() override; private Q_SLOTS: void activeDocumentChanged(KDevelop::IDocument *doc); void beautifySource(); void beautifyLine(); void formatFiles(); void documentLoaded( KDevelop::IDocument* ); private: /** \return A modeline string (to add at the end or the beginning of a file) * corresponding to the settings of the active language. */ QString addModelineForCurrentLang(QString input, const QUrl& url, const QMimeType&); /** \return The name of kate indentation mode for the mime type. * examples are cstyle, python, etc. */ QString indentationMode(const QMimeType& mime); void formatDocument(KDevelop::IDocument* doc, ISourceFormatter* formatter, const QMimeType& mime); // Adapts the mode of the editor regarding indentation-style void adaptEditorIndentationMode(KTextEditor::Document* doc, KDevelop::ISourceFormatter* formatter, bool ignoreModeline = false); void formatFiles(QList &list); // GUI actions QAction* m_formatTextAction; QAction* m_formatFilesAction; QAction* m_formatLine; QList m_prjItems; QList m_urls; bool m_enabled; }; } #endif // KDEVPLATFORM_SOURCEFORMATTERMANAGER_H diff --git a/shell/testcontroller.h b/shell/testcontroller.h index 5e27226f48..10a3a9cbad 100644 --- a/shell/testcontroller.h +++ b/shell/testcontroller.h @@ -1,57 +1,57 @@ /* This file is part of KDevelop Copyright 2012 Miha Čančula 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; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_TESTCONTROLLER_H #define KDEVPLATFORM_TESTCONTROLLER_H #include "interfaces/itestcontroller.h" #include "shellexport.h" namespace KDevelop { class KDEVPLATFORMSHELL_EXPORT TestController : public KDevelop::ITestController { Q_OBJECT public: explicit TestController(QObject *parent); - virtual ~TestController(); + ~TestController() override; void initialize(); void cleanup(); - virtual void removeTestSuite(KDevelop::ITestSuite* suite) override; - virtual void addTestSuite(KDevelop::ITestSuite* suite) override; + void removeTestSuite(KDevelop::ITestSuite* suite) override; + void addTestSuite(KDevelop::ITestSuite* suite) override; - virtual QList< KDevelop::ITestSuite* > testSuites() const override; - virtual KDevelop::ITestSuite* findTestSuite(KDevelop::IProject* project, const QString& name) const override; - virtual QList< KDevelop::ITestSuite* > testSuitesForProject(KDevelop::IProject* project) const override; + QList< KDevelop::ITestSuite* > testSuites() const override; + KDevelop::ITestSuite* findTestSuite(KDevelop::IProject* project, const QString& name) const override; + QList< KDevelop::ITestSuite* > testSuitesForProject(KDevelop::IProject* project) const override; - virtual void notifyTestRunFinished(KDevelop::ITestSuite* suite, const KDevelop::TestResult& result) override; - virtual void notifyTestRunStarted(KDevelop::ITestSuite* suite, const QStringList& test_cases) override; + void notifyTestRunFinished(KDevelop::ITestSuite* suite, const KDevelop::TestResult& result) override; + void notifyTestRunStarted(KDevelop::ITestSuite* suite, const QStringList& test_cases) override; private: class TestControllerPrivate; TestControllerPrivate* const d; }; } #endif // KDEVPLATFORM_TESTCONTROLLER_H diff --git a/shell/tests/test_ktexteditorpluginintegration.cpp b/shell/tests/test_ktexteditorpluginintegration.cpp index 666beee5dd..b2c2ba04f6 100644 --- a/shell/tests/test_ktexteditorpluginintegration.cpp +++ b/shell/tests/test_ktexteditorpluginintegration.cpp @@ -1,195 +1,195 @@ /* Copyright 2015 Milian Wolff 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_ktexteditorpluginintegration.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace KDevelop; namespace { template QPointer makeQPointer(T *ptr) { return {ptr}; } IToolViewFactory *findToolView(const QString &id) { const auto uiController = Core::self()->uiControllerInternal(); const auto map = uiController->factoryDocuments(); for (auto it = map.begin(); it != map.end(); ++it) { if (it.key()->id() == id) { return it.key(); } } return nullptr; } class TestPlugin : public KTextEditor::Plugin { public: TestPlugin(QObject *parent) : Plugin(parent) { } - QObject *createView(KTextEditor::MainWindow * mainWindow) + QObject *createView(KTextEditor::MainWindow * mainWindow) override { return new QObject(mainWindow); } }; } void TestKTextEditorPluginIntegration::initTestCase() { QLoggingCategory::setFilterRules(QStringLiteral("*.debug=false\ndefault.debug=true\n")); AutoTestShell::init({"katesnippetsplugin"}); TestCore::initialize(); QVERIFY(KTextEditor::Editor::instance()); } void TestKTextEditorPluginIntegration::cleanupTestCase() { auto controller = Core::self()->pluginController(); const auto id = QStringLiteral("katesnippetsplugin"); auto plugin = makeQPointer(controller->loadPlugin(id)); const auto editor = makeQPointer(KTextEditor::Editor::instance()); const auto application = makeQPointer(editor->application()); const auto window = makeQPointer(application->activeMainWindow()); TestCore::shutdown(); QVERIFY(!plugin); QVERIFY(!window); QVERIFY(!application); } void TestKTextEditorPluginIntegration::testApplication() { auto app = KTextEditor::Editor::instance()->application(); QVERIFY(app); QVERIFY(app->parent()); QCOMPARE(app->parent()->metaObject()->className(), "KTextEditorIntegration::Application"); QVERIFY(app->activeMainWindow()); QCOMPARE(app->mainWindows().size(), 1); QVERIFY(app->mainWindows().contains(app->activeMainWindow())); } void TestKTextEditorPluginIntegration::testMainWindow() { auto window = KTextEditor::Editor::instance()->application()->activeMainWindow(); QVERIFY(window); QVERIFY(window->parent()); QCOMPARE(window->parent()->metaObject()->className(), "KTextEditorIntegration::MainWindow"); const auto id = QStringLiteral("kte_integration_toolview"); const auto icon = QIcon::fromTheme(QStringLiteral("kdevelop")); const auto text = QStringLiteral("some text"); QVERIFY(!findToolView(id)); auto plugin = new TestPlugin(this); auto toolView = makeQPointer(window->createToolView(plugin, id, KTextEditor::MainWindow::Bottom, icon, text)); QVERIFY(toolView); auto factory = findToolView(id); QVERIFY(factory); // we reuse the same view QWidget parent; auto kdevToolview = makeQPointer(factory->create(&parent)); QCOMPARE(kdevToolview->parentWidget(), &parent); QCOMPARE(toolView->parentWidget(), kdevToolview.data()); // the children are kept alive when the toolview gets destroyed delete kdevToolview; QVERIFY(toolView); kdevToolview = factory->create(&parent); // and we reuse the ktexteditor toolview for the new kdevelop toolview QCOMPARE(toolView->parentWidget(), kdevToolview.data()); delete toolView; delete kdevToolview; delete plugin; QVERIFY(!findToolView(id)); } void TestKTextEditorPluginIntegration::testPlugin() { auto controller = Core::self()->pluginController(); const auto id = QStringLiteral("katesnippetsplugin"); auto plugin = makeQPointer(controller->loadPlugin(id)); if (!plugin) { QSKIP("Cannot continue without katesnippetsplugin, install Kate"); } auto app = KTextEditor::Editor::instance()->application(); auto ktePlugin = makeQPointer(app->plugin(id)); QVERIFY(ktePlugin); auto view = makeQPointer(app->activeMainWindow()->pluginView(id)); QVERIFY(view); const auto rawView = view.data(); QSignalSpy spy(app->activeMainWindow(), &KTextEditor::MainWindow::pluginViewDeleted); QVERIFY(controller->unloadPlugin(id)); QVERIFY(!ktePlugin); QCOMPARE(spy.count(), 1); QCOMPARE(spy.first().count(), 2); QCOMPARE(spy.first().at(0), QVariant::fromValue(id)); QCOMPARE(spy.first().at(1), QVariant::fromValue(rawView)); QVERIFY(!view); } void TestKTextEditorPluginIntegration::testPluginUnload() { auto controller = Core::self()->pluginController(); const auto id = QStringLiteral("katesnippetsplugin"); auto plugin = makeQPointer(controller->loadPlugin(id)); if (!plugin) { QSKIP("Cannot continue without katesnippetsplugin, install Kate"); } auto app = KTextEditor::Editor::instance()->application(); auto ktePlugin = makeQPointer(app->plugin(id)); QVERIFY(ktePlugin); delete ktePlugin; // don't crash plugin->unload(); } QTEST_MAIN(TestKTextEditorPluginIntegration); diff --git a/shell/tests/test_projectcontroller.cpp b/shell/tests/test_projectcontroller.cpp index 6782a25289..cdb9ba52c9 100644 --- a/shell/tests/test_projectcontroller.cpp +++ b/shell/tests/test_projectcontroller.cpp @@ -1,574 +1,574 @@ /*************************************************************************** * Copyright 2008 Manuel Breugelmans * * * * 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 Library 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 "test_projectcontroller.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace KDevelop; Q_DECLARE_METATYPE(KDevelop::IProject*) namespace { class DialogProviderFake : public IProjectDialogProvider { Q_OBJECT public: DialogProviderFake() : m_reopen(true) {} - virtual ~DialogProviderFake() {} + ~DialogProviderFake() override {} bool m_reopen; public slots: - virtual QUrl askProjectConfigLocation(bool /*fetch*/, const QUrl& /*startUrl*/ = QUrl()) override { return QUrl(); } - virtual bool userWantsReopen() override { return m_reopen; } + QUrl askProjectConfigLocation(bool /*fetch*/, const QUrl& /*startUrl*/ = QUrl()) override { return QUrl(); } + bool userWantsReopen() override { return m_reopen; } }; } /*! A Filemanager plugin that allows you to setup a file & directory structure */ class FakeFileManager : public IPlugin, public IProjectFileManager { Q_OBJECT Q_INTERFACES(KDevelop::IProjectFileManager) public: FakeFileManager(QObject*, const QVariantList&) : IPlugin(ICore::self()->aboutData().componentName(), Core::self()) { KDEV_USE_EXTENSION_INTERFACE( KDevelop::IProjectFileManager ) } FakeFileManager() : IPlugin(ICore::self()->aboutData().componentName(), Core::self()) { KDEV_USE_EXTENSION_INTERFACE( KDevelop::IProjectFileManager ) } - virtual ~FakeFileManager() {} + ~FakeFileManager() override {} - virtual Features features() const override + Features features() const override { return IProjectFileManager::Files | IProjectFileManager::Folders; } QMap m_filesInFolder; // initialize QMap m_subFoldersInFolder; /*! Setup this manager such that @p folder contains @p file */ void addFileToFolder(const Path& folder, const Path& file) { if (!m_filesInFolder.contains(folder)) { m_filesInFolder[folder] = Path::List(); } m_filesInFolder[folder] << file; } /*! Setup this manager such that @p folder has @p subFolder */ void addSubFolderTo(const Path& folder, Path subFolder) { if (!m_subFoldersInFolder.contains(folder)) { m_subFoldersInFolder[folder] = Path::List(); } m_subFoldersInFolder[folder] << subFolder; } - virtual QList parse(ProjectFolderItem *dom) override + QList parse(ProjectFolderItem *dom) override { Path::List files = m_filesInFolder[dom->path()]; foreach (const Path& file, files) { new ProjectFileItem(dom->project(), file, dom); } Path::List folderPaths = m_subFoldersInFolder[dom->path()]; QList folders; foreach (const Path& folderPath, folderPaths) { folders << new ProjectFolderItem(dom->project(), folderPath, dom); } return folders; } - virtual ProjectFolderItem *import(IProject *project) override + ProjectFolderItem *import(IProject *project) override { ProjectFolderItem* it = new ProjectFolderItem(project, project->path()); return it; } - virtual ProjectFolderItem* addFolder(const Path& /*folder*/, ProjectFolderItem */*parent*/) override { return 0; } - virtual ProjectFileItem* addFile(const Path& /*file*/, ProjectFolderItem */*parent*/) override { return 0; } - virtual bool removeFilesAndFolders(const QList &/*items*/) override { return false; } - virtual bool moveFilesAndFolders(const QList< KDevelop::ProjectBaseItem* > &/*items*/, KDevelop::ProjectFolderItem* /*newParent*/) override { return false; } - virtual bool copyFilesAndFolders(const Path::List &/*items*/, KDevelop::ProjectFolderItem* /*newParent*/) override { return false; } - virtual bool renameFile(ProjectFileItem* /*file*/, const Path& /*newPath*/) override { return false; } - virtual bool renameFolder(ProjectFolderItem* /*oldFolder*/, const Path& /*newPath*/ ) override { return false; } - virtual bool reload(ProjectFolderItem* /*item*/) override { return false; } + ProjectFolderItem* addFolder(const Path& /*folder*/, ProjectFolderItem */*parent*/) override { return 0; } + ProjectFileItem* addFile(const Path& /*file*/, ProjectFolderItem */*parent*/) override { return 0; } + bool removeFilesAndFolders(const QList &/*items*/) override { return false; } + bool moveFilesAndFolders(const QList< KDevelop::ProjectBaseItem* > &/*items*/, KDevelop::ProjectFolderItem* /*newParent*/) override { return false; } + bool copyFilesAndFolders(const Path::List &/*items*/, KDevelop::ProjectFolderItem* /*newParent*/) override { return false; } + bool renameFile(ProjectFileItem* /*file*/, const Path& /*newPath*/) override { return false; } + bool renameFolder(ProjectFolderItem* /*oldFolder*/, const Path& /*newPath*/ ) override { return false; } + bool reload(ProjectFolderItem* /*item*/) override { return false; } }; class FakePluginController : public PluginController { public: FakePluginController(Core* core) : PluginController(core) , m_fakeFileManager(new FakeFileManager) { } IPlugin* pluginForExtension(const QString& extension, const QString& pluginName = {}, const QVariantMap& constraints = QVariantMap()) override { if (extension == m_fakeFileManager->extensions().first()) return m_fakeFileManager; return PluginController::pluginForExtension(extension, pluginName, constraints); } private: FakeFileManager* m_fakeFileManager; }; ////////////////////// Fixture /////////////////////////////////////////////// void TestProjectController::initTestCase() { AutoTestShell::init(); TestCore* testCore = new TestCore; testCore->setPluginController( new FakePluginController(testCore) ); testCore->initialize(); qRegisterMetaType(); m_core = Core::self(); m_scratchDir = QDir(QDir::tempPath()); m_scratchDir.mkdir("prjctrltest"); m_scratchDir.cd("prjctrltest"); } void TestProjectController::cleanupTestCase() { TestCore::shutdown(); } void TestProjectController::init() { m_projName = "foo"; m_projFilePath = writeProjectConfig(m_projName); m_projCtrl = m_core->projectControllerInternal(); m_tmpConfigs << m_projFilePath; m_projFolder = Path(m_scratchDir.absolutePath() + '/'); } void TestProjectController::cleanup() { // also close any opened projects as we do not get a clean fixture, // following tests should start off clean. foreach(IProject* p, m_projCtrl->projects()) { m_projCtrl->closeProject(p); } foreach(const Path &cfg, m_tmpConfigs) { QFile::remove(cfg.pathOrUrl()); } qDeleteAll(m_fileManagerGarbage); m_fileManagerGarbage.clear(); } ////////////////////// Commands ////////////////////////////////////////////// #define WAIT_FOR_OPEN_SIGNAL \ {\ QSignalSpy signal(m_projCtrl, SIGNAL(projectOpened(KDevelop::IProject*)));\ QVERIFY2(signal.wait(30000), "Timeout while waiting for opened signal");\ } void(0) void TestProjectController::openProject() { QSignalSpy* spy = createOpenedSpy(); QVERIFY(!m_projCtrl->isProjectNameUsed(m_projName)); m_projCtrl->openProject(m_projFilePath.toUrl()); WAIT_FOR_OPEN_SIGNAL; QCOMPARE(m_projCtrl->projectCount(), 1); IProject* proj; assertProjectOpened(m_projName, proj);QVERIFY(proj); assertSpyCaughtProject(spy, proj); QCOMPARE(proj->projectFile(), m_projFilePath); QCOMPARE(proj->path(), Path(m_scratchDir.absolutePath()+'/')); QVERIFY(m_projCtrl->isProjectNameUsed(m_projName)); } void TestProjectController::closeProject() { m_projCtrl->openProject(m_projFilePath.toUrl()); WAIT_FOR_OPEN_SIGNAL; IProject* proj = m_projCtrl->findProjectByName(m_projName); Q_ASSERT(proj); QSignalSpy* spy1 = createClosedSpy(); QSignalSpy* spy2 = createClosingSpy(); m_projCtrl->closeProject(proj); QVERIFY(!m_projCtrl->isProjectNameUsed(m_projName)); QCOMPARE(m_projCtrl->projectCount(), 0); assertProjectClosed(proj); assertSpyCaughtProject(spy1, proj); assertSpyCaughtProject(spy2, proj); } void TestProjectController::openCloseOpen() { m_projCtrl->openProject(m_projFilePath.toUrl()); WAIT_FOR_OPEN_SIGNAL; IProject* proj; assertProjectOpened(m_projName, proj); m_projCtrl->closeProject(proj); QSignalSpy* spy = createOpenedSpy(); m_projCtrl->openProject(m_projFilePath.toUrl()); WAIT_FOR_OPEN_SIGNAL; QVERIFY(m_projCtrl->isProjectNameUsed(m_projName)); QCOMPARE(m_projCtrl->projectCount(), 1); assertProjectOpened(m_projName, proj); assertSpyCaughtProject(spy, proj); } void TestProjectController::reopen() { m_projCtrl->setDialogProvider(new DialogProviderFake); m_projCtrl->openProject(m_projFilePath.toUrl()); WAIT_FOR_OPEN_SIGNAL; QSignalSpy* spy = createOpenedSpy(); m_projCtrl->openProject(m_projFilePath.toUrl()); WAIT_FOR_OPEN_SIGNAL; QCOMPARE(m_projCtrl->projectCount(), 1); QVERIFY(m_projCtrl->isProjectNameUsed(m_projName)); IProject* proj; assertProjectOpened(m_projName, proj); assertSpyCaughtProject(spy, proj); } void TestProjectController::reopenWhileLoading() { // Open the same project again while the first is still // loading. The second open request should be blocked. m_projCtrl->setDialogProvider(new DialogProviderFake); QSignalSpy* spy = createOpenedSpy(); m_projCtrl->openProject(m_projFilePath.toUrl()); //m_projCtrl->openProject(m_projFilePath.toUrl()); WAIT_FOR_OPEN_SIGNAL; // wait a bit for a second signal, this should timeout QSignalSpy signal(m_projCtrl, SIGNAL(projectOpened(KDevelop::IProject*))); QVERIFY2(!signal.wait(100), "Received 2 projectOpened signals."); QCOMPARE(m_projCtrl->projectCount(), 1); IProject* proj; assertProjectOpened(m_projName, proj); assertSpyCaughtProject(spy, proj); } void TestProjectController::openMultiple() { QString secondProj("bar"); Path secondCfgUrl = writeProjectConfig(secondProj); QSignalSpy* spy = createOpenedSpy(); m_projCtrl->openProject(m_projFilePath.toUrl()); WAIT_FOR_OPEN_SIGNAL; m_projCtrl->openProject(secondCfgUrl.toUrl()); WAIT_FOR_OPEN_SIGNAL; QCOMPARE(m_projCtrl->projectCount(), 2); IProject *proj1, *proj2; assertProjectOpened(m_projName, proj1); assertProjectOpened(secondProj, proj2); QVERIFY(m_projCtrl->isProjectNameUsed(m_projName)); QVERIFY(m_projCtrl->isProjectNameUsed("bar")); QCOMPARE(spy->size(), 2); IProject* emittedProj1 = (*spy)[0][0].value(); IProject* emittedProj2 = (*spy)[1][0].value(); QCOMPARE(emittedProj1, proj1); QCOMPARE(emittedProj2, proj2); m_tmpConfigs << secondCfgUrl; } /*! Verify that the projectmodel contains a single project. Put this project's * ProjectFolderItem in the output parameter @p RootItem */ #define ASSERT_SINGLE_PROJECT_IN_MODEL(rootItem) \ {\ QCOMPARE(m_projCtrl->projectModel()->rowCount(), 1); \ QModelIndex projIndex = m_projCtrl->projectModel()->index(0,0); \ QVERIFY(projIndex.isValid()); \ ProjectBaseItem* i = m_projCtrl->projectModel()->itemFromIndex( projIndex ); \ QVERIFY(i); \ QVERIFY(i->folder()); \ rootItem = i->folder();\ } void(0) /*! Verify that the projectitem @p item has a single child item * named @p name with url @p url. @p subFolder is an output parameter * that contains the sub-folder projectitem. */ #define ASSERT_SINGLE_SUBFOLDER_IN(item, name, path__, subFolder) \ {\ QCOMPARE(item->rowCount(), 1);\ QCOMPARE(item->folderList().size(), 1);\ ProjectFolderItem* fo = item->folderList()[0];\ QVERIFY(fo);\ QCOMPARE(fo->path(), path__);\ QCOMPARE(fo->folderName(), QString(name));\ subFolder = fo;\ } void(0) #define ASSERT_SINGLE_FILE_IN(rootFolder, name, path__, fileItem)\ {\ QCOMPARE(rootFolder->rowCount(), 1);\ QCOMPARE(rootFolder->fileList().size(), 1);\ fileItem = rootFolder->fileList()[0];\ QVERIFY(fileItem);\ QCOMPARE(fileItem->path(), path__);\ QCOMPARE(fileItem->fileName(), QString(name));\ } void(0) // command void TestProjectController::emptyProject() { // verify that the project model contains a single top-level folder after loading // an empty project assertEmptyProjectModel(); m_projCtrl->openProject(m_projFilePath.toUrl()); WAIT_FOR_OPEN_SIGNAL; Project* proj; assertProjectOpened(m_projName, (KDevelop::IProject*&)proj); FakeFileManager* fileMng = createFileManager(); Q_ASSERT(fileMng); proj->setManagerPlugin(fileMng); proj->reloadModel(); QTest::qWait(100); ProjectFolderItem* rootFolder; ASSERT_SINGLE_PROJECT_IN_MODEL(rootFolder); // check that the project is empty QCOMPARE(rootFolder->rowCount(), 0); QCOMPARE(rootFolder->project()->name(), m_projName); QCOMPARE(rootFolder->path(), m_projFolder); } // command void TestProjectController::singleFile() { // verify that the project model contains a single file in the // top folder. First setup a FakeFileManager with this file m_projCtrl->openProject(m_projFilePath.toUrl()); WAIT_FOR_OPEN_SIGNAL; Project* proj; assertProjectOpened(m_projName, (KDevelop::IProject*&)proj); FakeFileManager* fileMng = createFileManager(); proj->setManagerPlugin(fileMng); Path filePath = Path(m_projFolder, QString::fromLatin1("foobar")); fileMng->addFileToFolder(m_projFolder, filePath); proj->reloadModel(); QTest::qWait(100); // NO signals for reload ... ProjectFolderItem* rootFolder; ASSERT_SINGLE_PROJECT_IN_MODEL(rootFolder); ProjectFileItem* fi; ASSERT_SINGLE_FILE_IN(rootFolder, "foobar", filePath, fi); QCOMPARE(fi->rowCount(), 0); ASSERT_SINGLE_PROJECT_IN_MODEL(rootFolder); ASSERT_SINGLE_FILE_IN(rootFolder, "foobar", filePath, fi); } // command void TestProjectController::singleDirectory() { // verify that the project model contains a single folder in the // top folder. First setup a FakeFileManager with this folder m_projCtrl->openProject(m_projFilePath.toUrl()); WAIT_FOR_OPEN_SIGNAL; Project* proj; assertProjectOpened(m_projName, (KDevelop::IProject*&)proj); Path folderPath = Path(m_projFolder, QString::fromLatin1("foobar/")); FakeFileManager* fileMng = createFileManager(); fileMng->addSubFolderTo(m_projFolder, folderPath); proj->setManagerPlugin(fileMng); proj->reloadModel(); QTest::qWait(100); ProjectFolderItem* rootFolder; ASSERT_SINGLE_PROJECT_IN_MODEL(rootFolder); // check that the project contains a single subfolder ProjectFolderItem* sub; ASSERT_SINGLE_SUBFOLDER_IN(rootFolder, "foobar", folderPath, sub); QCOMPARE(sub->rowCount(), 0); } // command void TestProjectController::fileInSubdirectory() { // verify that the project model contains a single file in a subfolder // First setup a FakeFileManager with this folder + file m_projCtrl->openProject(m_projFilePath.toUrl()); WAIT_FOR_OPEN_SIGNAL; Project* proj; assertProjectOpened(m_projName, (KDevelop::IProject*&)proj); Path folderPath = Path(m_projFolder, QString::fromLatin1("foobar/")); FakeFileManager* fileMng = createFileManager(); fileMng->addSubFolderTo(m_projFolder, folderPath); Path filePath = Path(folderPath, "zoo"); fileMng->addFileToFolder(folderPath, filePath); proj->setManagerPlugin(fileMng); ProjectFolderItem* rootFolder = nullptr; ProjectFolderItem* sub = nullptr; ProjectFileItem* file = nullptr; proj->reloadModel(); QTest::qWait(100); ASSERT_SINGLE_PROJECT_IN_MODEL(rootFolder); ASSERT_SINGLE_SUBFOLDER_IN(rootFolder, "foobar", folderPath, sub); ASSERT_SINGLE_FILE_IN(sub,"zoo",filePath,file); ASSERT_SINGLE_PROJECT_IN_MODEL(rootFolder); ASSERT_SINGLE_SUBFOLDER_IN(rootFolder, "foobar", folderPath, sub); ASSERT_SINGLE_FILE_IN(sub,"zoo",filePath,file); } void TestProjectController::prettyFileName_data() { QTest::addColumn("relativeFilePath"); QTest::newRow("basic") << "foobar.txt"; QTest::newRow("subfolder") << "sub/foobar.txt"; } void TestProjectController::prettyFileName() { QFETCH(QString, relativeFilePath); m_projCtrl->openProject(m_projFilePath.toUrl()); WAIT_FOR_OPEN_SIGNAL; Project* proj; assertProjectOpened(m_projName, (KDevelop::IProject*&)proj); FakeFileManager* fileMng = createFileManager(); proj->setManagerPlugin(fileMng); Path filePath = Path(m_projFolder, relativeFilePath); fileMng->addFileToFolder(m_projFolder, filePath); QCOMPARE(m_projCtrl->prettyFileName(filePath.toUrl(), ProjectController::FormattingOptions::FormatPlain), QString(m_projName + ':' + relativeFilePath)); } ////////////////////// Helpers /////////////////////////////////////////////// Path TestProjectController::writeProjectConfig(const QString& name) { Path configPath = Path(m_scratchDir.absolutePath() + '/' + name + ".kdev4"); QFile f(configPath.pathOrUrl()); f.open(QIODevice::WriteOnly); QTextStream str(&f); str << "[Project]\n" << "Name=" << name << "\n"; f.close(); return configPath; } ////////////////// Custom assertions ///////////////////////////////////////// void TestProjectController::assertProjectOpened(const QString& name, IProject*& proj) { QVERIFY(proj = m_projCtrl->findProjectByName(name)); QVERIFY(m_projCtrl->projects().contains(proj)); } void TestProjectController::assertSpyCaughtProject(QSignalSpy* spy, IProject* proj) { QCOMPARE(spy->size(), 1); IProject* emittedProj = (*spy)[0][0].value(); QCOMPARE(proj, emittedProj); } void TestProjectController::assertProjectClosed(IProject* proj) { IProject* p = m_projCtrl->findProjectByName(proj->name()); QVERIFY(p == 0); QVERIFY(!m_projCtrl->projects().contains(proj)); } void TestProjectController::assertEmptyProjectModel() { ProjectModel* m = m_projCtrl->projectModel(); Q_ASSERT(m); QCOMPARE(m->rowCount(), 0); } ///////////////////// Creation stuff ///////////////////////////////////////// QSignalSpy* TestProjectController::createOpenedSpy() { return new QSignalSpy(m_projCtrl, SIGNAL(projectOpened(KDevelop::IProject*))); } QSignalSpy* TestProjectController::createClosedSpy() { return new QSignalSpy(m_projCtrl, SIGNAL(projectClosed(KDevelop::IProject*))); } QSignalSpy* TestProjectController::createClosingSpy() { return new QSignalSpy(m_projCtrl, SIGNAL(projectClosing(KDevelop::IProject*))); } FakeFileManager* TestProjectController::createFileManager() { FakeFileManager* fileMng = new FakeFileManager; m_fileManagerGarbage << fileMng; return fileMng; } QTEST_MAIN(TestProjectController) #include "moc_test_projectcontroller.cpp" #include "test_projectcontroller.moc" diff --git a/shell/tests/test_shellbuddy.cpp b/shell/tests/test_shellbuddy.cpp index 5be02b0d06..3b87189980 100644 --- a/shell/tests/test_shellbuddy.cpp +++ b/shell/tests/test_shellbuddy.cpp @@ -1,424 +1,424 @@ /*************************************************************************** * Copyright 2011 Martin Heide * * Copyright 2012 Milian Wolff * * * * 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 Library 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 "test_shellbuddy.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../documentcontroller.h" #include "../uicontroller.h" // groups files like foo.l.txt and foo.r.txt such that l is left of r class TestBuddyFinder : public KDevelop::IBuddyDocumentFinder { - virtual bool areBuddies(const QUrl& url1, const QUrl& url2) override + bool areBuddies(const QUrl& url1, const QUrl& url2) override { const QStringList name1 = url1.fileName().split('.'); const QStringList name2 = url2.fileName().split('.'); if (name1.size() != 3 || name2.size() != 3) { return false; } if (name1.last() != name2.last() || name1.first() != name2.first()) { return false; } if (name1.at(1) == name2.at(1)) { return false; } if (name1.at(1) != "l" && name1.at(1) != "r") { return false; } if (name2.at(1) != "l" && name2.at(1) != "r") { return false; } qDebug() << "found buddies: " << url1 << url2; return true; } - virtual bool buddyOrder(const QUrl& url1, const QUrl& /*url2*/) override + bool buddyOrder(const QUrl& url1, const QUrl& /*url2*/) override { const QStringList name1 = url1.fileName().split('.'); return name1.at(1) == "l"; } - virtual QVector getPotentialBuddies(const QUrl& url) const override + QVector getPotentialBuddies(const QUrl& url) const override { Q_UNUSED(url); return QVector(); } }; void TestShellBuddy::initTestCase() { AutoTestShell::init(); TestCore::initialize(); m_documentController = Core::self()->documentController(); m_uiController = Core::self()->uiControllerInternal(); m_finder = new TestBuddyFinder; KDevelop::IBuddyDocumentFinder::addFinder("text/plain", m_finder); } void TestShellBuddy::cleanupTestCase() { KDevelop::IBuddyDocumentFinder::removeFinder("text/plain"); delete m_finder; m_finder = 0; TestCore::shutdown(); } //NOTE: macro for proper line-numbers in test's output in case the check fails #define verifyFilename(view, endOfFilename) \ QVERIFY(view); \ { \ Sublime::UrlDocument *urlDoc = dynamic_cast(view->document()); \ QVERIFY(urlDoc); \ QVERIFY(urlDoc->url().toLocalFile().endsWith(endOfFilename)); \ } void TestShellBuddy::createFile(const QTemporaryDir& dir, const QString& filename) { QFile file(dir.path() + '/' + filename); QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Text)); file.close(); } void TestShellBuddy::enableBuddies(bool enable) { { KConfigGroup uiGroup = KSharedConfig::openConfig()->group("UiSettings"); uiGroup.writeEntry("TabBarArrangeBuddies", (enable ? 1 : 0)); uiGroup.sync(); } Core::self()->uiControllerInternal()->loadSettings(); QCOMPARE(Core::self()->uiControllerInternal()->arrangeBuddies(), enable); } void TestShellBuddy::enableOpenAfterCurrent(bool enable) { { KConfigGroup uiGroup = KSharedConfig::openConfig()->group("UiSettings"); uiGroup.writeEntry("TabBarOpenAfterCurrent", (enable ? 1 : 0)); uiGroup.sync(); } Core::self()->uiControllerInternal()->loadSettings(); QCOMPARE(Core::self()->uiControllerInternal()->openAfterCurrent(), enable); } // ------------------ Tests ------------------------------------------------- void TestShellBuddy::testDeclarationDefinitionOrder() { QCOMPARE(m_documentController->openDocuments().count(), 0); enableBuddies(); enableOpenAfterCurrent(); QTemporaryDir dirA; createFile(dirA, "a.r.txt"); createFile(dirA, "b.r.txt"); createFile(dirA, "c.r.txt"); createFile(dirA, "a.l.txt"); createFile(dirA, "b.l.txt"); createFile(dirA, "c.l.txt"); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "a.r.txt")); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "b.l.txt")); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "c.r.txt")); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "b.r.txt")); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "a.l.txt")); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "c.l.txt")); Sublime::Area *area = m_uiController->activeArea(); Sublime::AreaIndex* areaIndex = area->indexOf(m_uiController->activeSublimeWindow()->activeView()); QCOMPARE(m_documentController->openDocuments().count(), 6); //QCOMPARE(m_uiController->documents().count(), 6); QCOMPARE(areaIndex->viewCount(), 6); qDebug() << dynamic_cast(areaIndex->viewAt(0)->document())->url(); verifyFilename(areaIndex->views().value(0), "a.l.txt"); verifyFilename(areaIndex->views().value(1), "a.r.txt"); verifyFilename(areaIndex->views().value(2), "b.l.txt"); verifyFilename(areaIndex->views().value(3), "b.r.txt"); verifyFilename(areaIndex->views().value(4), "c.l.txt"); verifyFilename(areaIndex->views().value(5), "c.r.txt"); for(int i = 0; i < 6; i++) m_documentController->openDocuments()[0]->close(IDocument::Discard); QCOMPARE(m_documentController->openDocuments().count(), 0); } void TestShellBuddy::testActivation() { QCOMPARE(m_documentController->openDocuments().count(), 0); enableBuddies(); enableOpenAfterCurrent(); QTemporaryDir dirA; createFile(dirA, "a.l.txt"); createFile(dirA, "a.r.txt"); createFile(dirA, "b.r.txt"); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "a.r.txt")); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "a.l.txt")); verifyFilename(m_uiController->activeSublimeWindow()->activeView(), "a.l.txt"); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "b.r.txt")); verifyFilename(m_uiController->activeSublimeWindow()->activeView(), "b.r.txt"); QCOMPARE(m_documentController->openDocuments().count(), 3); for(int i = 0; i < 3; i++) m_documentController->openDocuments()[0]->close(IDocument::Discard); QCOMPARE(m_documentController->openDocuments().count(), 0); } void TestShellBuddy::testDisableBuddies() { /* 3. Deactivate buddy option, Activate open next to active tab Open a.cpp a.l.txt Verify order (a.cpp a.l.txt) Verify that a.l.txt is activated Activate a.cpp Open b.cpp Verify order (a.cpp b.cpp a.l.txt) */ QCOMPARE(m_documentController->openDocuments().count(), 0); enableBuddies(false); enableOpenAfterCurrent(); QTemporaryDir dirA; createFile(dirA, "a.l.txt"); createFile(dirA, "a.r.txt"); createFile(dirA, "b.r.txt"); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "a.r.txt")); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "a.l.txt")); Sublime::Area *area = m_uiController->activeArea(); Sublime::AreaIndex* areaIndex = area->indexOf(m_uiController->activeSublimeWindow()->activeView()); // Buddies disabled => order of tabs should be the order of file opening verifyFilename(areaIndex->views().value(0), "a.r.txt"); verifyFilename(areaIndex->views().value(1), "a.l.txt"); verifyFilename(m_uiController->activeSublimeWindow()->activeView(), "a.l.txt"); //activate a.cpp => new doc should be opened right next to it m_uiController->activeSublimeWindow()->activateView(areaIndex->views().value(0)); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "b.r.txt")); verifyFilename(areaIndex->views().value(0), "a.r.txt"); verifyFilename(areaIndex->views().value(1), "b.r.txt"); verifyFilename(areaIndex->views().value(2), "a.l.txt"); verifyFilename(m_uiController->activeSublimeWindow()->activeView(), "b.r.txt"); QCOMPARE(m_documentController->openDocuments().count(), 3); for(int i = 0; i < 3; i++) m_documentController->openDocuments()[0]->close(IDocument::Discard); QCOMPARE(m_documentController->openDocuments().count(), 0); } void TestShellBuddy::testDisableOpenAfterCurrent() { /* 5. Enable buddy option, Disable open next to active tab Open foo.l.txt bar.cpp foo.cpp Verify order (foo.l.txt foo.cpp bar.cpp) Verify that foo.cpp is activated Open x.cpp => tab must be placed at the end Verify order (foo.l.txt foo.cpp bar.cpp x.cpp) Verify that x.cpp is activated*/ QCOMPARE(m_documentController->openDocuments().count(), 0); enableBuddies(); enableOpenAfterCurrent(false); QTemporaryDir dirA; createFile(dirA, "foo.l.txt"); createFile(dirA, "bar.r.txt"); createFile(dirA, "foo.r.txt"); createFile(dirA, "x.r.txt"); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "foo.l.txt")); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "bar.r.txt")); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "foo.r.txt")); Sublime::Area *area = m_uiController->activeArea(); Sublime::AreaIndex* areaIndex = area->indexOf(m_uiController->activeSublimeWindow()->activeView()); verifyFilename(areaIndex->views().value(0), "foo.l.txt"); verifyFilename(areaIndex->views().value(1), "foo.r.txt"); verifyFilename(areaIndex->views().value(2), "bar.r.txt"); verifyFilename(m_uiController->activeSublimeWindow()->activeView(), "foo.r.txt"); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "x.r.txt")); verifyFilename(areaIndex->views().value(0), "foo.l.txt"); verifyFilename(areaIndex->views().value(1), "foo.r.txt"); verifyFilename(areaIndex->views().value(2), "bar.r.txt"); verifyFilename(areaIndex->views().value(3), "x.r.txt"); verifyFilename(m_uiController->activeSublimeWindow()->activeView(), "x.r.txt"); QCOMPARE(m_documentController->openDocuments().count(), 4); for(int i = 0; i < 4; i++) m_documentController->openDocuments()[0]->close(IDocument::Discard); QCOMPARE(m_documentController->openDocuments().count(), 0); } void TestShellBuddy::testDisableAll() { /* 6. Disable buddy option, Disable open next to active tab Open foo.cpp bar.l.txt foo.l.txt Activate bar.l.txt Open bar.cpp Verify order (foo.cpp bar.l.txt foo.l.txt bar.cpp) Verify that bar.cpp is activated*/ QCOMPARE(m_documentController->openDocuments().count(), 0); enableBuddies(false); enableOpenAfterCurrent(false); QTemporaryDir dirA; createFile(dirA, "foo.l.txt"); createFile(dirA, "foo.r.txt"); createFile(dirA, "bar.l.txt"); createFile(dirA, "bar.r.txt"); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "foo.r.txt")); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "bar.l.txt")); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "foo.l.txt")); Sublime::Area *area = m_uiController->activeArea(); Sublime::AreaIndex* areaIndex = area->indexOf(m_uiController->activeSublimeWindow()->activeView()); //activate bar.l.txt m_uiController->activeSublimeWindow()->activateView(areaIndex->views().value(1)); m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "bar.r.txt")); verifyFilename(areaIndex->views().value(0), "foo.r.txt"); verifyFilename(areaIndex->views().value(1), "bar.l.txt"); verifyFilename(areaIndex->views().value(2), "foo.l.txt"); verifyFilename(areaIndex->views().value(3), "bar.r.txt"); verifyFilename(m_uiController->activeSublimeWindow()->activeView(), "bar.r.txt"); QCOMPARE(m_documentController->openDocuments().count(), 4); for(int i = 0; i < 4; i++) m_documentController->openDocuments()[0]->close(IDocument::Discard); QCOMPARE(m_documentController->openDocuments().count(), 0); } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void TestShellBuddy::testsplitViewBuddies() { Sublime::MainWindow *pMainWindow = m_uiController->activeSublimeWindow(); QCOMPARE(m_documentController->openDocuments().count(), 0); enableBuddies(); enableOpenAfterCurrent(); QTemporaryDir dirA; createFile(dirA, "classA.r.txt"); createFile(dirA, "classA.l.txt"); createFile(dirA, "foo.txt"); Sublime::Area *pCodeArea = m_uiController->activeArea(); QVERIFY(pCodeArea); IDocument *pClassAHeader = m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "classA.l.txt")); QVERIFY(pClassAHeader); Sublime::View *pClassAHeaderView = pMainWindow->activeView(); pClassAHeaderView->setObjectName("classA.l.txt"); // now, create a split view of the active view (pClassAHeader) Sublime::View *pClassAHeaderSplitView = dynamic_cast(pClassAHeader)->createView(); pClassAHeaderSplitView->setObjectName("splitOf" + pMainWindow->activeView()->objectName()); pCodeArea->addView(pClassAHeaderSplitView, pMainWindow->activeView(), Qt::Vertical); // and activate it pMainWindow->activateView(pClassAHeaderSplitView); // get the current view's container from the mainwindow QWidget *pCentral = pMainWindow->centralWidget(); QVERIFY(pCentral); QVERIFY(pCentral->inherits("QWidget")); QWidget *pSplitter = pCentral->findChild(); QVERIFY(pSplitter); QVERIFY(pSplitter->inherits("QSplitter")); Sublime::Container *pLeftContainer = pSplitter->findChildren().at(1); QVERIFY(pLeftContainer); Sublime::Container *pRightContainer = pSplitter->findChildren().at(0); QVERIFY(pRightContainer); // check that it only contains pClassAHeaderSplitView QVERIFY(pRightContainer->count() == 1 && pRightContainer->hasWidget(pClassAHeaderSplitView->widget())); // now open the correponding definition file, classA.r.txt IDocument *pClassAImplem = m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "classA.r.txt")); QVERIFY(pClassAImplem); pMainWindow->activeView()->setObjectName("classA.r.txt"); // and check its presence alongside pClassAHeaderSplitView in pRightContainer QVERIFY(pRightContainer->hasWidget(pClassAHeaderSplitView->widget())); QVERIFY(pRightContainer->hasWidget(pMainWindow->activeView()->widget())); // Now reactivate left side ClassAHeaderview pMainWindow->activateView(pClassAHeaderView); // open another file IDocument *pLeftSideCpp = m_documentController->openDocument(QUrl::fromLocalFile(dirA.path() + "foo.txt")); QVERIFY(pLeftSideCpp); pMainWindow->activeView()->setObjectName("foo.txt"); // and close left side ClassAHeaderview pCodeArea->closeView(pClassAHeaderView); // try to open classAImpl (which is already on the right) // but this time it should open on the left bool successfullyReOpened = m_documentController->openDocument(pClassAImplem); QVERIFY(successfullyReOpened); pMainWindow->activeView()->setObjectName("classA.r.txt"); // and check if it correctly opened on the left side QVERIFY(pLeftContainer->hasWidget(pMainWindow->activeView()->widget())); } QTEST_MAIN(TestShellBuddy) diff --git a/shell/tests/test_testcontroller.cpp b/shell/tests/test_testcontroller.cpp index 94c9686e0e..1e5e101f85 100644 --- a/shell/tests/test_testcontroller.cpp +++ b/shell/tests/test_testcontroller.cpp @@ -1,244 +1,244 @@ /* Unit tests for TestController. Copyright 2012 Miha Čančula This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "test_testcontroller.h" #include #include #include #include #include #include #include #include #include #include using namespace KDevelop; const char* TestSuiteName = "TestTestSuite"; const char* TestSuiteNameTwo = "TestTestSuiteTwo"; const char* TestCaseNameOne = "TestTestCaseOne"; const char* TestCaseNameTwo = "TestTestCaseTwo"; Q_DECLARE_METATYPE(KDevelop::TestResult) Q_DECLARE_METATYPE(KDevelop::ITestSuite*) class FakeTestSuite : public KDevelop::ITestSuite { public: FakeTestSuite(const QString& name, IProject* project, const QStringList& cases = QStringList()) : m_name(name), m_project(project), m_cases(cases) {} - virtual ~FakeTestSuite() {} + ~FakeTestSuite() override {} - virtual IProject* project() const override {return m_project;} - virtual QString name() const override {return m_name;} - virtual QStringList cases() const override {return m_cases;} + IProject* project() const override {return m_project;} + QString name() const override {return m_name;} + QStringList cases() const override {return m_cases;} - virtual IndexedDeclaration declaration() const override; - virtual IndexedDeclaration caseDeclaration(const QString& testCase) const override; + IndexedDeclaration declaration() const override; + IndexedDeclaration caseDeclaration(const QString& testCase) const override; - virtual KJob* launchAllCases(TestJobVerbosity verbosity) override; - virtual KJob* launchCase(const QString& testCase, TestJobVerbosity verbosity) override; - virtual KJob* launchCases(const QStringList& testCases, TestJobVerbosity verbosity) override; + KJob* launchAllCases(TestJobVerbosity verbosity) override; + KJob* launchCase(const QString& testCase, TestJobVerbosity verbosity) override; + KJob* launchCases(const QStringList& testCases, TestJobVerbosity verbosity) override; private: QString m_name; IProject* m_project; QStringList m_cases; }; IndexedDeclaration FakeTestSuite::declaration() const { return IndexedDeclaration(); } IndexedDeclaration FakeTestSuite::caseDeclaration(const QString& testCase) const { Q_UNUSED(testCase); return IndexedDeclaration(); } KJob* FakeTestSuite::launchAllCases(ITestSuite::TestJobVerbosity verbosity) { Q_UNUSED(verbosity); return 0; } KJob* FakeTestSuite::launchCase(const QString& testCase, ITestSuite::TestJobVerbosity verbosity) { Q_UNUSED(testCase); Q_UNUSED(verbosity); return 0; } KJob* FakeTestSuite::launchCases(const QStringList& testCases, ITestSuite::TestJobVerbosity verbosity) { Q_UNUSED(testCases); Q_UNUSED(verbosity); return 0; } void TestTestController::emitTestResult(ITestSuite* suite, TestResult::TestCaseResult caseResult) { TestResult result; result.suiteResult = caseResult; foreach (const QString& testCase, suite->cases()) { result.testCaseResults.insert(testCase, caseResult); } m_testController->notifyTestRunFinished(suite, result); } void TestTestController::initTestCase() { AutoTestShell::init(); TestCore::initialize( Core::NoUi ); m_testController = Core::self()->testControllerInternal(); m_project = new TestProject(Path(), this); qRegisterMetaType("KDevelop::ITestSuite*"); qRegisterMetaType("KDevelop::TestResult"); } void TestTestController::cleanupTestCase() { delete m_project; TestCore::shutdown(); } void TestTestController::addSuite() { FakeTestSuite suite(TestSuiteName, m_project); m_testController->addTestSuite(&suite); ITestSuite* found = m_testController->findTestSuite(m_project, TestSuiteName); QVERIFY(found); QCOMPARE(found->name(), QString(TestSuiteName)); QCOMPARE(found->project(), m_project); m_testController->removeTestSuite(&suite); } void TestTestController::removeSuite() { FakeTestSuite suite(TestSuiteName, m_project); m_testController->addTestSuite(&suite); QVERIFY(m_testController->findTestSuite(m_project, TestSuiteName)); m_testController->removeTestSuite(&suite); QCOMPARE(m_testController->findTestSuite(m_project, TestSuiteName), (ITestSuite*)0); QVERIFY(m_testController->testSuites().isEmpty()); } void TestTestController::replaceSuite() { FakeTestSuite* suiteOne = new FakeTestSuite(TestSuiteName, m_project, QStringList() << TestCaseNameOne); m_testController->addTestSuite(suiteOne); QCOMPARE(m_testController->findTestSuite(m_project, TestSuiteName)->name(), QString(TestSuiteName)); QCOMPARE(m_testController->findTestSuite(m_project, TestSuiteName)->cases().size(), 1); FakeTestSuite* suiteTwo = new FakeTestSuite(TestSuiteName, m_project, QStringList() << TestCaseNameOne << TestCaseNameTwo); m_testController->addTestSuite(suiteTwo); QCOMPARE(m_testController->testSuites().size(), 1); QCOMPARE(m_testController->findTestSuite(m_project, TestSuiteName)->name(), QString(TestSuiteName)); QCOMPARE(m_testController->findTestSuite(m_project, TestSuiteName)->cases().size(), 2); // TestController deletes the old suite when replacing it, so make sure we don't delete suiteOne manually m_testController->removeTestSuite(suiteTwo); delete suiteTwo; } void TestTestController::findByProject() { IProject* otherProject = new TestProject(Path(), this); ITestSuite* suiteOne = new FakeTestSuite(TestSuiteName, m_project); ITestSuite* suiteTwo = new FakeTestSuite(TestSuiteName, otherProject); m_testController->addTestSuite(suiteOne); m_testController->addTestSuite(suiteTwo); QCOMPARE(m_testController->testSuites().size(), 2); QCOMPARE(m_testController->testSuitesForProject(m_project).size(), 1); QCOMPARE(m_testController->testSuitesForProject(m_project).first(), suiteOne); m_testController->removeTestSuite(suiteOne); m_testController->removeTestSuite(suiteTwo); delete suiteOne; delete suiteTwo; delete otherProject; } void TestTestController::testResults() { ITestSuite* suite = new FakeTestSuite(TestSuiteName, m_project); m_testController->addTestSuite(suite); QSignalSpy spy(m_testController, SIGNAL(testRunFinished(KDevelop::ITestSuite*,KDevelop::TestResult))); QVERIFY(spy.isValid()); QList results; results << TestResult::Passed << TestResult::Failed << TestResult::Error << TestResult::Skipped << TestResult::NotRun; foreach (const TestResult::TestCaseResult& result, results) { emitTestResult(suite, result); QCOMPARE(spy.size(), 1); QVariantList arguments = spy.takeFirst(); QCOMPARE(arguments.size(), 2); QVERIFY(arguments.first().canConvert()); QCOMPARE(arguments.first().value(), suite); QVERIFY(arguments.at(1).canConvert()); QCOMPARE(arguments.at(1).value().suiteResult, result); foreach (const QString& testCase, suite->cases()) { QCOMPARE(arguments.at(1).value().testCaseResults[testCase], result); } } QCOMPARE(spy.size(), 0); ITestSuite* suiteTwo = new FakeTestSuite(TestSuiteNameTwo, m_project); m_testController->addTestSuite(suiteTwo); // Verify that only one signal gets emitted even with more suites present emitTestResult(suiteTwo, TestResult::Passed); QCOMPARE(spy.size(), 1); m_testController->removeTestSuite(suite); m_testController->removeTestSuite(suiteTwo); delete suite; delete suiteTwo; } QTEST_GUILESS_MAIN(TestTestController) diff --git a/shell/textdocument.h b/shell/textdocument.h index e790e7f857..54f20e3f60 100644 --- a/shell/textdocument.h +++ b/shell/textdocument.h @@ -1,126 +1,126 @@ /*************************************************************************** * Copyright 2007 Alexander Dymo * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_TEXTDOCUMENT_H #define KDEVPLATFORM_TEXTDOCUMENT_H #include #include #include #include "partdocument.h" #include "shellexport.h" class QMenu; namespace KTextEditor { class View; } namespace KDevelop { /** Text document which represents KTextEditor documents. Usually Kate documents are represented by this class but TextDocument is not limited to Kate. Each conforming text editor will work. */ class KDEVPLATFORMSHELL_EXPORT TextDocument: public PartDocument { Q_OBJECT public: TextDocument(const QUrl &url, ICore*, const QString& encoding ); - virtual ~TextDocument(); + ~TextDocument() override; - virtual QWidget *createViewWidget(QWidget *parent = 0) override; - virtual KParts::Part *partForView(QWidget *view) const override; - virtual bool close(DocumentSaveMode mode = Default) override; + QWidget *createViewWidget(QWidget *parent = 0) override; + KParts::Part *partForView(QWidget *view) const override; + bool close(DocumentSaveMode mode = Default) override; - virtual bool save(DocumentSaveMode mode = Default) override; - virtual DocumentState state() const override; + bool save(DocumentSaveMode mode = Default) override; + DocumentState state() const override; - virtual KTextEditor::Cursor cursorPosition() const override; - virtual void setCursorPosition(const KTextEditor::Cursor &cursor) override; + KTextEditor::Cursor cursorPosition() const override; + void setCursorPosition(const KTextEditor::Cursor &cursor) override; - virtual KTextEditor::Range textSelection() const override; - virtual void setTextSelection(const KTextEditor::Range &range) override; + KTextEditor::Range textSelection() const override; + void setTextSelection(const KTextEditor::Range &range) override; - virtual QString textLine() const override; - virtual QString textWord() const override; + QString textLine() const override; + QString textWord() const override; - virtual bool isTextDocument() const override; - virtual KTextEditor::Document* textDocument() const override; + bool isTextDocument() const override; + KTextEditor::Document* textDocument() const override; - virtual QString documentType() const override; + QString documentType() const override; - virtual QIcon defaultIcon() const override; + QIcon defaultIcon() const override; - virtual KTextEditor::View* activeTextView() const override; + KTextEditor::View* activeTextView() const override; public Q_SLOTS: - virtual void reload() override; + void reload() override; protected: - virtual Sublime::View *newView(Sublime::Document *doc) override; + Sublime::View *newView(Sublime::Document *doc) override; private: Q_PRIVATE_SLOT(d, void saveSessionConfig()); Q_PRIVATE_SLOT(d, void modifiedOnDisk(KTextEditor::Document *, bool, KTextEditor::ModificationInterface::ModifiedOnDiskReason)); void newDocumentStatus(KTextEditor::Document*); void populateContextMenu(KTextEditor::View*, QMenu*); void textChanged(KTextEditor::Document*); void documentUrlChanged(KTextEditor::Document*); void slotDocumentLoaded(); void documentSaved(KTextEditor::Document*,bool); void repositoryCheckFinished(bool); struct TextDocumentPrivate * const d; friend struct TextDocumentPrivate; }; class KDEVPLATFORMSHELL_EXPORT TextView : public Sublime::View { Q_OBJECT public: explicit TextView(TextDocument* doc); - virtual ~TextView(); + ~TextView() override; QWidget *createWidget(QWidget *parent = 0) override; KTextEditor::View *textView() const; - virtual QString viewStatus() const override; - virtual QString viewState() const override; - virtual void setState(const QString& state) override; + QString viewStatus() const override; + QString viewState() const override; + void setState(const QString& state) override; void setInitialRange(const KTextEditor::Range& range); KTextEditor::Range initialRange() const; private: void sendStatusChanged(); struct TextViewPrivate* const d; }; } #endif diff --git a/shell/uicontroller.cpp b/shell/uicontroller.cpp index e62102fe61..44f35bdec1 100644 --- a/shell/uicontroller.cpp +++ b/shell/uicontroller.cpp @@ -1,740 +1,740 @@ /*************************************************************************** * Copyright 2007 Alexander Dymo * * * * 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 Library 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 "uicontroller.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "core.h" #include "configpage.h" #include "configdialog.h" #include "debug.h" #include "editorconfigpage.h" #include "shellextension.h" #include "partcontroller.h" #include "plugincontroller.h" #include "mainwindow.h" #include "partdocument.h" #include "textdocument.h" #include "documentcontroller.h" #include #include "workingsetcontroller.h" #include "workingsets/workingset.h" #include "settings/bgpreferences.h" #include "settings/languagepreferences.h" #include "settings/environmentpreferences.h" #include "settings/pluginpreferences.h" #include "settings/projectpreferences.h" #include "settings/sourceformattersettings.h" #include "settings/uipreferences.h" #include "settings/templateconfig.h" namespace KDevelop { class UiControllerPrivate { public: UiControllerPrivate(UiController *controller) : areasRestored(false), m_controller(controller) { if (Core::self()->workingSetControllerInternal()) Core::self()->workingSetControllerInternal()->initializeController(m_controller); m_controller->connect(m_controller, &Sublime::Controller::mainWindowAdded, m_controller, &UiController::mainWindowAdded); QMap desired; desired["org.kdevelop.ClassBrowserView"] = Sublime::Left; desired["org.kdevelop.DocumentsView"] = Sublime::Left; desired["org.kdevelop.ProjectsView"] = Sublime::Left; desired["org.kdevelop.FileManagerView"] = Sublime::Left; desired["org.kdevelop.ProblemReporterView"] = Sublime::Bottom; desired["org.kdevelop.OutputView"] = Sublime::Bottom; desired["org.kdevelop.ContextBrowser"] = Sublime::Bottom; desired["org.kdevelop.KonsoleView"] = Sublime::Bottom; desired["org.kdevelop.SnippetView"] = Sublime::Right; desired["org.kdevelop.ExternalScriptView"] = Sublime::Right; Sublime::Area* a = new Sublime::Area(m_controller, "code", i18n("Code")); a->setDesiredToolViews(desired); a->setIconName("document-edit"); m_controller->addDefaultArea(a); desired.clear(); desired["org.kdevelop.debugger.VariablesView"] = Sublime::Left; desired["org.kdevelop.debugger.BreakpointsView"] = Sublime::Bottom; desired["org.kdevelop.debugger.StackView"] = Sublime::Bottom; desired["org.kdevelop.debugger.ConsoleView"] = Sublime::Bottom; desired["org.kdevelop.KonsoleView"] = Sublime::Bottom; a = new Sublime::Area(m_controller, "debug", i18n("Debug")); a->setDesiredToolViews(desired); a->setIconName("tools-report-bug"); m_controller->addDefaultArea(a); desired.clear(); desired["org.kdevelop.ProjectsView"] = Sublime::Left; desired["org.kdevelop.PatchReview"] = Sublime::Bottom; a = new Sublime::Area(m_controller, "review", i18n("Review")); a->setDesiredToolViews(desired); a->setIconName("applications-engineering"); m_controller->addDefaultArea(a); if(!(Core::self()->setupFlags() & Core::NoUi)) { defaultMainWindow = new MainWindow(m_controller); m_controller->addMainWindow(defaultMainWindow); activeSublimeWindow = defaultMainWindow; } else { activeSublimeWindow = defaultMainWindow = 0; } m_assistantTimer.setSingleShot(true); m_assistantTimer.setInterval(100); } void widgetChanged(QWidget*, QWidget* now) { if (now) { Sublime::MainWindow* win = qobject_cast(now->window()); if( win ) { activeSublimeWindow = win; } } } Core *core; QPointer defaultMainWindow; QMap factoryDocuments; QPointer activeSublimeWindow; bool areasRestored; /// QWidget implementing IToolViewActionListener interface, or null QPointer activeActionListener; QTimer m_assistantTimer; private: UiController *m_controller; }; class UiToolViewFactory: public Sublime::ToolFactory { public: UiToolViewFactory(IToolViewFactory *factory): m_factory(factory) {} - ~UiToolViewFactory() { delete m_factory; } - virtual QWidget* create(Sublime::ToolDocument *doc, QWidget *parent = 0) override + ~UiToolViewFactory() override { delete m_factory; } + QWidget* create(Sublime::ToolDocument *doc, QWidget *parent = 0) override { Q_UNUSED( doc ); return m_factory->create(parent); } - virtual QList< QAction* > contextMenuActions(QWidget* viewWidget) const override + QList< QAction* > contextMenuActions(QWidget* viewWidget) const override { return m_factory->contextMenuActions( viewWidget ); } QList toolBarActions( QWidget* viewWidget ) const override { return m_factory->toolBarActions( viewWidget ); } QString id() const override { return m_factory->id(); } private: IToolViewFactory *m_factory; }; class ViewSelectorItem: public QListWidgetItem { public: ViewSelectorItem(const QString &text, QListWidget *parent = 0, int type = Type) :QListWidgetItem(text, parent, type) {} IToolViewFactory *factory; }; class NewToolViewListWidget: public QListWidget { Q_OBJECT public: NewToolViewListWidget(MainWindow *mw, QWidget* parent = 0) :QListWidget(parent), m_mw(mw) { connect(this, &NewToolViewListWidget::doubleClicked, this, &NewToolViewListWidget::addNewToolViewByDoubleClick); } Q_SIGNALS: void addNewToolView(MainWindow *mw, QListWidgetItem *item); private Q_SLOTS: void addNewToolViewByDoubleClick(QModelIndex index) { QListWidgetItem *item = itemFromIndex(index); // Disable item so that the toolview can not be added again. item->setFlags(item->flags() & ~Qt::ItemIsEnabled); emit addNewToolView(m_mw, item); } private: MainWindow *m_mw; }; UiController::UiController(Core *core) :Sublime::Controller(0), IUiController(), d(new UiControllerPrivate(this)) { setObjectName("UiController"); d->core = core; if (!defaultMainWindow() || (Core::self()->setupFlags() & Core::NoUi)) return; connect(qApp, &QApplication::focusChanged, this, [&] (QWidget* old, QWidget* now) { d->widgetChanged(old, now); } ); setupActions(); } UiController::~UiController() { delete d; } void UiController::setupActions() { } void UiController::mainWindowAdded(Sublime::MainWindow* mainWindow) { connect(mainWindow, &MainWindow::activeToolViewChanged, this, &UiController::slotActiveToolViewChanged); connect(mainWindow, &MainWindow::areaChanged, this, &UiController::slotAreaChanged); // also check after area reconstruction } // FIXME: currently, this always create new window. Probably, // should just rename it. void UiController::switchToArea(const QString &areaName, SwitchMode switchMode) { if (switchMode == ThisWindow) { showArea(areaName, activeSublimeWindow()); return; } MainWindow *main = new MainWindow(this); addMainWindow(main); showArea(areaName, main); main->initialize(); // WTF? First, enabling this code causes crashes since we // try to disconnect some already-deleted action, or something. // Second, this code will disconnection the clients from guiFactory // of the previous main window. Ick! #if 0 //we need to add all existing guiclients to the new mainwindow //@todo adymo: add only ones that belong to the area (when the area code is there) foreach (KXMLGUIClient *client, oldMain->guiFactory()->clients()) main->guiFactory()->addClient(client); #endif main->show(); } QWidget* UiController::findToolView(const QString& name, IToolViewFactory *factory, FindFlags flags) { if(!d->areasRestored || !activeArea()) return 0; QList< Sublime::View* > views = activeArea()->toolViews(); foreach(Sublime::View* view, views) { Sublime::ToolDocument *doc = dynamic_cast(view->document()); if(doc && doc->title() == name && view->widget()) { if(flags & Raise) view->requestRaise(); return view->widget(); } } QWidget* ret = 0; if(flags & Create) { Sublime::ToolDocument* doc = d->factoryDocuments.value(factory); if(!doc) { doc = new Sublime::ToolDocument(name, this, new UiToolViewFactory(factory)); d->factoryDocuments.insert(factory, doc); } Sublime::View* view = addToolViewToArea(factory, doc, activeArea()); if(view) ret = view->widget(); if(flags & Raise) findToolView(name, factory, Raise); } return ret; } void UiController::raiseToolView(QWidget* toolViewWidget) { if(!d->areasRestored) return; QList< Sublime::View* > views = activeArea()->toolViews(); foreach(Sublime::View* view, views) { if(view->widget() == toolViewWidget) { view->requestRaise(); return; } } } void UiController::addToolView(const QString & name, IToolViewFactory *factory) { if (!factory) return; qCDebug(SHELL) ; Sublime::ToolDocument *doc = new Sublime::ToolDocument(name, this, new UiToolViewFactory(factory)); d->factoryDocuments[factory] = doc; /* Until areas are restored, we don't know which views should be really added, and which not, so we just record view availability. */ if (d->areasRestored) { foreach (Sublime::Area* area, allAreas()) { addToolViewToArea(factory, doc, area); } } } void KDevelop::UiController::raiseToolView(Sublime::View * view) { foreach( Sublime::Area* area, allAreas() ) { if( area->toolViews().contains( view ) ) area->raiseToolView( view ); } slotActiveToolViewChanged(view); } void UiController::slotAreaChanged(Sublime::Area*) { // this slot gets call if an area in *any* MainWindow changed // so let's first get the "active area" const auto area = activeSublimeWindow()->area(); if (area) { // walk through shown tool views and maku sure the const auto shownIds = area->shownToolViews(Sublime::AllPositions); foreach (Sublime::View* toolView, area->toolViews()) { if (shownIds.contains(toolView->document()->documentSpecifier())) { slotActiveToolViewChanged(toolView); } } } } void UiController::slotActiveToolViewChanged(Sublime::View* view) { if (!view) { return; } // record the last active tool view action listener if (qobject_cast(view->widget())) { d->activeActionListener = view->widget(); } } void KDevelop::UiController::removeToolView(IToolViewFactory *factory) { if (!factory) return; qCDebug(SHELL) ; //delete the tooldocument Sublime::ToolDocument *doc = d->factoryDocuments.value(factory); ///@todo adymo: on document deletion all its views shall be also deleted foreach (Sublime::View *view, doc->views()) { foreach (Sublime::Area *area, allAreas()) if (area->removeToolView(view)) view->deleteLater(); } d->factoryDocuments.remove(factory); delete doc; } Sublime::Area *UiController::activeArea() { Sublime::MainWindow *m = activeSublimeWindow(); if (m) return activeSublimeWindow()->area(); return 0; } Sublime::MainWindow *UiController::activeSublimeWindow() { return d->activeSublimeWindow; } MainWindow *UiController::defaultMainWindow() { return d->defaultMainWindow; } void UiController::initialize() { defaultMainWindow()->initialize(); } void UiController::cleanup() { foreach (Sublime::MainWindow* w, mainWindows()) w->saveSettings(); saveAllAreas(KSharedConfig::openConfig()); } void UiController::selectNewToolViewToAdd(MainWindow *mw) { if (!mw || !mw->area()) return; QDialog *dia = new QDialog(mw); dia->setWindowTitle(i18n("Select Tool View to Add")); auto mainLayout = new QVBoxLayout(dia); NewToolViewListWidget *list = new NewToolViewListWidget(mw, dia); list->setSelectionMode(QAbstractItemView::ExtendedSelection); list->setSortingEnabled(true); for (QMap::const_iterator it = d->factoryDocuments.constBegin(); it != d->factoryDocuments.constEnd(); ++it) { ViewSelectorItem *item = new ViewSelectorItem(it.value()->title(), list); item->factory = it.key(); if (!item->factory->allowMultiple() && toolViewPresent(it.value(), mw->area())) { // Disable item if the toolview is already present. item->setFlags(item->flags() & ~Qt::ItemIsEnabled); } list->addItem(item); } list->setFocus(); connect(list, &NewToolViewListWidget::addNewToolView, this, &UiController::addNewToolView); mainLayout->addWidget(list); auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); auto okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return); dia->connect(buttonBox, &QDialogButtonBox::accepted, dia, &QDialog::accept); dia->connect(buttonBox, &QDialogButtonBox::rejected, dia, &QDialog::reject); mainLayout->addWidget(buttonBox); if (dia->exec() == QDialog::Accepted) { foreach (QListWidgetItem* item, list->selectedItems()) { addNewToolView(mw, item); } } delete dia; } void UiController::addNewToolView(MainWindow *mw, QListWidgetItem* item) { ViewSelectorItem *current = static_cast(item); Sublime::ToolDocument *doc = d->factoryDocuments[current->factory]; Sublime::View *view = doc->createView(); mw->area()->addToolView(view, Sublime::dockAreaToPosition(current->factory->defaultPosition())); current->factory->viewCreated(view); } void UiController::showSettingsDialog() { auto editorConfigPage = new EditorConfigPage(activeMainWindow()); auto languageConfigPage = new LanguagePreferences(activeMainWindow()); auto configPages = QVector { new UiPreferences(activeMainWindow()), new PluginPreferences(activeMainWindow()), new SourceFormatterSettings(activeMainWindow()), new ProjectPreferences(activeMainWindow()), new EnvironmentPreferences(QString(), activeMainWindow()), new BGPreferences(activeMainWindow()), new TemplateConfig(activeMainWindow()), editorConfigPage }; ConfigDialog cfgDlg(configPages, activeMainWindow()); auto addPluginPages = [&](IPlugin* plugin) { for (int i = 0, numPages = plugin->configPages(); i < numPages; ++i) { auto page = plugin->configPage(i, &cfgDlg); if(page && page->configPageType() == ConfigPage::LanguageConfigPage){ cfgDlg.addSubConfigPage(languageConfigPage, page); } else { // insert them before the editor config page cfgDlg.addConfigPage(page, editorConfigPage); } } }; cfgDlg.addConfigPage(languageConfigPage, configPages[5]); for (IPlugin* plugin : ICore::self()->pluginController()->loadedPlugins()) { addPluginPages(plugin); } // TODO: only load settings if a UI related page was changed? connect(&cfgDlg, &ConfigDialog::configSaved, activeSublimeWindow(), &Sublime::MainWindow::loadSettings); // make sure that pages get added whenever a new plugin is loaded (probably from the plugin selection dialog) // removal on plugin unload is already handled in ConfigDialog connect(ICore::self()->pluginController(), &IPluginController::pluginLoaded, &cfgDlg, addPluginPages); cfgDlg.exec(); } Sublime::Controller* UiController::controller() { return this; } KParts::MainWindow *UiController::activeMainWindow() { return activeSublimeWindow(); } void UiController::saveArea(Sublime::Area * area, KConfigGroup & group) { area->save(group); if (!area->workingSet().isEmpty()) { WorkingSet* set = Core::self()->workingSetControllerInternal()->getWorkingSet(area->workingSet()); set->saveFromArea(area, area->rootIndex()); } } void UiController::loadArea(Sublime::Area * area, const KConfigGroup & group) { area->load(group); if (!area->workingSet().isEmpty()) { WorkingSet* set = Core::self()->workingSetControllerInternal()->getWorkingSet(area->workingSet()); Q_ASSERT(set->isConnected(area)); Q_UNUSED(set); } } void UiController::saveAllAreas(KSharedConfigPtr config) { KConfigGroup uiConfig(config, "User Interface"); int wc = mainWindows().size(); uiConfig.writeEntry("Main Windows Count", wc); for (int w = 0; w < wc; ++w) { KConfigGroup mainWindowConfig(&uiConfig, QStringLiteral("Main Window %1").arg(w)); foreach (Sublime::Area* defaultArea, defaultAreas()) { // FIXME: using object name seems ugly. QString type = defaultArea->objectName(); Sublime::Area* area = this->area(w, type); KConfigGroup areaConfig(&mainWindowConfig, "Area " + type); areaConfig.deleteGroup(); areaConfig.writeEntry("id", type); saveArea(area, areaConfig); areaConfig.sync(); } } uiConfig.sync(); } void UiController::loadAllAreas(KSharedConfigPtr config) { KConfigGroup uiConfig(config, "User Interface"); int wc = uiConfig.readEntry("Main Windows Count", 1); /* It is expected the main windows are restored before restoring areas. */ if (wc > mainWindows().size()) wc = mainWindows().size(); QList changedAreas; /* Offer all toolviews to the default areas. */ foreach (Sublime::Area *area, defaultAreas()) { QMap::const_iterator i, e; for (i = d->factoryDocuments.constBegin(), e = d->factoryDocuments.constEnd(); i != e; ++i) { addToolViewIfWanted(i.key(), i.value(), area); } } /* Restore per-windows areas. */ for (int w = 0; w < wc; ++w) { KConfigGroup mainWindowConfig(&uiConfig, QStringLiteral("Main Window %1").arg(w)); Sublime::MainWindow *mw = mainWindows()[w]; /* We loop over default areas. This means that if the config file has an area of some type that is not in default set, we'd just ignore it. I think it's fine -- the model were a given mainwindow can has it's own area types not represented in the default set is way too complex. */ foreach (Sublime::Area* defaultArea, defaultAreas()) { QString type = defaultArea->objectName(); Sublime::Area* area = this->area(w, type); KConfigGroup areaConfig(&mainWindowConfig, "Area " + type); qCDebug(SHELL) << "Trying to restore area " << type; /* This is just an easy check that a group exists, to avoid "restoring" area from empty config group, wiping away programmatically installed defaults. */ if (areaConfig.readEntry("id", "") == type) { qCDebug(SHELL) << "Restoring area " << type; loadArea(area, areaConfig); } // At this point we know which toolviews the area wants. // Tender all tool views we have. QMap::const_iterator i, e; for (i = d->factoryDocuments.constBegin(), e = d->factoryDocuments.constEnd(); i != e; ++i) { addToolViewIfWanted(i.key(), i.value(), area); } } // Force reload of the changes. showAreaInternal(mw->area(), mw); mw->enableAreaSettingsSave(); } d->areasRestored = true; } void UiController::addToolViewToDockArea(IToolViewFactory* factory, Qt::DockWidgetArea area) { addToolViewToArea(factory, d->factoryDocuments.value(factory), activeArea(), Sublime::dockAreaToPosition(area)); } bool UiController::toolViewPresent(Sublime::ToolDocument* doc, Sublime::Area* area) { foreach (Sublime::View *view, doc->views()) { if( area->toolViews().contains( view ) ) return true; } return false; } void UiController::addToolViewIfWanted(IToolViewFactory* factory, Sublime::ToolDocument* doc, Sublime::Area* area) { if (area->wantToolView(factory->id())) { addToolViewToArea(factory, doc, area); } } Sublime::View* UiController::addToolViewToArea(IToolViewFactory* factory, Sublime::ToolDocument* doc, Sublime::Area* area, Sublime::Position p) { Sublime::View* view = doc->createView(); area->addToolView( view, p == Sublime::AllPositions ? Sublime::dockAreaToPosition(factory->defaultPosition()) : p); connect(view, &Sublime::View::raise, this, static_cast(&UiController::raiseToolView)); factory->viewCreated(view); return view; } void UiController::registerStatus(QObject* status) { Sublime::MainWindow* w = activeSublimeWindow(); if (!w) return; MainWindow* mw = qobject_cast(w); if (!mw) return; mw->registerStatus(status); } void UiController::showErrorMessage(const QString& message, int timeout) { Sublime::MainWindow* w = activeSublimeWindow(); if (!w) return; MainWindow* mw = qobject_cast(w); if (!mw) return; QMetaObject::invokeMethod(mw, "showErrorMessage", Q_ARG(QString, message), Q_ARG(int, timeout)); } const QMap< IToolViewFactory*, Sublime::ToolDocument* >& UiController::factoryDocuments() const { return d->factoryDocuments; } QWidget* UiController::activeToolViewActionListener() const { return d->activeActionListener; } QList UiController::allAreas() const { return Sublime::Controller::allAreas(); } } #include "uicontroller.moc" #include "moc_uicontroller.cpp" diff --git a/shell/uicontroller.h b/shell/uicontroller.h index b3bc4175b0..88e3da92b8 100644 --- a/shell/uicontroller.h +++ b/shell/uicontroller.h @@ -1,129 +1,129 @@ /*************************************************************************** * Copyright 2007 Alexander Dymo * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_UICONTROLLER_H #define KDEVPLATFORM_UICONTROLLER_H #include "shellexport.h" #include #include #include #include class QListWidgetItem; namespace Sublime { class AreaIndex; class ToolDocument; } namespace KDevelop { class Core; class MainWindow; class KDEVPLATFORMSHELL_EXPORT UiController: public Sublime::Controller, public IUiController { Q_OBJECT public: explicit UiController(Core *core); - virtual ~UiController(); + ~UiController() override; /** @return area for currently active sublime mainwindow or 0 if no sublime mainwindow is active.*/ - virtual Sublime::Area *activeArea() override; + Sublime::Area *activeArea() override; /** @return active sublime mainwindow or 0 if no such mainwindow is active.*/ virtual Sublime::MainWindow *activeSublimeWindow(); /** @return active sublime mainwindow or 0 if no such mainwindow is active.*/ - virtual KParts::MainWindow *activeMainWindow() override; + KParts::MainWindow *activeMainWindow() override; /** @return default main window - the main window for default area in the shell. No guarantee is given that it always exists so this method may return 0.*/ MainWindow *defaultMainWindow(); - virtual void switchToArea(const QString &areaName, SwitchMode switchMode) override; + void switchToArea(const QString &areaName, SwitchMode switchMode) override; - virtual void addToolView(const QString &name, IToolViewFactory *factory) override; - virtual void removeToolView(IToolViewFactory *factory) override; + void addToolView(const QString &name, IToolViewFactory *factory) override; + void removeToolView(IToolViewFactory *factory) override; - virtual QWidget* findToolView(const QString& name, IToolViewFactory *factory, FindFlags flags) override; - virtual void raiseToolView(QWidget* toolViewWidget) override; + QWidget* findToolView(const QString& name, IToolViewFactory *factory, FindFlags flags) override; + void raiseToolView(QWidget* toolViewWidget) override; void selectNewToolViewToAdd(MainWindow *mw); void initialize(); void cleanup(); void showSettingsDialog(); Sublime::Controller* controller() override; void mainWindowAdded(Sublime::MainWindow* mainWindow); void saveAllAreas(KSharedConfigPtr config); void saveArea(Sublime::Area* area, KConfigGroup & group); void loadAllAreas(KSharedConfigPtr config); void loadArea(Sublime::Area* area, const KConfigGroup & group); /*! @p status must implement KDevelop::IStatus */ - virtual void registerStatus(QObject* status) override; + void registerStatus(QObject* status) override; - virtual void showErrorMessage(const QString& message, int timeout) override; + void showErrorMessage(const QString& message, int timeout) override; /// Returns list of available view factories together with their ToolDocuments. /// @see addToolView(), removeToolView(), findToolView() const QMap& factoryDocuments() const; /// Adds a tool view in the active area to the dock area @p area. /// @see activeArea() void addToolViewToDockArea(KDevelop::IToolViewFactory* factory, Qt::DockWidgetArea area); bool toolViewPresent(Sublime::ToolDocument* doc, Sublime::Area* area); - virtual QWidget* activeToolViewActionListener() const override; + QWidget* activeToolViewActionListener() const override; - virtual QList allAreas() const override; + QList allAreas() const override; public Q_SLOTS: void raiseToolView(Sublime::View * view); private Q_SLOTS: void addNewToolView(MainWindow* mw, QListWidgetItem* item); void slotAreaChanged(Sublime::Area* area); void slotActiveToolViewChanged(Sublime::View* view); private: void addToolViewIfWanted(IToolViewFactory* factory, Sublime::ToolDocument* doc, Sublime::Area* area); Sublime::View* addToolViewToArea(IToolViewFactory* factory, Sublime::ToolDocument* doc, Sublime::Area* area, Sublime::Position p=Sublime::AllPositions); void setupActions(); class UiControllerPrivate* const d; friend class UiControllerPrivate; Q_PRIVATE_SLOT(d, void widgetChanged(QWidget*,QWidget*)) }; } #endif diff --git a/shell/watcheddocumentset.h b/shell/watcheddocumentset.h index f175db26b1..7a53703a91 100644 --- a/shell/watcheddocumentset.h +++ b/shell/watcheddocumentset.h @@ -1,133 +1,133 @@ /* * KDevelop Problem Reporter * * Copyright 2010 Dmitry Risenberg * * 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. */ #ifndef KDEVPLATFORM_PLUGIN_WATCHEDDOCUMENTSET_H #define KDEVPLATFORM_PLUGIN_WATCHEDDOCUMENTSET_H #include #include #include #include "problemconstants.h" namespace KDevelop { class IDocument; class IProject; class ProjectFileItem; class Path; /** * Helper class that tracks set of documents and notifies its owner whenever this set changes. Derived classes implement different tracking strategies. */ class WatchedDocumentSet : public QObject { Q_OBJECT public: typedef QSet DocumentSet; explicit WatchedDocumentSet(QObject* parent); virtual DocumentSet get() const; virtual void setCurrentDocument(const IndexedString& url); virtual ProblemScope getScope() const = 0; - virtual ~WatchedDocumentSet() {} + ~WatchedDocumentSet() override {} signals: void changed(); protected: DocumentSet m_documents; }; /** * Tracks a document that is current at any given moment. * When a new file is activated, it becomes tracked instead of the old one. */ class CurrentDocumentSet : public WatchedDocumentSet { Q_OBJECT public: explicit CurrentDocumentSet(const IndexedString& document, QObject* parent); - virtual void setCurrentDocument(const IndexedString& url) override; - virtual ProblemScope getScope() const override; + void setCurrentDocument(const IndexedString& url) override; + ProblemScope getScope() const override; }; /** * Tracks all open documents. */ class OpenDocumentSet : public WatchedDocumentSet { Q_OBJECT public: explicit OpenDocumentSet(QObject* parent); - virtual ProblemScope getScope() const override; + ProblemScope getScope() const override; private slots: void documentClosed(IDocument* doc); void documentCreated(IDocument* doc); }; /** * Tracks documents that are in the same project as the current file. * If current file is not in any project, none are tracked. */ class ProjectSet : public WatchedDocumentSet { Q_OBJECT public: explicit ProjectSet(QObject* parent); protected: void trackProjectFiles(const IProject* project); protected slots: void fileAdded(ProjectFileItem*); void fileRemoved(ProjectFileItem* file); void fileRenamed(const Path& oldFile, ProjectFileItem* newFile); }; /** * Tracks files in all open projects. */ class CurrentProjectSet : public ProjectSet { Q_OBJECT public: explicit CurrentProjectSet(const IndexedString& document, QObject* parent); - virtual void setCurrentDocument(const IndexedString& url) override; - virtual ProblemScope getScope() const override; + void setCurrentDocument(const IndexedString& url) override; + ProblemScope getScope() const override; private: void setCurrentDocumentInternal(const IndexedString& url); // to avoid virtual in constructor IProject* m_currentProject; }; class AllProjectSet : public ProjectSet { Q_OBJECT public: explicit AllProjectSet(QObject* parent); - virtual ProblemScope getScope() const override; + ProblemScope getScope() const override; }; } #endif // KDEVPLATFORM_PLUGIN_WATCHEDDOCUMENTSET_H diff --git a/shell/workingsets/workingsetfilelabel.h b/shell/workingsets/workingsetfilelabel.h index 1c384a89e5..513acfd0ca 100644 --- a/shell/workingsets/workingsetfilelabel.h +++ b/shell/workingsets/workingsetfilelabel.h @@ -1,49 +1,49 @@ /* Copyright David Nolden This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef KDEVPLATFORM_WORKINGSETFILELABEL_H #define KDEVPLATFORM_WORKINGSETFILELABEL_H #include class QMouseEvent; namespace KDevelop { class WorkingSetFileLabel : public QLabel { Q_OBJECT public: WorkingSetFileLabel(); - virtual void mouseReleaseEvent(QMouseEvent* ev) override; + void mouseReleaseEvent(QMouseEvent* ev) override; void setIsActiveFile(bool active); bool isActive() const; void emitClicked(); Q_SIGNALS: void clicked(); private: bool m_isActive; }; } #endif // KDEVPLATFORM_WORKINGSETFILELABEL_H diff --git a/shell/workingsets/workingsettoolbutton.h b/shell/workingsets/workingsettoolbutton.h index e04144cad4..a2e1dadbdd 100644 --- a/shell/workingsets/workingsettoolbutton.h +++ b/shell/workingsets/workingsettoolbutton.h @@ -1,64 +1,64 @@ /* Copyright David Nolden This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef KDEVPLATFORM_WORKINGSETTOOLBUTTON_H #define KDEVPLATFORM_WORKINGSETTOOLBUTTON_H #include namespace KDevelop { class MainWindow; class WorkingSet; /** * @NOTE: This button should be hidden when it is not associated to any set! */ class WorkingSetToolButton : public QToolButton { Q_OBJECT public: WorkingSetToolButton(QWidget* parent, WorkingSet* set); void disableTooltip() { m_toolTipEnabled = false; } WorkingSet* workingSet() const; void setWorkingSet(WorkingSet* set); public slots: void closeSet(bool ask = false); void loadSet(); void duplicateSet(); void mergeSet(); void subtractSet(); void intersectSet(); void buttonTriggered(); void showTooltip(); private: - virtual void contextMenuEvent(QContextMenuEvent* ev) override; - virtual bool event(QEvent* e) override; + void contextMenuEvent(QContextMenuEvent* ev) override; + bool event(QEvent* e) override; WorkingSet* m_set; bool m_toolTipEnabled; }; } #endif // KDEVPLATFORM_WORKINGSETTOOLBUTTON_H diff --git a/shell/workingsets/workingsetwidget.h b/shell/workingsets/workingsetwidget.h index a150fac6c5..11615cbed0 100644 --- a/shell/workingsets/workingsetwidget.h +++ b/shell/workingsets/workingsetwidget.h @@ -1,57 +1,57 @@ /* Copyright David Nolden Copyright 2010 Milian Wolff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef KDEVPLATFORM_WORKINGSETWIDGET_H #define KDEVPLATFORM_WORKINGSETWIDGET_H #include #include "workingsettoolbutton.h" namespace Sublime { class Area; } namespace KDevelop { class WorkingSetController; class WorkingSet; /** * One instance of this widget is created per area switcher tab, showing * the currently opened working set for this area. */ class WorkingSetWidget : public WorkingSetToolButton { Q_OBJECT public: explicit WorkingSetWidget(Sublime::Area* area, QWidget* parent = 0); - virtual void setVisible( bool visible ) override; + void setVisible( bool visible ) override; private slots: void changingWorkingSet(Sublime::Area* area, const QString& from, const QString& to); void setChangedSignificantly(); private: QPointer m_area; }; } #endif // KDEVPLATFORM_WORKINGSETWIDGET_H diff --git a/sublime/aggregatemodel.h b/sublime/aggregatemodel.h index 26b2434fa2..dca2b3aad5 100644 --- a/sublime/aggregatemodel.h +++ b/sublime/aggregatemodel.h @@ -1,99 +1,99 @@ /*************************************************************************** * Copyright 2007 Alexander Dymo * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_SUBLIMEAGGREGATEMODEL_H #define KDEVPLATFORM_SUBLIMEAGGREGATEMODEL_H #include #include #include #include "sublimeexport.h" class QStandardItemModel; namespace Sublime { /** @short A model to combine several QStandardItemModel's into one. Combine standard models into the aggregate model to display them in the one view. Each new model gets its own parent item to differentiate items between different models, for example: Tea Model: @code - Black - Green - White @endcode Coffee Model: @code - Arabica - Robusta @endcode When aggregated with @code AggregateModel model; model->addModel("Tea", teaModel); model->addModel("Coffee", coffeeModel); @endcode they will look as: @code - Tea - Black - Green - White - Coffee - Arabica - Robusta @endcode @note It is impossible to aggregate any model, aggregation works only for standard models. @note Currently aggregate model displays only 1 column. */ class KDEVPLATFORMSUBLIME_EXPORT AggregateModel: public QAbstractItemModel { Q_OBJECT public: explicit AggregateModel(QObject *parent = 0); - virtual ~AggregateModel(); + ~AggregateModel() override; /**Adds the model and creates a parent item with given @p name in the aggregated model.*/ void addModel(const QString &name, QStandardItemModel *model); /**Removes the model from aggregation.*/ void removeModel(QStandardItemModel *model); //reimplemented methods from QAbstractItemModel - virtual Qt::ItemFlags flags(const QModelIndex &index) const override; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override; - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - virtual QModelIndex parent(const QModelIndex &index) const override; - virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + Qt::ItemFlags flags(const QModelIndex &index) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QModelIndex parent(const QModelIndex &index) const override; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; private: struct AggregateModelPrivate *d; }; } #endif diff --git a/sublime/area.h b/sublime/area.h index b627211759..c8c1f44545 100644 --- a/sublime/area.h +++ b/sublime/area.h @@ -1,290 +1,290 @@ /*************************************************************************** * Copyright 2006-2007 Alexander Dymo * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_SUBLIMEAREA_H #define KDEVPLATFORM_SUBLIMEAREA_H #include #include "sublimeexport.h" #include "areaindex.h" #include "sublimedefs.h" #include class QAction; namespace Sublime { class AreaIndex; class RootAreaIndex; class Controller; class View; /** @short Area - the universal view container Area contains views and toolviews, knows about their positions and provides functionality to add new (tool)views and remove existing. Area takes care of all placement/configuration details so that in order for @ref MainWindow to show the area it just needs to reconstruct itself according to the area's rules. Usual way of creating an area is: @code Controller *controller = new Controller(); ... //document creation code here Area *area = new Area(controller, "My Area"); area->addView(document->createView()); MainWindow *mw = new MainWindow(controller); controller->show(area, mw); @endcode */ class KDEVPLATFORMSUBLIME_EXPORT Area: public QObject { Q_OBJECT public: /**Creates and area with given @p name and adds it to the @p controller. @param controller is the controller in which this area will be available. @param name should identify this area and be unique for all areas in the controller. @ref QObject::objectName shall be used to get this name after area creation. @param title is the user-visible (translatable) title for the area. Use @ref title and @ref setTitle to operate on the title. This parameter can be omitted and then name will be used as title.*/ Area(Controller *controller, const QString &name, const QString &title = {}); Area(const Area &area); - ~Area(); + ~Area() override; QString title() const; void setTitle(const QString &title); QString iconName() const; void setIconName(const QString &iconName); /**Adds the @p view to the list of views at the given area index, after the given view @p after. If @p after == 0 && controller()->openAfterCurrent(): @p view is inserted after current view If @p after == 0 && !controller()->openAfterCurrent(): @p view is inserted at the last position. */ void addView(View *view, AreaIndex *index, View *after = 0); /**Adds the @p view to the list of views at the current area index.*/ void addView(View *view, View *after = 0); /**Adds the @p view to the area splitting the @p viewToSplit using given @p orientation. @p view Will be in the second child index of the area-index containing the view. */ void addView(View *view, View *viewToSplit, Qt::Orientation orientation); /**Adds the @p view to the area splitting the area index @p indexToSplit using given @p orientation. @p view Will be in the second child index of the area-index containing the view. */ void addView(View *view, AreaIndex *indexToSplit, Qt::Orientation orientation); /**Removes the @p view from the area. Does not delete it. */ View* removeView(View *view); /**@return the list of all views in this area in no particular order. To process the views in ordered manner (tree walk) use @ref walkViews method. This method is added only for convenience.*/ QList views(); /** Removes all views from this area and deletes them. * If an open document has changes, and it is the last view of that document, * the user may push 'Cancel', and the view will stay active. * @param silent If this is true, the user is never asked for feedback. */ void clearViews(bool silent = false); /** * Returns the view that was last stored through setActiveView(view), or zero * if the view was deleted or it was never set. */ View* activeView(); /** * Allows marking a view as active that can later be retrieved through activeView() */ void setActiveView(View* view); /** Closes and deletes the view, asking the user for feedback if needed. * Closes the document if it is the last view. * Does allow breaking the closing process. * If it is the last view of the document that has changes, and the user pushed 'Cancel', * false will be returned, and the view will not be closed. * @param silent If this is false, the user will be asked for feedback. Otherwise he won't. */ bool closeView(View* view, bool silent = false); /**@return the index of view or 0 if it can not be found.*/ AreaIndex *indexOf(View *view); /**@return the root index of the area. Root index always exists so this method will never return 0.*/ RootAreaIndex *rootIndex() const; /**Adds the toolview to the area. Area will use its configuration and restore the proper position for the toolview when necessary. If it has no configuration for this view, it will use @p defaultPosition.*/ void addToolView(View *toolView, Position defaultPosition); /**Removes the toolview from the area.*/ View* removeToolView(View *toolView); /**Moves the toolview to a different position. */ void moveToolView(View *toolView, Position newPosition); /**Raise tool view.*/ void raiseToolView(View *toolView); /**@return the list of toolviews in the area. No particular sort order is guaranteed.*/ QList &toolViews() const; /**@return the current position of @p toolView in the area.*/ Position toolViewPosition(View *toolView) const; /* Returns true if this area actively desires to show a tool view with id of 'id'. The area, of course, will show any tool view added with 'addToolView', however, this method can be used to guess a set of tool views that make most sense to be added. */ bool wantToolView(const QString& id); void setShownToolViews(Sublime::Position pos, const QStringList& ids); QStringList shownToolViews(Sublime::Position pos) const; 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); /**@return the controller for this area.*/ Controller *controller() const; ///Returns the currently set working-set for this area. The working-set is persistent QString workingSet() const; ///Sets the working-set for this area. The working-set is just a marker, and does nothing ///within Area. ///The actual view management has to be implemented in the entity that knows more ///about possible views, documents, etc. (kdevplatform/shell) ///@warning (KDevelop): Before calling this, make sure that all views are saved! (see IDocumentController::saveAllDocumentsForWindow) void setWorkingSet(QString name); /**Walker mode to determine the behavior of area walkers.*/ enum WalkerMode { StopWalker, /**< Stop after processing this area index or toolview */ ContinueWalker /**< Continue walking */ }; /**Walks the tree of area indices and executes the operator. It will always walk the tree of views from top to bottom from left to right. Operator should be the class with WalkerResult operator()(AreaIndex *index) method. That method should return Area::StopWalker if the walker has to stop at current index or Area::ContinueWalker to continue. Example (operator to print the indices, assumes hypothetical operator <<()): @code struct MyOperator { WalkerMode operator()(AreaIndex *index) { std::cerr << index << std::endl; return Area::ContinueWalker; } }; ... MyOperator op; walkViews(op, rootIndex()) @endcode*/ template void walkViews(Operator &op, AreaIndex *index); /**Walks the list of toolviews. The order in which toolviews are walked is not specified. Operator should be the class with bool operator()(View *view, Sublime::Position position) method. That method should return Area::StopWalker if the walker has to stop at current index or Area::ContinueWalker to continue. Example (operator to print the list of views): @code struct MyOperator { WalkerMode operator()(View *view, Sublime::Position position) { std::cerr << view << " at position " << position << std::endl; return Area::ContinueWalker; } }; ... MyOperator op; walkToolViews(op, Sublime::AllPositions) @endcode */ template void walkToolViews(Operator &op, Positions positions); /** Adds an action to the area. They will be made available from different places, like the Area Display*/ void addAction(QAction* action); /** @returns the actions related to the area */ QList actions() const; /** * Closes all the views and requests the working set to be cleared. * Works even though the area isn't opened yet */ void clearDocuments(); Q_SIGNALS: /**Emitted when a new view is added to the area.*/ void viewAdded(Sublime::AreaIndex*, Sublime::View*); /**Emitted when a view is going to be removed from the area.*/ void aboutToRemoveView(Sublime::AreaIndex*, Sublime::View*); /**Emitted when a view was removed from the area.*/ void viewRemoved(Sublime::AreaIndex*, Sublime::View*); /**Emitted when a new toolview is added to the area.*/ void toolViewAdded(Sublime::View*, Sublime::Position); /**Emitted when a toolview is requesting to be raised.*/ void requestToolViewRaise(Sublime::View*); /**Emitted when a toolview is going to be removed from the area.*/ void aboutToRemoveToolView(Sublime::View*, Sublime::Position); /**Emitted when a toolview is moved to a different position.*/ void toolViewMoved(Sublime::View*, Sublime::Position); /**Emitted before the working-set is changed.*/ void changingWorkingSet(Sublime::Area* area, QString from, QString to); /**Emitted after the working-set was changed.*/ void changedWorkingSet(Sublime::Area* area, QString from, QString to); /** notifies the working set that it should clear */ void clearWorkingSet(Sublime::Area* area); private Q_SLOTS: void positionChanged(Sublime::View*, int); void actionDestroyed(QObject* action); private: template WalkerMode walkViewsInternal(Operator &op, AreaIndex *index); void initialize(); struct AreaPrivate *const d; }; } #include "areawalkers.h" #endif diff --git a/sublime/container.cpp b/sublime/container.cpp index eb967bcf6b..9e088bcbe4 100644 --- a/sublime/container.cpp +++ b/sublime/container.cpp @@ -1,627 +1,627 @@ /*************************************************************************** * Copyright 2006-2009 Alexander Dymo * * * * 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 Library 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 "container.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "view.h" #include "document.h" #include namespace Sublime { // struct ContainerPrivate class ContainerTabBar : public QTabBar { Q_OBJECT public: ContainerTabBar(Container* container) : QTabBar(container), m_container(container) { installEventFilter(this); } - virtual bool event(QEvent* ev) override { + bool event(QEvent* ev) override { if(ev->type() == QEvent::ToolTip) { ev->accept(); int tab = tabAt(mapFromGlobal(QCursor::pos())); if(tab != -1) { m_container->showTooltipForTab(tab); } return true; } return QTabBar::event(ev); } - virtual void mousePressEvent(QMouseEvent* event) override { + void mousePressEvent(QMouseEvent* event) override { if (event->button() == Qt::MidButton) { // just close on midbutton, drag can still be done with left mouse button int tab = tabAt(mapFromGlobal(QCursor::pos())); if (tab != -1) { emit tabCloseRequested(tab); } return; } QTabBar::mousePressEvent(event); } bool eventFilter(QObject* obj, QEvent* event) override { if (obj != this) { return QObject::eventFilter(obj, event); } // TODO Qt6: Move to mouseDoubleClickEvent when fixme in qttabbar.cpp is resolved // see "fixme Qt 6: move to mouseDoubleClickEvent(), here for BC reasons." in qtabbar.cpp if (event->type() == QEvent::MouseButtonDblClick) { // block tabBarDoubleClicked signals with RMB, see https://bugs.kde.org/show_bug.cgi?id=356016 auto mouseEvent = static_cast(event); if (mouseEvent->button() == Qt::MidButton) { return true; } } return QObject::eventFilter(obj, event); } Q_SIGNALS: void newTabRequested(); private: Container* m_container; }; bool sortViews(const View* const lhs, const View* const rhs) { return lhs->document()->title().compare(rhs->document()->title(), Qt::CaseInsensitive) < 0; } struct ContainerPrivate { QBoxLayout* layout; QMap viewForWidget; ContainerTabBar *tabBar; QStackedWidget *stack; KSqueezedTextLabel *fileNameCorner; QLabel *fileStatus; KSqueezedTextLabel *statusCorner; QPointer leftCornerWidget; QToolButton* documentListButton; QMenu* documentListMenu; QMap documentListActionForView; /** * Updates the context menu which is shown when * the document list button in the tab bar is clicked. * * It shall build a popup menu which contains all currently * enabled views using the title their document provides. */ void updateDocumentListPopupMenu() { qDeleteAll(documentListActionForView); documentListActionForView.clear(); documentListMenu->clear(); // create a lexicographically sorted list QVector views; views.reserve(viewForWidget.size()); foreach(View* view, viewForWidget){ views << view; } std::sort(views.begin(), views.end(), sortViews); foreach(View* view, views) { QAction* action = documentListMenu->addAction(view->document()->title()); action->setData(QVariant::fromValue(view)); documentListActionForView[view] = action; action->setIcon(view->document()->icon()); ///FIXME: push this code somehow into shell, such that we can access the project model for /// icons and also get a neat, short path like the document switcher. } } }; class UnderlinedLabel: public KSqueezedTextLabel { public: UnderlinedLabel(QTabBar *tabBar, QWidget* parent = 0) :KSqueezedTextLabel(parent), m_tabBar(tabBar) { } protected: - virtual void paintEvent(QPaintEvent *ev) override + void paintEvent(QPaintEvent *ev) override { if (m_tabBar->isVisible() && m_tabBar->count() > 0) { QStylePainter p(this); QStyleOptionTabBarBase optTabBase; optTabBase.init(m_tabBar); optTabBase.shape = m_tabBar->shape(); optTabBase.tabBarRect = m_tabBar->rect(); optTabBase.tabBarRect.moveRight(0); QStyleOptionTab tabOverlap; tabOverlap.shape = m_tabBar->shape(); int overlap = style()->pixelMetric(QStyle::PM_TabBarBaseOverlap, &tabOverlap, m_tabBar); if( overlap > 0 ) { QRect rect; rect.setRect(0, height()-overlap, width(), overlap); optTabBase.rect = rect; } if( m_tabBar->drawBase() ) { p.drawPrimitive(QStyle::PE_FrameTabBarBase, optTabBase); } } KSqueezedTextLabel::paintEvent(ev); } QTabBar *m_tabBar; }; class StatusLabel: public UnderlinedLabel { public: StatusLabel(QTabBar *tabBar, QWidget* parent = 0): UnderlinedLabel(tabBar, parent) { setAlignment(Qt::AlignRight | Qt::AlignVCenter); setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed); } - virtual QSize minimumSizeHint() const override + QSize minimumSizeHint() const override { QRect rect = style()->itemTextRect(fontMetrics(), QRect(), Qt::AlignRight, true, i18n("Line: 00000 Col: 000")); rect.setHeight(m_tabBar->height()); return rect.size(); } }; // class Container Container::Container(QWidget *parent) :QWidget(parent), d(new ContainerPrivate()) { KAcceleratorManager::setNoAccel(this); QBoxLayout *l = new QBoxLayout(QBoxLayout::TopToBottom, this); l->setMargin(0); l->setSpacing(0); d->layout = new QBoxLayout(QBoxLayout::LeftToRight); d->layout->setMargin(0); d->layout->setSpacing(0); d->documentListMenu = new QMenu(this); d->documentListButton = new QToolButton(this); d->documentListButton->setIcon(QIcon::fromTheme("format-list-unordered")); d->documentListButton->setMenu(d->documentListMenu); d->documentListButton->setPopupMode(QToolButton::InstantPopup); d->documentListButton->setAutoRaise(true); d->documentListButton->setToolTip(i18n("Show sorted list of opened documents")); d->documentListButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); d->layout->addWidget(d->documentListButton); d->tabBar = new ContainerTabBar(this); d->tabBar->setContextMenuPolicy(Qt::CustomContextMenu); d->layout->addWidget(d->tabBar); d->fileStatus = new QLabel( this ); d->fileStatus->setFixedSize( QSize( 16, 16 ) ); d->layout->addWidget(d->fileStatus); d->fileNameCorner = new UnderlinedLabel(d->tabBar, this); d->layout->addWidget(d->fileNameCorner); d->statusCorner = new StatusLabel(d->tabBar, this); d->layout->addWidget(d->statusCorner); l->addLayout(d->layout); d->stack = new QStackedWidget(this); l->addWidget(d->stack); connect(d->tabBar, &ContainerTabBar::currentChanged, this, &Container::widgetActivated); connect(d->tabBar, &ContainerTabBar::tabCloseRequested, this, static_cast(&Container::requestClose)); connect(d->tabBar, &ContainerTabBar::newTabRequested, this, &Container::newTabRequested); connect(d->tabBar, &ContainerTabBar::tabMoved, this, &Container::tabMoved); connect(d->tabBar, &ContainerTabBar::customContextMenuRequested, this, &Container::contextMenu); connect(d->tabBar, &ContainerTabBar::tabBarDoubleClicked, this, &Container::doubleClickTriggered); connect(d->documentListMenu, &QMenu::triggered, this, &Container::documentListActionTriggered); setTabBarHidden(!configTabBarVisible()); d->tabBar->setTabsClosable(true); d->tabBar->setMovable(true); d->tabBar->setExpanding(false); d->tabBar->setSelectionBehaviorOnRemove(QTabBar::SelectPreviousTab); } bool Container::configTabBarVisible() { KConfigGroup group = KSharedConfig::openConfig()->group("UiSettings"); return group.readEntry("TabBarVisibility", 1); } void Container::setLeftCornerWidget(QWidget* widget) { if(d->leftCornerWidget.data() == widget) { if(d->leftCornerWidget) d->leftCornerWidget.data()->setParent(0); }else{ delete d->leftCornerWidget.data(); d->leftCornerWidget.clear(); } d->leftCornerWidget = widget; if(!widget) return; widget->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); d->layout->insertWidget(0, widget); widget->show(); } Container::~Container() { delete d; } QList Container::views() const { return d->viewForWidget.values(); } void Container::requestClose(int idx) { emit requestClose(widget(idx)); } void Container::widgetActivated(int idx) { if (idx < 0) return; if (QWidget* w = d->stack->widget(idx)) { Sublime::View* view = d->viewForWidget.value(w); if(view) emit activateView(view); } } void Container::addWidget(View *view, int position) { QWidget *w = view->widget(this); int idx = 0; if (position != -1) { idx = d->stack->insertWidget(position, w); } else idx = d->stack->addWidget(w); d->tabBar->insertTab(idx, view->document()->statusIcon(), view->document()->title()); Q_ASSERT(view); d->viewForWidget[w] = view; // Update document list context menu. This has to be called before // setCurrentWidget, because we call the status icon and title update slots // already, which in turn need the document list menu to be setup. d->updateDocumentListPopupMenu(); setCurrentWidget(d->stack->currentWidget()); // This fixes a strange layouting bug, that could be reproduced like this: Open a few files in KDevelop, activate the rightmost tab. // Then temporarily switch to another area, and then switch back. After that, the tab-bar was gone. // The problem could only be fixed by closing/opening another view. d->tabBar->setMinimumHeight(d->tabBar->sizeHint().height()); connect(view, &View::statusChanged, this, &Container::statusChanged); connect(view->document(), &Document::statusIconChanged, this, &Container::statusIconChanged); connect(view->document(), &Document::titleChanged, this, &Container::documentTitleChanged); } void Container::statusChanged(Sublime::View* view) { d->statusCorner->setText(view->viewStatus()); } void Container::statusIconChanged(Document* doc) { QMapIterator it = d->viewForWidget; while (it.hasNext()) { if (it.next().value()->document() == doc) { d->fileStatus->setPixmap( doc->statusIcon().pixmap( QSize( 16,16 ) ) ); int tabIndex = d->stack->indexOf(it.key()); if (tabIndex != -1) { d->tabBar->setTabIcon(tabIndex, doc->statusIcon()); } // Update the document title's menu associated action // using the View* index map Q_ASSERT(d->documentListActionForView.contains(it.value())); d->documentListActionForView[it.value()]->setIcon(doc->icon()); break; } } } void Container::documentTitleChanged(Sublime::Document* doc) { QMapIterator it = d->viewForWidget; while (it.hasNext()) { Sublime::View* view = it.next().value(); if (view->document() == doc) { if (currentView() == view) { d->fileNameCorner->setText( doc->title(Document::Extended) ); } int tabIndex = d->stack->indexOf(it.key()); 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; } } } int Container::count() const { return d->stack->count(); } QWidget* Container::currentWidget() const { return d->stack->currentWidget(); } void Container::setCurrentWidget(QWidget* w) { d->stack->setCurrentWidget(w); //prevent from emitting activateView() signal on tabbar active tab change //this function is called from MainWindow::activateView() //which does the activation without any additional signals d->tabBar->blockSignals(true); d->tabBar->setCurrentIndex(d->stack->indexOf(w)); d->tabBar->blockSignals(false); if (View* view = viewForWidget(w)) { statusChanged(view); if (!d->tabBar->isVisible()) { // repaint icon and document title only in tabbar-less mode // tabbar will do repainting for us statusIconChanged( view->document() ); documentTitleChanged( view->document() ); } } } QWidget* Container::widget(int i) const { return d->stack->widget(i); } int Container::indexOf(QWidget* w) const { return d->stack->indexOf(w); } void Container::removeWidget(QWidget *w) { if (w) { int widgetIdx = d->stack->indexOf(w); d->stack->removeWidget(w); d->tabBar->removeTab(widgetIdx); if (d->tabBar->currentIndex() != -1 && !d->tabBar->isVisible()) { // repaint icon and document title only in tabbar-less mode // tabbar will do repainting for us View* view = currentView(); if( view ) { statusIconChanged( view->document() ); documentTitleChanged( view->document() ); } } View* view = d->viewForWidget.take(w); if (view) { disconnect(view->document(), &Document::titleChanged, this, &Container::documentTitleChanged); disconnect(view->document(), &Document::statusIconChanged, this, &Container::statusIconChanged); disconnect(view, &View::statusChanged, this, &Container::statusChanged); // Update document list context menu Q_ASSERT(d->documentListActionForView.contains(view)); delete d->documentListActionForView.take(view); } } } bool Container::hasWidget(QWidget *w) { return d->stack->indexOf(w) != -1; } View *Container::viewForWidget(QWidget *w) const { return d->viewForWidget.value(w); } void Container::setTabBarHidden(bool hide) { if (hide) { d->tabBar->hide(); d->fileNameCorner->show(); d->fileStatus->show(); } else { d->fileNameCorner->hide(); d->fileStatus->hide(); d->tabBar->show(); } View* v = currentView(); if (v) { documentTitleChanged(v->document()); } } void Container::resetTabColors(const QColor& color) { for (int i = 0; i < count(); i++){ d->tabBar->setTabTextColor(i, color); } } void Container::setTabColor(const View* view, const QColor& color) { for (int i = 0; i < count(); i++){ if (view == viewForWidget(widget(i))) { d->tabBar->setTabTextColor(i, color); } } } void Container::tabMoved(int from, int to) { QWidget *w = d->stack->widget(from); d->stack->removeWidget(w); d->stack->insertWidget(to, w); d->viewForWidget[w]->notifyPositionChanged(to); } void Container::contextMenu( const QPoint& pos ) { QWidget* senderWidget = qobject_cast(sender()); Q_ASSERT(senderWidget); int currentTab = d->tabBar->tabAt(pos); QMenu menu; Sublime::View* view = viewForWidget(widget(currentTab)); emit tabContextMenuRequested(view, &menu); menu.addSeparator(); QAction* closeTabAction = nullptr; QAction* closeOtherTabsAction = nullptr; if (view) { closeTabAction = menu.addAction(QIcon::fromTheme("document-close"), i18n("Close File")); closeOtherTabsAction = menu.addAction(QIcon::fromTheme("document-close"), i18n("Close Other Files")); } QAction* closeAllTabsAction = menu.addAction( QIcon::fromTheme("document-close"), i18n( "Close All Files" ) ); QAction* triggered = menu.exec(senderWidget->mapToGlobal(pos)); if (triggered) { if ( triggered == closeTabAction ) { requestClose(currentTab); } else if ( triggered == closeOtherTabsAction ) { // activate the remaining tab widgetActivated(currentTab); // first get the widgets to be closed since otherwise the indices will be wrong QList otherTabs; for ( int i = 0; i < count(); ++i ) { if ( i != currentTab ) { otherTabs << widget(i); } } // finally close other tabs foreach( QWidget* tab, otherTabs ) { requestClose(tab); } } else if ( triggered == closeAllTabsAction ) { // activate last tab widgetActivated(count() - 1); // close all for ( int i = 0; i < count(); ++i ) { requestClose(widget(i)); } } // else the action was handled by someone else } } void Container::showTooltipForTab(int tab) { emit tabToolTipRequested(viewForWidget(widget(tab)), this, tab); } bool Container::isCurrentTab(int tab) const { return d->tabBar->currentIndex() == tab; } QRect Container::tabRect(int tab) const { return d->tabBar->tabRect(tab).translated(d->tabBar->mapToGlobal(QPoint(0, 0))); } void Container::doubleClickTriggered(int tab) { if (tab == -1) { emit newTabRequested(); } else { emit tabDoubleClicked(viewForWidget(widget(tab))); } } void Container::documentListActionTriggered(QAction* action) { Sublime::View* view = action->data().value< Sublime::View* >(); Q_ASSERT(view); QWidget* widget = d->viewForWidget.key(view); Q_ASSERT(widget); setCurrentWidget(widget); } Sublime::View* Container::currentView() const { return d->viewForWidget.value(widget( d->tabBar->currentIndex() )); } } #include "container.moc" diff --git a/sublime/container.h b/sublime/container.h index 95feac05ce..7f15997bef 100644 --- a/sublime/container.h +++ b/sublime/container.h @@ -1,118 +1,118 @@ /*************************************************************************** * Copyright 2006-2007 Alexander Dymo * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_SUBLIMECONTAINER_H #define KDEVPLATFORM_SUBLIMECONTAINER_H #include #include "urldocument.h" #include "sublimeexport.h" class QMenu; class QBoxLayout; class QPaintEvent; namespace Sublime { class View; class Document; /** @short Container for the widgets. This container is placed inside mainwindow splitters to show widgets for views in the area. */ class KDEVPLATFORMSUBLIME_EXPORT Container: public QWidget { Q_OBJECT public: explicit Container(QWidget *parent = 0); - ~Container(); + ~Container() override; /**Adds the widget for given @p view to the container.*/ void addWidget(Sublime::View* view, int position = -1); /**Removes the widget from the container.*/ void removeWidget(QWidget *w); /** @return true if widget is placed inside this container.*/ bool hasWidget(QWidget *w); QList views() const; int count() const; QWidget *currentWidget() const; void setCurrentWidget(QWidget *w); QWidget *widget(int i) const; int indexOf(QWidget *w) const; View *viewForWidget(QWidget *w) const; void setTabBarHidden(bool hide); void setTabColor(const View* view, const QColor& color); void resetTabColors(const QColor& color); /** Adds a corner widget to the left of this containers tab-bar. To remove it again, just delete it. * The ownership otherwise goes to the container. */ void setLeftCornerWidget(QWidget* widget); void showTooltipForTab(int tab); bool isCurrentTab(int tab) const; /// @return Rect in global position of the tab identified by index @p tab QRect tabRect(int tab) const; static bool configTabBarVisible(); Q_SIGNALS: void activateView(Sublime::View* view); void requestClose(QWidget *w); /** * This signal is emitted whenever the users double clicks on the free * space next to the tab bar. Typically, a new document should be * created. */ void newTabRequested(); void tabContextMenuRequested(Sublime::View* view, QMenu* menu); /** * @p view The view represented by the tab that was hovered * @p Container The tab container that triggered the event * @p idx The index of the tab that was hovered */ void tabToolTipRequested(Sublime::View* view, Sublime::Container* container, int idx); void tabDoubleClicked(Sublime::View* view); private Q_SLOTS: void widgetActivated(int idx); void documentTitleChanged(Sublime::Document* doc); void statusIconChanged(Sublime::Document*); void statusChanged(Sublime::View *view); void requestClose(int idx); void tabMoved(int from, int to); void contextMenu(const QPoint&); void doubleClickTriggered(int tab); void documentListActionTriggered(QAction*); private: Sublime::View* currentView() const; struct ContainerPrivate * const d; }; } #endif diff --git a/sublime/controller.h b/sublime/controller.h index 06ded43e82..5ec130737f 100644 --- a/sublime/controller.h +++ b/sublime/controller.h @@ -1,200 +1,200 @@ /*************************************************************************** * Copyright 2006-2007 Alexander Dymo * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_SUBLIMECONTROLLER_H #define KDEVPLATFORM_SUBLIMECONTROLLER_H #include #include "sublimedefs.h" #include "sublimeexport.h" #include "mainwindowoperator.h" namespace Sublime { class Area; class AreaIndex; class Document; class MainWindow; /** @short Handles association of areas to main windows. Whereas the MainWindow class can be told to show arbitrary Area instance, this class establishes more high-level rules based on the following assumptions: 1. It's desirable to have a list of "area types" -- basically string, and be able to switch each main window between those "area types". For example, to switch main window between "Code" and "Debug" 2. It's also desirable to save the state of area -- like the set of toolviews, position of toolviews, etc. This need to be done per-main window, so that "code" area of one window is allowed to be different from "code" area of another window. 3. Is it desirable to be able to reset an area of given type in a given main window to a default state. The current implementation achieves those goals as follows. 1. Controller keeps a list of default areas. Those areas are not shown by any main window, and never modified as result of user actions. They are directly constructed by kdevelop core. Those areas are returned by the ::defaultAreas method. Each Area instance in the list provides area type id, and human name of the area -- via Area::objectName and Area::title methods respectively. All methods in this class accept area id, and human name of the area is only used to present the area type to the user, for selection. 2. Controller also keeps a list of MainWindow instances that it manages. For each instance, it keeps a list of areas private to the MainWindow instance. There's one area for each area in defaultAreas. That is, for each area type, there's one area in defaultAreas, and one area per each main window 3. It's possible to switch a given main window to display an area of the given type -- which finds the area with the given id in the list of area private to that main window, and switches the main window to the found area. When we create a new main window, we create fresh set of private areas by cloning the default areas. An alternative approach would be to create a clone only when we try to show a specific area type in a main window. However, I think that knowing that each main window has its Area instance for each area type simplifies the code. For example, most of the time, during restoring areas we'd need per-window area instances anyway. Of course, we can introduce a method demand_area_type(MainWindow*, QString) that clones the default area of the necessary type, but I don't see what that will buy us. Controller has to exist before any area, document or mainwindow can be created. There's no point in having two controllers for one application unless they need to show completely different sets of areas. */ class KDEVPLATFORMSUBLIME_EXPORT Controller: public QObject, public MainWindowOperator { Q_OBJECT public: explicit Controller(QObject *parent = 0); - ~Controller(); + ~Controller() override; /** Add the area to the set of default areas in this controller. */ void addDefaultArea(Area *area); /** Return the list of default areas. */ const QList &defaultAreas() const; /** Return the default area with given @p id.*/ Area *defaultArea(const QString &id) const; /** Add a main window to the set of of windows managed by this controller. The ownership of the window is passed to the controller. The window will be associated with a set of areas created by cloning the current defaultAreas. */ void addMainWindow(MainWindow* mainWindow); /** Return the set of MainWindow instances managed by *this. */ const QList &mainWindows() const; /** Return all areas associated with the main window with the specified index. */ const QList &areas(int mainWindow) const; /** Return all areas associated with the main window with the specified index. */ const QList &areas(MainWindow* mainWindow) const; /** Return the area with the given in main window specified by its index, @p mainWindow. */ Area *area(int mainWindow, const QString& id) const; /** Returns the area that contains the given view. * */ Area* areaForView(View* view) const; /**Shows an @p area in @p mainWindow. @todo Remove this method */ void showArea(Area *area, MainWindow *mainWindow); /** Show area with the id of @p areaTypeId in @p mainWindow. */ void showArea(const QString& areaTypeId, MainWindow *mainWindow); /** Make the tool configuration of the area currently shown in @p mainWindow match those of default area with the same area type. */ void resetCurrentArea(MainWindow *mainWindow); /** Return the list of all areas, including default area and area private to each main window. */ const QList &allAreas() const; /**@return the list of documents created in this controller.*/ const QList &documents() const; void setStatusIcon(Document* document, const QIcon& icon); bool openAfterCurrent() const; bool arrangeBuddies() const; void loadSettings(); public Q_SLOTS: //@todo adymo: this should not be a part of public API /**Area can connect to this slot to release itself from its mainwindow.*/ void areaReleased(); /**Releases @p area from its mainwindow.*/ void areaReleased(Sublime::Area *area); protected: bool eventFilter(QObject *obj, QEvent *ev) override; void showAreaInternal(Area* area, MainWindow *mainWindow); private Q_SLOTS: void notifyToolViewRemoved(Sublime::View *view, Sublime::Position); void notifyToolViewAdded(Sublime::View *view, Sublime::Position); void notifyViewRemoved(Sublime::AreaIndex*, Sublime::View *view); void notifyViewAdded(Sublime::AreaIndex*, Sublime::View *view); Q_SIGNALS: void aboutToRemoveToolView(Sublime::View*); void toolViewAdded(Sublime::View*); void aboutToRemoveView(Sublime::View*); void viewAdded(Sublime::View*); void toolViewMoved(Sublime::View*); void mainWindowAdded(Sublime::MainWindow*); void areaCreated(Sublime::Area* area); private: void init(); void removeArea(Sublime::Area*); // called by Sublime::Area void removeDocument(Sublime::Document*); // called by Sublime::Document /**Adds the document to the controller, used by Document class. @todo adymo: refactor*/ void addDocument(Document *document); struct ControllerPrivate *const d; friend class Area; friend class Document; }; } #endif diff --git a/sublime/document.h b/sublime/document.h index f28c8cde63..c00638f316 100644 --- a/sublime/document.h +++ b/sublime/document.h @@ -1,146 +1,146 @@ /*************************************************************************** * Copyright 2006-2007 Alexander Dymo * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_SUBLIMEDOCUMENT_H #define KDEVPLATFORM_SUBLIMEDOCUMENT_H #include #include #include "sublimeexport.h" class QIcon; class QWidget; namespace Sublime { class Area; class View; class Controller; /** @short Abstract base class for all Sublime documents Subclass from Document and implement createViewWidget() method to return a new widget for a view. */ class KDEVPLATFORMSUBLIME_EXPORT Document: public QObject { Q_OBJECT public: /**Creates a document and adds it to a @p controller.*/ Document(const QString &title, Controller *controller); - ~Document(); + ~Document() override; /**@return the new view for this document. @note it will not create a widget, just return a view object.*/ View *createView(); /**@return the list of all views in all areas for this document.*/ const QList &views() const; /**@return the controller for this document.*/ Controller *controller() const; /**@return the document title.*/ enum TitleType { Normal, Extended}; virtual QString title(TitleType type = Normal) const; /**Set the document title.*/ void setTitle(const QString& newTitle); void setToolTip(const QString& newToolTip); QString toolTip() const; /**@return the type of document which can be written to config.*/ virtual QString documentType() const = 0; /**@return the specifics of this document which can be written to config.*/ virtual QString documentSpecifier() const = 0; /** * If the document is in a state where data may be lost while closking, * asks the user whether he really wants to close the document. * * This function may also take actions like saving the document before closing * if the user desires so. * * @return true if the document is allowed to be closed, otherwise false. * * The default implementation always returns true. * * */ virtual bool askForCloseFeedback(); /**Should try closing the document, eventually asking the user for feedback. * *If closing is successful, all views should be deleted, and the document itself *be scheduled for deletion using deleteLater(). * * @param silent If this is true, the user must not be asked. * * Returns whether closing was successful (The user did not push 'Cancel') */ virtual bool closeDocument(bool silent = false); void setStatusIcon(QIcon icon); /** * @return The status icon of the document. */ QIcon statusIcon() const; /** * @return The status icon of the document, or, if none is present, an icon * that resembles the document, i.e. based on its mime type. * @see defaultIcon() */ QIcon icon() const; /** * Optionally override this to return a default icon when no status * icon is set for the document. The default returns an invalid icon. */ virtual QIcon defaultIcon() const; Q_SIGNALS: /**Emitted when the document is about to be deleted but is still in valid state.*/ void aboutToDelete(Sublime::Document *doc); /**Emitted when the document's title is changed.*/ void titleChanged(Sublime::Document *doc); /**Emitted when the document status-icon has changed */ void statusIconChanged(Sublime::Document *doc); protected: /**Creates and returns the new view. Reimplement in subclasses to instantiate views of derived from Sublime::View classes.*/ virtual View *newView(Document *doc); /**Reimplement this to create and return the new widget to display this document in the view. This method is used by View class when it is asked for its widget.*/ virtual QWidget *createViewWidget(QWidget *parent = 0) = 0; /** Closes all views associated to this document */ virtual void closeViews(); private: struct DocumentPrivate *const d; friend struct DocumentPrivate; friend class View; }; } #endif diff --git a/sublime/idealbuttonbarwidget.h b/sublime/idealbuttonbarwidget.h index 4981ead762..f1266387b1 100644 --- a/sublime/idealbuttonbarwidget.h +++ b/sublime/idealbuttonbarwidget.h @@ -1,84 +1,84 @@ /* Copyright 2007 Roberto Raggi Copyright 2007 Hamish Rodda Copyright 2011 Alexander Dymo Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE KDEVELOP TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef IDEALBUTTONBARWIDGET_H #define IDEALBUTTONBARWIDGET_H #include #include class IdealToolButton; class QAction; namespace Sublime { class MainWindow; class IdealController; class IdealDockWidget; class View; class Area; class IdealButtonBarWidget: public QWidget { Q_OBJECT public: IdealButtonBarWidget(Qt::DockWidgetArea area, IdealController *controller, Sublime::MainWindow *parent); QAction* addWidget(const QString& title, IdealDockWidget *widget, Area* area, View *view); void removeAction(QAction* action); Qt::Orientation orientation() const; Qt::DockWidgetArea area() const; IdealDockWidget* widgetForAction(QAction* action) const; QWidget* corner(); void showWidget(QAction *widgetAction, bool checked); bool isEmpty(); private Q_SLOTS: void showWidget(bool checked); void buttonPressed(bool state); signals: void emptyChanged(); protected: - virtual void actionEvent(QActionEvent *event) override; + void actionEvent(QActionEvent *event) override; private: Sublime::MainWindow* parentWidget() const; Qt::DockWidgetArea _area; IdealController *_controller; QHash _buttons; QHash _widgets; QWidget *_corner; }; } #endif // IDEALBUTTONBARWIDGET_H diff --git a/sublime/idealdockwidget.h b/sublime/idealdockwidget.h index fdae2f8479..c966481b23 100644 --- a/sublime/idealdockwidget.h +++ b/sublime/idealdockwidget.h @@ -1,67 +1,67 @@ /* Copyright 2007 Roberto Raggi Copyright 2007 Hamish Rodda Copyright 2011 Alexander Dymo Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE KDEVELOP TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef IDEALDOCKWIDGET_H #define IDEALDOCKWIDGET_H #include #include "idealcontroller.h" namespace Sublime { class IdealDockWidget : public QDockWidget { Q_OBJECT public: IdealDockWidget(IdealController *controller, Sublime::MainWindow *parent); - virtual ~IdealDockWidget(); + ~IdealDockWidget() override; Area *area() const; void setArea(Area *area); View *view() const; void setView(View *view); Qt::DockWidgetArea dockWidgetArea() const; void setDockWidgetArea(Qt::DockWidgetArea dockingArea); public slots: /// The IdealToolButton also connects to this slot to show the same context menu. void contextMenuRequested(const QPoint &point); Q_SIGNALS: void closeRequested(); private Q_SLOTS: void slotRemove(); private: Qt::Orientation m_orientation; Area *m_area; View *m_view; Qt::DockWidgetArea m_docking_area; IdealController *m_controller; }; } #endif // IDEALDOCKWIDGET_H diff --git a/sublime/ideallayout.h b/sublime/ideallayout.h index b0406940ff..6b469cd888 100644 --- a/sublime/ideallayout.h +++ b/sublime/ideallayout.h @@ -1,90 +1,90 @@ /* Copyright 2007 Roberto Raggi Copyright 2007 Hamish Rodda Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE KDEVELOP TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef KDEVPLATFORM_SUBLIME_IDEALLAYOUT_H #define KDEVPLATFORM_SUBLIME_IDEALLAYOUT_H #include #include #include #include "sublimedefs.h" #define IDEAL_LAYOUT_MARGIN 0 #define IDEAL_LAYOUT_SPACING 2 class QAction; class KActionCollection; namespace Sublime { class IdealDockWidget; class IdealButtonBarLayout: public QLayout { Q_OBJECT public: explicit IdealButtonBarLayout(Qt::Orientation orientation, QWidget *parent = 0); - virtual ~IdealButtonBarLayout(); + ~IdealButtonBarLayout() override; void setHeight(int height); inline Qt::Orientation orientation() const; - virtual Qt::Orientations expandingDirections() const override; + Qt::Orientations expandingDirections() const override; - virtual QSize minimumSize() const override; + QSize minimumSize() const override; - virtual QSize sizeHint() const override; + QSize sizeHint() const override; - virtual void setGeometry(const QRect &rect) override; + void setGeometry(const QRect &rect) override; - virtual void addItem(QLayoutItem *item) override; + void addItem(QLayoutItem *item) override; - virtual QLayoutItem* itemAt(int index) const override; + QLayoutItem* itemAt(int index) const override; - virtual QLayoutItem* takeAt(int index) override; + QLayoutItem* takeAt(int index) override; - virtual int count() const override; + int count() const override; - virtual void invalidate() override; + void invalidate() override; protected: int doVerticalLayout(const QRect &rect, bool updateGeometry = true) const; int doHorizontalLayout(const QRect &rect, bool updateGeometry = true) const; private: QList _items; Qt::Orientation _orientation; int _height; mutable bool m_minSizeDirty : 1; mutable bool m_sizeHintDirty : 1; mutable bool m_layoutDirty : 1; mutable QSize m_min; mutable QSize m_hint; }; } #endif diff --git a/sublime/idealtoolbutton.h b/sublime/idealtoolbutton.h index 606f018b09..cd63af0863 100644 --- a/sublime/idealtoolbutton.h +++ b/sublime/idealtoolbutton.h @@ -1,46 +1,46 @@ /* Copyright 2007 Roberto Raggi Copyright 2007 Hamish Rodda Copyright 2011 Alexander Dymo Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE KDEVELOP TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef IDEALTOOLBUTTON_H #define IDEALTOOLBUTTON_H #include class IdealToolButton: public QToolButton { Q_OBJECT public: explicit IdealToolButton(Qt::DockWidgetArea area, QWidget *parent = 0); Qt::Orientation orientation() const; - virtual QSize sizeHint() const override; + QSize sizeHint() const override; protected: - virtual void paintEvent(QPaintEvent *event) override; + void paintEvent(QPaintEvent *event) override; private: Qt::DockWidgetArea _area; }; #endif // IDEALTOOLBUTTON_H diff --git a/sublime/mainwindow.h b/sublime/mainwindow.h index 779b8531df..4c13a7b537 100644 --- a/sublime/mainwindow.h +++ b/sublime/mainwindow.h @@ -1,189 +1,189 @@ /*************************************************************************** * Copyright 2006-2007 Alexander Dymo * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_SUBLIMEMAINWINDOW_H #define KDEVPLATFORM_SUBLIMEMAINWINDOW_H #include #include #include #include "sublimeexport.h" class QDockWidget; namespace Sublime { class Container; class Area; class View; class Controller; class MainWindowOperator; /** @short Sublime Main Window The area-enabled mainwindow to show Sublime views and toolviews. To use, a controller and constructed areas are necessary: @code MainWindow w(controller); controller->showArea(area, &w); @endcode */ class KDEVPLATFORMSUBLIME_EXPORT MainWindow: public KParts::MainWindow { Q_OBJECT public: /**Creates a mainwindow and adds it to the controller.*/ explicit MainWindow(Controller *controller, Qt::WindowFlags flags = KDE_DEFAULT_WINDOWFLAGS); - ~MainWindow(); + ~MainWindow() override; /**@return the list of dockwidgets that contain area's toolviews.*/ QList toolDocks() const; /**@return area which mainwindow currently shows or 0 if no area has been set.*/ Area *area() const; /**@return controller for this mainwindow.*/ Controller *controller() const; /**@return active view inside this mainwindow.*/ View *activeView() const; /**@return active toolview inside this mainwindow.*/ View *activeToolView() const; /**Enable saving of per-area UI settings (like toolbar properties and position) whenever area is changed. This should be called after all areas are restored, and main window area is set, to prevent saving a half-broken state. */ void enableAreaSettingsSave(); /** Allows setting an additional widget that will be inserted left to the document tab-bar. * The ownership goes to the target. */ void setTabBarLeftCornerWidget(QWidget* widget); /**Sets the area of main window and fills it with views. *The contents is reconstructed, even if the area equals the currently set area. */ void setArea(Area *area); /** * Reconstruct the view structure. This is required after significant untracked changes to the * area-index structure. * Views listed in topViews will be on top of their view stacks. * */ void reconstructViews(QList topViews = QList()); /**Returns a list of all views which are on top of their corresponding view stacks*/ QList getTopViews() const; QList containers() const; /**Returns the view that is closest to the given global position, or zero.*/ View* viewForPosition(QPoint globalPos) const; /**Returns true if this main-window contains this view*/ bool containsView(View* view) const; /**Returns all areas that belong to this main-window*/ QList areas() const; /** Sets a @p w widget that will be shown when there are no opened documents. * This method takes the ownership of @p w. */ void setBackgroundCentralWidget(QWidget* w); public Q_SLOTS: /**Shows the @p view and makes it active, focusing it by default).*/ void activateView(Sublime::View *view, bool focus = true); /**Loads size/toolbar/menu/statusbar settings to the global configuration file. Reimplement in subclasses to load more and don't forget to call inherited method.*/ virtual void loadSettings(); Q_SIGNALS: /**Emitted before the area is cleared from this mainwindow.*/ void areaCleared(Sublime::Area*); /**Emitted after the new area has been shown in this mainwindow.*/ void areaChanged(Sublime::Area*); /**Emitted when the active view is changed.*/ void activeViewChanged(Sublime::View*); /**Emitted when the active toolview is changed.*/ void activeToolViewChanged(Sublime::View*); /**Emitted when the user interface settings have changed.*/ void settingsLoaded(); /**Emitted when a new view is added to the mainwindow.*/ void viewAdded(Sublime::View*); /**Emitted when a view is going to be removed from the mainwindow.*/ void aboutToRemoveView(Sublime::View*); protected: QWidget *statusBarLocation(); virtual void initializeStatusBar(); protected Q_SLOTS: virtual void tabDoubleClicked(Sublime::View* view); virtual void tabContextMenuRequested(Sublime::View*, QMenu*); virtual void tabToolTipRequested(Sublime::View* view, Sublime::Container* container, int tab); virtual void newTabRequested(); /**Called whenever the user requests a context menu on a dockwidget bar. You can then e.g. add actions to add dockwidgets. Default implementation does nothing.**/ virtual void dockBarContextMenuRequested(Qt::DockWidgetArea, const QPoint&); public: // FIXME? /**Saves size/toolbar/menu/statusbar settings to the global configuration file. Reimplement in subclasses to save more and don't forget to call inherited method.*/ virtual void saveSettings(); /**Reimplemented to save settings.*/ - virtual bool queryClose() override; + bool queryClose() override; /** Allow connecting to activateView without the need for a lambda for the default parameter */ void activateViewAndFocus(Sublime::View *view) { activateView(view, true); } private: Q_PRIVATE_SLOT(d, void viewAdded(Sublime::AreaIndex*, Sublime::View*)) Q_PRIVATE_SLOT(d, void viewRemovedInternal(Sublime::AreaIndex*, Sublime::View*)) Q_PRIVATE_SLOT(d, void aboutToRemoveView(Sublime::AreaIndex*, Sublime::View*)) Q_PRIVATE_SLOT(d, void toolViewAdded(Sublime::View*, Sublime::Position)) Q_PRIVATE_SLOT(d, void raiseToolView(Sublime::View*)) Q_PRIVATE_SLOT(d, void aboutToRemoveToolView(Sublime::View*, Sublime::Position)) Q_PRIVATE_SLOT(d, void toolViewMoved(Sublime::View*, Sublime::Position)) //Inherit MainWindowOperator to access four methods below /**Unsets the area clearing main window.*/ void clearArea(); /**Sets the active view.*/ void setActiveView(Sublime::View* view, bool focus = true); /**Sets the active toolview and focuses it.*/ void setActiveToolView(View *view); void resizeEvent(QResizeEvent* event) override; void saveGeometry(KConfigGroup &config); void loadGeometry(const KConfigGroup &config); class MainWindowPrivate *const d; friend class MainWindowOperator; friend class MainWindowPrivate; }; } #endif diff --git a/sublime/mainwindow_p.h b/sublime/mainwindow_p.h index 25eae530c3..abef1a759e 100644 --- a/sublime/mainwindow_p.h +++ b/sublime/mainwindow_p.h @@ -1,166 +1,166 @@ /*************************************************************************** * Copyright 2006-2007 Alexander Dymo * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_SUBLIMEMAINWINDOW_P_H #define KDEVPLATFORM_SUBLIMEMAINWINDOW_P_H #include #include #include #include #include #include #include #include "area.h" #include "sublimedefs.h" #include "mainwindow.h" #include #include #include #include #include #include class QMenu; class QAction; class QSplitter; class QDockWidget; class QComboBox; class IdealToolBar; namespace Sublime { class View; class Container; class Controller; class AreaIndex; class IdealMainWidget; class IdealController; class MainWindowPrivate: public QObject { Q_OBJECT public: MainWindowPrivate(MainWindow *w, Controller* controller); - ~MainWindowPrivate(); + ~MainWindowPrivate() override; /**Use this to create tool views for an area.*/ class IdealToolViewCreator { public: explicit IdealToolViewCreator(MainWindowPrivate *_d): d(_d) {} Area::WalkerMode operator() (View *view, Sublime::Position position); private: MainWindowPrivate *d; }; /**Use this to create views for an area.*/ class ViewCreator { public: explicit ViewCreator(MainWindowPrivate *_d, QList _topViews = QList()): d(_d), topViews(_topViews.toSet()) {} Area::WalkerMode operator() (AreaIndex *index); private: MainWindowPrivate *d; QSet topViews; }; /**Reconstructs the mainwindow according to the current area.*/ void reconstruct(); /**Reconstructs the views according to the current area index.*/ void reconstructViews(QList topViews = QList()); /**Clears the area leaving mainwindow empty.*/ void clearArea(); /** Sets a @p w widget that will be shown when there are no documents on the area */ void setBackgroundCentralWidget(QWidget* w); void activateFirstVisibleView(); Controller *controller; Area *area; QList docks; QMap viewContainers; QMap widgetToView; View *activeView; View *activeToolView; QWidget *centralWidget; QWidget* bgCentralWidget; QSplitter* splitterCentralWidget; IdealController *idealController; int ignoreDockShown; bool autoAreaSettingsSave; bool eventFilter(QObject* obj, QEvent* event) override; void disableConcentrationMode(); public slots: void toggleDocksShown(); void viewAdded(Sublime::AreaIndex *index, Sublime::View *view); void viewRemovedInternal(Sublime::AreaIndex *index, Sublime::View *view); void raiseToolView(Sublime::View* view); void aboutToRemoveView(Sublime::AreaIndex *index, Sublime::View *view); void toolViewAdded(Sublime::View *toolView, Sublime::Position position); void aboutToRemoveToolView(Sublime::View *toolView, Sublime::Position position); void toolViewMoved(Sublime::View *toolView, Sublime::Position position); void setTabBarLeftCornerWidget(QWidget* widget); private slots: void switchToArea(QAction *action); void updateAreaSwitcher(Sublime::Area *area); void slotDockShown(Sublime::View*, Sublime::Position, bool); void widgetResized(Qt::DockWidgetArea dockArea, int thickness); void widgetCloseRequest(QWidget* widget); void showLeftDock(bool b); void showRightDock(bool b); void showBottomDock(bool b); void focusEditor(); void selectNextDock(); void selectPreviousDock(); private: void restoreConcentrationMode(); void setBackgroundVisible(bool v); Qt::DockWidgetArea positionToDockArea(Position position); void cleanCentralWidget(); MainWindow *m_mainWindow; // uses QPointer to make already-deleted splitters detectable QMap > m_indexSplitters; QMap m_areaActions; QMap m_actionAreas; QPointer m_leftTabbarCornerWidget; QPointer m_concentrateToolBar; IdealToolBar* m_bottomToolBar; IdealToolBar* m_rightToolBar; IdealToolBar* m_leftToolBar; QAction* m_concentrationModeAction; }; } #endif diff --git a/sublime/tests/test_toolviewtoolbar.cpp b/sublime/tests/test_toolviewtoolbar.cpp index 821215d476..837a7609e0 100644 --- a/sublime/tests/test_toolviewtoolbar.cpp +++ b/sublime/tests/test_toolviewtoolbar.cpp @@ -1,134 +1,134 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2008 Andreas Pakulat * * Copyright 2008 Manuel Breugelmans * * * * 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 Library 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 "test_toolviewtoolbar.h" #include #include #include #include #include #include #include #include #include #include #include using namespace Sublime; class ToolViewToolBarFactory : public SimpleToolWidgetFactory { public: ToolViewToolBarFactory(const QString &id): SimpleToolWidgetFactory(id) {} - virtual QList toolBarActions( QWidget* ) const override + QList toolBarActions( QWidget* ) const override { QAction* action = new QAction(actionText, 0); return QList() << action; } QString actionText; }; void TestToolViewToolBar::init() { // this is starting to become a GeneralFixture controller = new Controller(this); area = new Area( controller, "Area" ); MainWindow* mw = new MainWindow(controller); // a horizontal tool with toolbar ToolViewToolBarFactory* factoryT1 = new ToolViewToolBarFactory("tool1factory"); actionTextT1 = "Tool1Action"; factoryT1->actionText = actionTextT1; tool1 = new ToolDocument( "tool1", controller, factoryT1 ); viewT11 = tool1->createView(); area->addToolView( viewT11, Sublime::Bottom ); // a vertical tool with toolbar ToolViewToolBarFactory* factoryT2 = new ToolViewToolBarFactory("tool2factory"); actionTextT2 = "Tool2Action"; factoryT2->actionText = actionTextT2; tool2 = new ToolDocument( "tool2", controller, factoryT2 ); viewT21 = tool2->createView(); area->addToolView( viewT21, Sublime::Left ); controller->showArea(area, mw); } void TestToolViewToolBar::cleanup() { delete controller; } QToolBar* TestToolViewToolBar::fetchToolBarFor(Sublime::View* view) { QWidget* toolWidget = view->widget(); const char* loc = "fetchToolBarFor"; Q_UNUSED(loc); Q_ASSERT_X(toolWidget, loc, "Tool refuses to create widget (null)."); Q_ASSERT(toolWidget->parent()); QMainWindow* toolWin = dynamic_cast(toolWidget->parent()); Q_ASSERT_X(toolWin, loc, "Tool widget's parent is not a QMainWindow."); QList toolBars = toolWin->findChildren(); int barCount = toolBars.count(); char* failMsg = qstrdup(QStringLiteral("Expected to find a toolbar but found %1").arg(barCount).toLatin1().data()); Q_UNUSED(failMsg); Q_ASSERT_X(barCount == 1, loc, failMsg); return toolBars.at(0); } void TestToolViewToolBar::assertGoodBar(QToolBar* toolbar, QString actionText) { QVERIFY( toolbar ); QVERIFY( !toolbar->isFloatable() ); QCOMPARE( toolbar->iconSize(), QSize( 16, 16 ) ); QList actions = toolbar->actions(); QCOMPARE( actions.count(), 1 ); QCOMPARE( actions.at(0)->text(), actionText); QCOMPARE( toolbar->orientation(), Qt::Horizontal ); } void TestToolViewToolBar::horizontalTool() { // viewT11 was added with Sublime::Bottom, so it should have a horizontal bar QToolBar* bar = fetchToolBarFor(viewT11); assertGoodBar(bar, actionTextT1); } void TestToolViewToolBar::verticalTool() { // viewT21 was added with Sublime::Left, so it should have a vertical bar QToolBar* bar = fetchToolBarFor(viewT21); assertGoodBar(bar, actionTextT2); } void TestToolViewToolBar::toolViewMove() { area->moveToolView( viewT11, Sublime::Right ); area->moveToolView( viewT21, Sublime::Bottom ); QToolBar* barT1 = fetchToolBarFor(viewT11); QToolBar* barT2 = fetchToolBarFor(viewT21); assertGoodBar(barT1, actionTextT1); assertGoodBar(barT2, actionTextT2); } QTEST_MAIN(TestToolViewToolBar) diff --git a/sublime/tests/test_view.cpp b/sublime/tests/test_view.cpp index d8aa3dfbec..34479d5124 100644 --- a/sublime/tests/test_view.cpp +++ b/sublime/tests/test_view.cpp @@ -1,69 +1,69 @@ /*************************************************************************** * Copyright 2007 Alexander Dymo * * * * 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 Library 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 "test_view.h" #include #include #include #include #include using namespace Sublime; void TestView::widgetDeletion() { Controller controller; Document *doc = new ToolDocument("tool", &controller, new SimpleToolWidgetFactory("tool")); View *view = doc->createView(); //create the widget view->widget(); QVERIFY(view->hasWidget()); QCOMPARE(view->widget()->metaObject()->className(), "QTextEdit"); //delete the widget and check that view knows about that delete view->widget(); QVERIFY(!view->hasWidget()); } class Test: public View { public: Test(Document *doc): View(doc) {} }; class TestDocument: public Document { public: TestDocument(Controller *controller): Document("TestDocument", controller) {} - virtual QString documentType() const override { return "Test"; } - virtual QString documentSpecifier() const override { return QString(); } + QString documentType() const override { return "Test"; } + QString documentSpecifier() const override { return QString(); } protected: - virtual QWidget *createViewWidget(QWidget *parent = 0) override { return new QWidget(parent); } - virtual View *newView(Document *doc) override { return new Test(doc); } + QWidget *createViewWidget(QWidget *parent = 0) override { return new QWidget(parent); } + View *newView(Document *doc) override { return new Test(doc); } }; void TestView::viewReimplementation() { Controller controller; Document *doc = new TestDocument(&controller); View *view = doc->createView(); QVERIFY(dynamic_cast(view) != 0); } QTEST_MAIN(TestView) diff --git a/sublime/tests/test_viewactivation.cpp b/sublime/tests/test_viewactivation.cpp index 5003237560..ac50d95425 100644 --- a/sublime/tests/test_viewactivation.cpp +++ b/sublime/tests/test_viewactivation.cpp @@ -1,227 +1,227 @@ /*************************************************************************** * Copyright 2007 Alexander Dymo * * * * 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 Library 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 "test_viewactivation.h" #include #include #include #include #include #include #include #include #include #include #include using namespace Sublime; template class SpecialWidgetFactory: public SimpleToolWidgetFactory { public: SpecialWidgetFactory(const QString &id): SimpleToolWidgetFactory(id) {} - virtual QWidget* create(ToolDocument *doc, QWidget *parent = 0) + QWidget* create(ToolDocument *doc, QWidget *parent = 0) override { QWidget *w = new QWidget(parent); Widget *inner = new Widget(w); inner->setObjectName(doc->title()+"_inner"); w->setObjectName(doc->title()+"_outer"); return w; } }; void TestViewActivation::initTestCase() { qRegisterMetaType("View*"); } void TestViewActivation::init() { controller = new Controller(this); doc1 = new ToolDocument("doc1", controller, new SimpleToolWidgetFactory("doc1")); //this document will create special widgets - QListView nested in QWidget doc2 = new ToolDocument("doc2", controller, new SpecialWidgetFactory("doc2")); doc3 = new ToolDocument("doc3", controller, new SimpleToolWidgetFactory("doc3")); doc4 = new ToolDocument("doc4", controller, new SimpleToolWidgetFactory("doc4")); tool1 = new ToolDocument("tool1", controller, new SimpleToolWidgetFactory("tool1")); tool2 = new ToolDocument("tool2", controller, new SimpleToolWidgetFactory("tool2")); tool3 = new ToolDocument("tool3", controller, new SimpleToolWidgetFactory("tool3")); area = new Area(controller, "Area"); view211 = doc1->createView(); view211->setObjectName("view211"); area->addView(view211); view212 = doc1->createView(); view212->setObjectName("view212"); area->addView(view212); view221 = doc2->createView(); area->addView(view221, view211, Qt::Vertical); view231 = doc3->createView(); area->addView(view231, view221, Qt::Horizontal); view241 = doc4->createView(); area->addView(view241, view212, Qt::Vertical); viewT11 = tool1->createView(); area->addToolView(viewT11, Sublime::Bottom); viewT21 = tool2->createView(); area->addToolView(viewT21, Sublime::Right); viewT31 = tool3->createView(); area->addToolView(viewT31, Sublime::Top); viewT32 = tool3->createView(); area->addToolView(viewT32, Sublime::Top); } void TestViewActivation::cleanup() { delete controller; } void TestViewActivation::signalsOnViewCreationAndDeletion() { Controller *controller = new Controller(this); ToolDocument *doc1 = new ToolDocument("doc1", controller, new SimpleToolWidgetFactory("doc1")); Area *area = new Area(controller, "Area"); QSignalSpy spy(controller, SIGNAL(viewAdded(Sublime::View*))); View *v = doc1->createView(); area->addView(v); QCOMPARE(spy.count(), 1); QSignalSpy spy2(controller, SIGNAL(aboutToRemoveView(Sublime::View*))); area->removeView(v); QCOMPARE(spy2.count(), 1); QSignalSpy spy3(controller, SIGNAL(toolViewAdded(Sublime::View*))); v = doc1->createView(); area->addToolView(v, Sublime::Bottom); QCOMPARE(spy3.count(), 1); QSignalSpy spy4(controller, SIGNAL(aboutToRemoveToolView(Sublime::View*))); area->removeToolView(v); QCOMPARE(spy4.count(), 1); delete controller; } void TestViewActivation::viewActivation() { MainWindow* mw = new MainWindow(controller); controller->addDefaultArea(area); // Q_ASSERT without this. controller->addMainWindow(mw); controller->showArea(area, mw); //we should have an active view immediatelly after the area is shown QCOMPARE(mw->activeView(), view211); //add some widgets that are not in layout QTextEdit *breaker = new QTextEdit(mw); breaker->setObjectName("breaker"); QTextEdit *toolBreaker = new QTextEdit(mw); toolBreaker->setObjectName("toolBreaker"); QDockWidget *dock = new QDockWidget(mw); dock->setWidget(toolBreaker); mw->addDockWidget(Qt::LeftDockWidgetArea, dock); //now post events to the widgets and see if mainwindow has the right active views //activate view qApp->sendEvent(view212->widget(), new QFocusEvent(QEvent::FocusIn)); QString failMsg = QStringLiteral("\nWas expecting %1 to be active but got %2"). arg(view212->objectName()).arg(mw->activeView()->objectName()); QVERIFY2(mw->activeView() == view212, failMsg.toLatin1().data()); //activate toolview and check that both view and toolview are active qApp->sendEvent(viewT31->widget(), new QFocusEvent(QEvent::FocusIn)); QCOMPARE(mw->activeView(), view212); QCOMPARE(mw->activeToolView(), viewT31); //active another view qApp->sendEvent(view241->widget(), new QFocusEvent(QEvent::FocusIn)); QCOMPARE(mw->activeView(), view241); QCOMPARE(mw->activeToolView(), viewT31); //focus a widget not in the area qApp->sendEvent(breaker, new QFocusEvent(QEvent::FocusIn)); QCOMPARE(mw->activeView(), view241); QCOMPARE(mw->activeToolView(), viewT31); //focus a dock not in the area qApp->sendEvent(toolBreaker, new QFocusEvent(QEvent::FocusIn)); QCOMPARE(mw->activeView(), view241); QCOMPARE(mw->activeToolView(), viewT31); //focus inner widget for view221 QListView *inner = mw->findChild("doc2_inner"); QVERIFY(inner); qApp->sendEvent(inner, new QFocusEvent(QEvent::FocusIn)); QCOMPARE(mw->activeView(), view221); QCOMPARE(mw->activeToolView(), viewT31); } void TestViewActivation::activationInMultipleMainWindows() { MainWindow mw(controller); controller->showArea(area, &mw); QCOMPARE(mw.activeView(), view211); //check that new mainwindow always have active view right after displaying area MainWindow mw2(controller); controller->showArea(area, &mw2); QVERIFY(mw2.activeView()); QCOMPARE(mw2.activeView()->document(), doc1); } void TestViewActivation::activationAfterViewRemoval() { MainWindow mw(controller); controller->showArea(area, &mw); QCOMPARE(mw.activeView(), view211); //check what happens if we remove a view which is not the only one in container delete area->removeView(view211); QCOMPARE(mw.activeView(), view212); //check what happens if we remove a view which is alone in container mw.activateView(view231); QCOMPARE(mw.activeView(), view231); delete area->removeView(view231); QCOMPARE(mw.activeView(), view221); } void TestViewActivation::activationAfterRemovalSimplestCase() { //we don't have split views - just two views in one area index MainWindow mw(controller); Area *area = new Area(controller, "Area"); View *v1 = doc1->createView(); View *v2 = doc2->createView(); area->addView(v1); area->addView(v2, v1); controller->showArea(area, &mw); mw.activateView(v2); //delete active view and check that previous is activated delete area->removeView(v2); QCOMPARE(mw.activeView(), v1); } QTEST_MAIN(TestViewActivation) diff --git a/sublime/urldocument.h b/sublime/urldocument.h index 063036422a..b30275c4c4 100644 --- a/sublime/urldocument.h +++ b/sublime/urldocument.h @@ -1,65 +1,65 @@ /*************************************************************************** * Copyright 2006-2007 Alexander Dymo * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_URLDOCUMENT_H #define KDEVPLATFORM_URLDOCUMENT_H #include #include "sublimeexport.h" #include "document.h" namespace Sublime { /** @short Basic document that has an URL. */ class KDEVPLATFORMSUBLIME_EXPORT UrlDocument: public Document { Q_OBJECT public: UrlDocument(Controller *controller, const QUrl &url); - ~UrlDocument(); + ~UrlDocument() override; - virtual QString documentType() const override; + QString documentType() const override; - virtual QString documentSpecifier() const override; + QString documentSpecifier() const override; QUrl url() const; /** * @return the icon for the mimetype of the document url. */ QIcon defaultIcon() const override; - virtual QString title(TitleType type) const override; + QString title(TitleType type) const override; protected: - virtual QWidget *createViewWidget(QWidget *parent = 0) override; + QWidget *createViewWidget(QWidget *parent = 0) override; void setUrl(const QUrl& newUrl); private: struct UrlDocumentPrivate * const d; }; } #endif diff --git a/sublime/view.h b/sublime/view.h index fe1c4b1c30..7d59744c4e 100644 --- a/sublime/view.h +++ b/sublime/view.h @@ -1,112 +1,112 @@ /*************************************************************************** * Copyright 2006-2007 Alexander Dymo * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_SUBLIMEVIEW_H #define KDEVPLATFORM_SUBLIMEVIEW_H #include #include #include "sublimeexport.h" class QAction; namespace Sublime { class Document; /** @short View - the wrapper to the widget that knows about its document Views are the convenient way to manage a widget. It is specifically designed to be light and fast. Use @ref Document::createView() to get the new view for the document and call @ref View::widget() to create and get the actual widget. It is not possible to create a view by hand. You need either subclass it or use a Document. If you create a subclass of View you need to override Sublime::View::createWidget to provide a custom widget for your view. */ class KDEVPLATFORMSUBLIME_EXPORT View: public QObject { Q_OBJECT public: enum WidgetOwnership { TakeOwnership, DoNotTakeOwnerShip }; - ~View(); + ~View() override; /**@return the toolbar actions for this view, this needs to be called _after_ the first call to widget() */ QList toolBarActions() const; /**@return the toolbar actions for this view, this needs to be called _after_ the first call to widget() */ QList contextMenuActions() const; /**@return the document for this view.*/ Document *document() const; /**@return widget for this view (creates it if it's not yet created).*/ QWidget *widget(QWidget *parent = 0); /**@return true if this view has an initialized widget.*/ bool hasWidget() const; /// Retrieve information to be placed in the status bar. virtual QString viewStatus() const; /// Retrieve view state for saving into configuration. virtual QString viewState() const; /// Restore view state from configuration virtual void setState(const QString& state); void notifyPositionChanged(int newPositionInArea); Q_SIGNALS: void raise(Sublime::View*); /// Notify that the status for this document has changed void statusChanged(Sublime::View*); void positionChanged(Sublime::View*, int); public Q_SLOTS: void requestRaise(); protected: View(Document *doc, WidgetOwnership ws = DoNotTakeOwnerShip ); /** * override this function to create a custom widget in your View subclass * @param parent the parent widget * @returns a new widget which is used for this view */ virtual QWidget *createWidget(QWidget *parent); private: Q_PRIVATE_SLOT(d, void unsetWidget()) //copy is not allowed, create a new view from the document instead View(const View &v); struct ViewPrivate *const d; friend class Document; }; } Q_DECLARE_METATYPE(Sublime::View*) #endif diff --git a/template/filters/kdevfilters.h b/template/filters/kdevfilters.h index a1faa5b407..6b95eb90c9 100644 --- a/template/filters/kdevfilters.h +++ b/template/filters/kdevfilters.h @@ -1,94 +1,94 @@ /* This file is part of KDevelop Copyright 2012 Miha Čančula 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 KDEVPLATFORM_KDEVFILTERS_H #define KDEVPLATFORM_KDEVFILTERS_H #include #include #include #include namespace KDevelop { class CamelCaseFilter : public Grantlee::Filter { public: - virtual QVariant doFilter(const QVariant& input, + QVariant doFilter(const QVariant& input, const QVariant& argument = QVariant(), bool autoescape = false) const override; }; class LowerCamelCaseFilter : public Grantlee::Filter { public: - virtual QVariant doFilter(const QVariant& input, + QVariant doFilter(const QVariant& input, const QVariant& argument = QVariant(), bool autoescape = false) const override; }; class UnderscoreFilter : public Grantlee::Filter { public: - virtual QVariant doFilter(const QVariant& input, + QVariant doFilter(const QVariant& input, const QVariant& argument = QVariant(), bool autoescape = false) const override; }; class UpperFirstFilter : public Grantlee::Filter { public: - virtual QVariant doFilter(const QVariant& input, + QVariant doFilter(const QVariant& input, const QVariant& argument = QVariant(), bool autoescape = false) const override; }; class SplitLinesFilter : public Grantlee::Filter { public: - virtual QVariant doFilter(const QVariant& input, + QVariant doFilter(const QVariant& input, const QVariant& argument = QVariant(), bool autoescape = false) const override; }; class ArgumentTypeFilter : public Grantlee::Filter { public: - virtual QVariant doFilter(const QVariant& input, + QVariant doFilter(const QVariant& input, const QVariant& argument = QVariant(), bool autoescape = false) const override; }; class KDevFilters : public QObject, public Grantlee::TagLibraryInterface { Q_OBJECT Q_INTERFACES(Grantlee::TagLibraryInterface) Q_PLUGIN_METADATA(IID "org.grantlee.TagLibraryInterface") public: explicit KDevFilters(QObject* parent = 0, const QVariantList &args = QVariantList()); - virtual ~KDevFilters(); + ~KDevFilters() override; - virtual QHash< QString, Grantlee::Filter* > filters(const QString& name = QString()) override; + QHash< QString, Grantlee::Filter* > filters(const QString& name = QString()) override; }; } #endif // KDEVPLATFORM_KDEVFILTERS_H diff --git a/tests/testfile.h b/tests/testfile.h index 879723823d..90539a0417 100644 --- a/tests/testfile.h +++ b/tests/testfile.h @@ -1,167 +1,167 @@ /* This file is part of KDevelop Copyright 2010 Niko Sams Copyright 2011 Milian Wolff 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. */ #ifndef KDEVPLATFORM_TESTFILE_H #define KDEVPLATFORM_TESTFILE_H #include #include #include "testsexport.h" namespace KDevelop { class TestProject; /** * Helper file to parse a file using the full KDevelop architecture. * * The file will be added to the background parser, and eventually * parsed by a fitting language plugin, just like a normal file * would be in an actual KDevelop instance. * * Example usage: * \code * TestFile file("... * @endcode */ TestFile(const QString& contents, const QString& fileExtension, KDevelop::TestProject *project = 0, const QString& dir = QString()); /** * Create a temporary file from @p contents with the same file basename as * @p other but with the given @p fileExtension. * * @param fileExtension the new file extension without the dot. * @param other a different TestFile which is used for this file's basename * * This can be used to create e.g. .cpp/.h file pairs: * * @code * TestFile header("...", "h"); * TestFile impl("...", "cpp", &header); * @endcode */ TestFile(const QString& contents, const QString& fileExtension, const TestFile* base); /** * Removes temporary file and cleans up. */ - ~TestFile(); + ~TestFile() override; /** * Returns the URL to this file. */ IndexedString url() const; /** * Trigger (re-)parsing of this file with given @p features and @p priority. * * @see KDevelop::DUChain::updateContextForUrl */ void parse(TopDUContext::Features features = TopDUContext::AllDeclarationsContextsAndUses, int priority = 1); /** * Convenience method: * Trigger parse and wait for the file to be parsed. Internally calls waitForParsed() * * @see waitForParsed() * @see parse() */ bool parseAndWait(TopDUContext::Features features = TopDUContext::AllDeclarationsContextsAndUses, int priority = 1, int timeout = 1000); /** * Blocks current thread and waits until the file has been parsed. * * If it has waited longer than @p timeout ms, we return false * and assume something went wrong. * * Otherwise true is returned, indicating parsing finished * within the timeout interval. */ bool waitForParsed(int timeout = 1000); /** * Check whether the file has been processed after the last call to @c parse(). */ bool isReady() const; /** * Returns the @c TopDUContext for the current file, if it has been successfully parsed. */ KDevelop::ReferencedTopDUContext topContext(); /** * Change the file contents to @p contents. * * Use this to test behavior of your parsing code over * file changes. */ void setFileContents(const QString& contents); /** * Read the files contents and return them. */ QString fileContents() const; /** * Set to true when you want to keep the DUChain data. * * By default the DUChain data is removed on destruction of the TestFile. */ void setKeepDUChainData(bool keep); bool keepDUChainData(); private: struct TestFilePrivate; TestFilePrivate* d; Q_PRIVATE_SLOT(d, void updateReady(const KDevelop::IndexedString& url, KDevelop::ReferencedTopDUContext topContext)) }; } #endif // KDEVPLATFORM_TESTFILE_H diff --git a/tests/testlanguagecontroller.h b/tests/testlanguagecontroller.h index c7ad36a368..ccb2f1772f 100644 --- a/tests/testlanguagecontroller.h +++ b/tests/testlanguagecontroller.h @@ -1,45 +1,45 @@ /* * This file is part of KDevelop * * Copyright 2012 Milian Wolff * * 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. */ #ifndef KDEVPLATFORM_TESTLANGUAGECONTROLLER_H #define KDEVPLATFORM_TESTLANGUAGECONTROLLER_H #include "testsexport.h" #include namespace KDevelop { class ILanguageSupport; class KDEVPLATFORMTESTS_EXPORT TestLanguageController : public LanguageController { Q_OBJECT public: TestLanguageController(QObject* parent); - virtual ~TestLanguageController(); + ~TestLanguageController() override; void addTestLanguage(KDevelop::ILanguageSupport* languageSupport, const QStringList& mimetypes); }; } #endif // KDEVPLATFORM_TESTLANGUAGECONTROLLER_H diff --git a/tests/testplugincontroller.h b/tests/testplugincontroller.h index d66a343912..1a987543af 100644 --- a/tests/testplugincontroller.h +++ b/tests/testplugincontroller.h @@ -1,55 +1,55 @@ /* * This file is part of KDevelop * * Copyright 2012 Milian Wolff * * 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. */ #ifndef KDEVPLATFORM_TESTPLUGINCONTROLLER_H #define KDEVPLATFORM_TESTPLUGINCONTROLLER_H #include "testsexport.h" #include #include namespace KDevelop { /** * Dummy controller that disables plugins. */ class KDEVPLATFORMTESTS_EXPORT TestPluginController : public PluginController { Q_OBJECT public: TestPluginController(KDevelop::Core* core); - virtual QList< KDevelop::IPlugin* > allPluginsForExtension(const QString& extension, + QList< KDevelop::IPlugin* > allPluginsForExtension(const QString& extension, const QVariantMap& constraints = QVariantMap()) override; - virtual QList< KDevelop::IPlugin* > loadedPlugins() const override; - virtual KDevelop::IPlugin* pluginForExtension(const QString& extension, const QString& pluginName = {}, const QVariantMap& constraints = QVariantMap()) override; - virtual KDevelop::IPlugin* loadPlugin(const QString& pluginName) override; - virtual KPluginMetaData pluginInfo(const KDevelop::IPlugin*) const override; - virtual QList< KDevelop::ContextMenuExtension > queryPluginsForContextMenuExtensions(KDevelop::Context* context)const override ; - virtual QVector queryExtensionPlugins(const QString& extension, const QVariantMap& constraints = QVariantMap()) const override; - virtual bool unloadPlugin(const QString& plugin) override; - virtual void initialize() override; + QList< KDevelop::IPlugin* > loadedPlugins() const override; + KDevelop::IPlugin* pluginForExtension(const QString& extension, const QString& pluginName = {}, const QVariantMap& constraints = QVariantMap()) override; + KDevelop::IPlugin* loadPlugin(const QString& pluginName) override; + KPluginMetaData pluginInfo(const KDevelop::IPlugin*) const override; + QList< KDevelop::ContextMenuExtension > queryPluginsForContextMenuExtensions(KDevelop::Context* context)const override ; + QVector queryExtensionPlugins(const QString& extension, const QVariantMap& constraints = QVariantMap()) const override; + bool unloadPlugin(const QString& plugin) override; + void initialize() override; }; } #endif // KDEVPLATFORM_TESTPLUGINCONTROLLER_H diff --git a/tests/testproject.h b/tests/testproject.h index 6b7b59a358..a18c645f9f 100644 --- a/tests/testproject.h +++ b/tests/testproject.h @@ -1,106 +1,106 @@ /*************************************************************************** * Copyright 2010 Niko Sams * * Copyright 2012 Milian Wolff * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_TEST_PROJECT_H #define KDEVPLATFORM_TEST_PROJECT_H #include #include #include #include #include "testsexport.h" #include namespace KDevelop { /** * Dummy Project than can be used for Unit Tests. * * Currently only FileSet methods are implemented. */ class KDEVPLATFORMTESTS_EXPORT TestProject : public IProject { Q_OBJECT public: /** * @p url Path to project directory. */ TestProject(const Path& url = Path(), QObject* parent = 0); - virtual ~TestProject(); + ~TestProject() override; IProjectFileManager* projectFileManager() const override { return 0; } IBuildSystemManager* buildSystemManager() const override { return 0; } IPlugin* managerPlugin() const override { return 0; } IPlugin* versionControlPlugin() const override { return 0; } ProjectFolderItem* projectItem() const override; void setProjectItem(ProjectFolderItem* item); int fileCount() const { return 0; } ProjectFileItem* fileAt( int ) const { return 0; } QList files() const; - virtual QList< ProjectBaseItem* > itemsForPath(const IndexedString&) const override { return QList< ProjectBaseItem* >(); } - virtual QList< ProjectFileItem* > filesForPath(const IndexedString&) const override; - virtual QList< ProjectFolderItem* > foldersForPath(const IndexedString&) const override { return QList(); } + QList< ProjectBaseItem* > itemsForPath(const IndexedString&) const override { return QList< ProjectBaseItem* >(); } + QList< ProjectFileItem* > filesForPath(const IndexedString&) const override; + QList< ProjectFolderItem* > foldersForPath(const IndexedString&) const override { return QList(); } void reloadModel() override { } Path projectFile() const override; KSharedConfigPtr projectConfiguration() const override { return m_projectConfiguration; } void addToFileSet( ProjectFileItem* file) override; void removeFromFileSet( ProjectFileItem* file) override; QSet fileSet() const override { return m_fileSet; } bool isReady() const override { return true; } void setPath(const Path& path); Path path() const override; QString name() const override { return "Test Project"; } - virtual bool inProject(const IndexedString& path) const override; - virtual void setReloadJob(KJob* ) override {} + bool inProject(const IndexedString& path) const override; + void setReloadJob(KJob* ) override {} private: QSet m_fileSet; Path m_path; ProjectFolderItem* m_root; KSharedConfigPtr m_projectConfiguration; }; /** * ProjectController that can clear open projects. Useful in Unit Tests. */ class KDEVPLATFORMTESTS_EXPORT TestProjectController : public ProjectController { Q_OBJECT public: TestProjectController(Core* core) : ProjectController(core) {} IProject* projectAt( int i ) const override { return m_projects.at(i); } int projectCount() const override { return m_projects.count(); } QList projects() const override { return m_projects; } public: void addProject(IProject* p); void takeProject(IProject* p); void clearProjects(); - virtual void closeProject(IProject* p) override; + void closeProject(IProject* p) override; - virtual void initialize() override; + void initialize() override; private: QList m_projects; }; } #endif diff --git a/util/activetooltip.h b/util/activetooltip.h index 8e5399b0ad..2f17bbfd22 100644 --- a/util/activetooltip.h +++ b/util/activetooltip.h @@ -1,93 +1,93 @@ /* This file is part of the KDE project Copyright 2007 Vladimir Prus Copyright 2009-2010 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 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 KDEVPLATFORM_ACTIVE_TOOLTIP_H #define KDEVPLATFORM_ACTIVE_TOOLTIP_H #include #include "utilexport.h" namespace KDevelop { /** This class implements a tooltip that can contain arbitrary widgets that the user can interact with. Usage example: KDevelop::ActiveToolTip* tooltip = new KDevelop::ActiveToolTip(mainWindow, QCursor::pos()); QVBoxLayout* layout = new QVBoxLayout(tooltip); layout->addWidget(widget); tooltip->resize( tooltip->sizeHint() ); ActiveToolTip::showToolTip(tooltip); */ class KDEVPLATFORMUTIL_EXPORT ActiveToolTip : public QWidget { Q_OBJECT public: ///@param parent Parent widget. Must not be zero, else the widget won't be shown. /// @param position Position where to show the tooltip, in global coordinates. ActiveToolTip(QWidget *parent, const QPoint& position); - ~ActiveToolTip(); + ~ActiveToolTip() override; ///Shows and registers the given tool-tip. ///This should be used instead of just calling show() to make multiple different ///tooltips work together. ///The tooltip is owned by the manager after this is called. It will delete itself. ///@param tooltip The tooltip to show. It should not be visible yet, show() will eventually be called from here, with some delay. /// The ownership stays with the caller. ///@param priority The priority of this tooltip. Lower is better. Multiple tooltips will be stacked down in the given order. /// If it is zero, the given tooltip will be shown exclusively. ///@param uniqueId If this is nonempty, ActiveTooltip will make sure that only one tooltip with the given id is shown at a time static void showToolTip(ActiveToolTip* tooltip, float priority = 100, const QString& uniqueId = QString()); bool eventFilter(QObject *object, QEvent *e) override; bool insideThis(QObject* object); void showEvent(QShowEvent*) override; void resizeEvent(QResizeEvent*) override; void paintEvent(QPaintEvent*) override; void adjustRect(); ///Clicks within the friend widget are allowed void addFriendWidget(QWidget* widget); ///Set rect of handle (object) this tool tip is created for ///Moving mouse inside this rect, and between this and bounding geometry won't hide the tooltip void setHandleRect(const QRect& rect); ///Set the area within which the mouse can be moved freely without hiding the tooltip void setBoundingGeometry(const QRect& geometry); Q_SIGNALS: void resized(); // Emitted whenever mouse-activity is noticed within the tooltip area void mouseIn(); // Emitted whenever mouse-activity is noticed outside of the tooltip area void mouseOut(); private: - virtual void closeEvent(QCloseEvent* ) override; + void closeEvent(QCloseEvent* ) override; class ActiveToolTipPrivate* const d; }; } #endif diff --git a/util/autoorientedsplitter.h b/util/autoorientedsplitter.h index d59cf92f50..2b12a45ad5 100644 --- a/util/autoorientedsplitter.h +++ b/util/autoorientedsplitter.h @@ -1,52 +1,52 @@ /* This file is part of KDevelop Copyright 2014 Kevin Funk 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 KDEVPLATFORM_AUTOORIENTEDSPLITTER_H #define KDEVPLATFORM_AUTOORIENTEDSPLITTER_H #include "utilexport.h" #include namespace KDevelop { /** * Auto-oriented version of QSplitter based on the aspect ratio of the widget size * * In case this widget is resized, we check whether we're currently in * "portrait" (width < height) or "landscape" (width >= height) mode. * Consequently, in "portrait" mode the QSplitter orientation is set to Qt::Vertical * in order to get a vertical layout of the items -- Qt::Horizontal is set for * "landscape" mode */ class KDEVPLATFORMUTIL_EXPORT AutoOrientedSplitter : public QSplitter { Q_OBJECT public: explicit AutoOrientedSplitter(QWidget* parent = 0); explicit AutoOrientedSplitter(Qt::Orientation orientation, QWidget* parent = 0); protected: - virtual void resizeEvent(QResizeEvent*) override; + void resizeEvent(QResizeEvent*) override; }; } #endif diff --git a/util/commandexecutor.h b/util/commandexecutor.h index ed9ea38664..a1ff1ee8d2 100644 --- a/util/commandexecutor.h +++ b/util/commandexecutor.h @@ -1,143 +1,143 @@ /* This file is part of KDevelop Copyright 2007 Andreas Pakulat 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 KDEVPLATFORM_COMMANDEXECUTOR_H #define KDEVPLATFORM_COMMANDEXECUTOR_H #include #include #include "utilexport.h" namespace KDevelop { /** * Simplifying the exeuction of a Command through (QK)Process. * * This class emits only very basic signals when the process writes something * to stdout or stderr and for signaling completed and failed status of running * the process. This means that a process that is executed without a crash or so * is considered to be completed, even if it indicates an error during execution * using a non-zero return value. This needs to be handled by the user of the class * using the argument in the completed signal * * If you need more fine-grained control use (QK)Process directly and also * check whether you can use \ref KDevelop::ProcessLineMaker to use properly * terminated lines of output. * * Also this class provides only asynchronous operation, it doesn't allow to * wait for the program to finish. * * @author Andreas Pakulat * TODO: Should this be a KJob?? */ class KDEVPLATFORMUTIL_EXPORT CommandExecutor : public QObject { Q_OBJECT public: /** * Create a command using the given executable, arguments and environment * * The process is not started immediately, instead start() has to be called. */ explicit CommandExecutor( const QString& command, QObject* parent = 0 ); - ~CommandExecutor(); + ~CommandExecutor() override; /** * set additional arguments to be used when executing the command */ void setArguments( const QStringList& args ); /** * set additional environment variables to be used when executing the command */ void setEnvironment( const QMap& env ); /** * set additional environment variables to be used when executing the command */ void setEnvironment( const QStringList& env ); /** * Sets the working directory of the command */ void setWorkingDirectory( const QString& dir ); /** * start the command, after this has been called signals may be emitted */ void start(); /** * kill the process, failed() will likely be emitted */ void kill(); /** * set the Command that should be started, now a commandexecutor can be reused */ void setCommand( const QString& command ); /** * whether the commands are executed from a shell */ bool useShell() const; /** * if @p shell is true, the command is executed from a shell */ void setUseShell( bool shell ); /** * @returns the arguments */ QStringList arguments() const; /** * @returns the command */ QString command() const; /** * @returns the working directory */ QString workingDirectory() const; Q_SIGNALS: void receivedStandardError( const QStringList& ); void receivedStandardOutput( const QStringList& ); /** * Emitted when there was a severe problem executing the process, for example it * could not be started or crashed during execution. */ void failed( QProcess::ProcessError ); /** * Emitted when the process was successfully started and finished without crashing * The @p code parameter indicates the return value from executing the process */ void completed(int code); private: Q_PRIVATE_SLOT( d, void procError( QProcess::ProcessError ) ) Q_PRIVATE_SLOT( d, void procFinished( int, QProcess::ExitStatus ) ) class CommandExecutorPrivate* const d; friend class CommandExecutorPrivate; }; } #endif diff --git a/util/environmentselectionmodel.h b/util/environmentselectionmodel.h index 57e1e4f7db..e32e87a731 100644 --- a/util/environmentselectionmodel.h +++ b/util/environmentselectionmodel.h @@ -1,75 +1,75 @@ /* This file is part of KDevelop Copyright 2013 Ivan Shapovalov 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 ENVIRONMENTSELECTIONMODEL_H #define ENVIRONMENTSELECTIONMODEL_H #include "environmentgrouplist.h" #include #include namespace KDevelop { class EnvironmentSelectionModel : public QStringListModel { Q_OBJECT public: enum SpecialRoles { EffectiveNameRole = Qt::UserRole + 1 }; explicit EnvironmentSelectionModel( QObject* parent = 0 ); - virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override; + QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override; - virtual QVariant data( const QModelIndex& index, int role ) const override; - virtual bool setData( const QModelIndex& index, const QVariant& value, int role = Qt::EditRole ) override; + QVariant data( const QModelIndex& index, int role ) const override; + bool setData( const QModelIndex& index, const QVariant& value, int role = Qt::EditRole ) override; /** * @returns The @ref EnvironmentGroupList which has bee used to populate this * model. */ EnvironmentGroupList environment() const; /** * Reloads the model from the global config. */ void reload(); /** * Shall be used by views to update selection (current item) after the model has been reloaded. * * @param currentProfile Previous selected item. * @returns The item which shall become selected. */ QString reloadSelectedItem( const QString& currentProfile ); private: EnvironmentGroupList m_env; QSet m_groupsLookupTable; }; } // namespace KDevelop #endif // ENVIRONMENTSELECTIONMODEL_H diff --git a/util/environmentselectionwidget.h b/util/environmentselectionwidget.h index b0f58eb885..82c059719d 100644 --- a/util/environmentselectionwidget.h +++ b/util/environmentselectionwidget.h @@ -1,89 +1,89 @@ /* This file is part of KDevelop Copyright 2007 Dukju Ahn 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 KDEVPLATFORM_ENVIRONMENTSELECTIONWIDGET_H #define KDEVPLATFORM_ENVIRONMENTSELECTIONWIDGET_H #include #include "utilexport.h" #include "environmentgrouplist.h" namespace KDevelop { /** * Simple combobox which allows each plugin to decide which environment * variable group to use. * * Can be used just like a KComboBox in Configuration dialogs including usage * with KConfigXT. * * @note The widget is populated and defaulted automatically. * */ class KDEVPLATFORMUTIL_EXPORT EnvironmentSelectionWidget : public QWidget { Q_OBJECT Q_PROPERTY( QString currentProfile READ currentProfile WRITE setCurrentProfile NOTIFY currentProfileChanged USER true ) public: explicit EnvironmentSelectionWidget( QWidget *parent = 0 ); - ~EnvironmentSelectionWidget(); + ~EnvironmentSelectionWidget() override; /** * @returns The currently selected environment profile name, as written to KConfigXT */ QString currentProfile() const; /** * Sets the environment profile to be written to KConfigXT and updates the combo-box. * * @param text The environment profile name to select */ void setCurrentProfile( const QString& text ); /** * @returns The currently effective environment profile name (like @ref currentProfile(), * but with empty value resolved to the default profile). */ QString effectiveProfileName() const; /** * @returns The @ref EnvironmentGroupList which has been used to populate this * widget. */ EnvironmentGroupList environment() const; public slots: /** * Makes the widget re-read its environment group list. */ void reconfigure(); Q_SIGNALS: void currentProfileChanged(const QString& currentProfile); private: struct EnvironmentSelectionWidgetPrivate* const d; friend struct EnvironmentSelectionWidgetPrivate; }; } #endif diff --git a/util/executecompositejob.h b/util/executecompositejob.h index 2b8c2df4d8..cb8ebc270c 100644 --- a/util/executecompositejob.h +++ b/util/executecompositejob.h @@ -1,57 +1,57 @@ /* This file is part of KDevelop Copyright 2007-2008 Hamish Rodda 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 KDEVPLATFORM_EXECUTECOMPOSITEJOB_H #define KDEVPLATFORM_EXECUTECOMPOSITEJOB_H #include #include "utilexport.h" template class QList; namespace KDevelop { class KDEVPLATFORMUTIL_EXPORT ExecuteCompositeJob : public KCompositeJob { Q_OBJECT public: explicit ExecuteCompositeJob(QObject* parent = 0, const QList& jobs = {}); - ~ExecuteCompositeJob(); + ~ExecuteCompositeJob() override; - virtual void start() override; + void start() override; void setAbortOnError(bool abort); public Q_SLOTS: - virtual bool addSubjob(KJob* job) override; - virtual void slotResult(KJob* job) override; + bool addSubjob(KJob* job) override; + void slotResult(KJob* job) override; protected Q_SLOTS: virtual void slotPercent(KJob* job, unsigned long percent); protected: - virtual bool doKill() override; + bool doKill() override; private: class ExecuteCompositeJobPrivate* const d; }; } #endif diff --git a/util/focusedtreeview.h b/util/focusedtreeview.h index 26b52234e8..b57e2ef2bc 100644 --- a/util/focusedtreeview.h +++ b/util/focusedtreeview.h @@ -1,67 +1,67 @@ /* This file is part of KDevelop * * Copyright 2009 David Nolden * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef KDEVPLATFORM_FOCUSEDTREEVIEW_H #define KDEVPLATFORM_FOCUSEDTREEVIEW_H #include #include #include "utilexport.h" namespace KDevelop { /** * Specialized version of QTreeView, that allows efficiently managing an extremely * long list of items, by focusing the size of the horizontal scroll-bars only on the currently * visible items. * * In addition, this class provides optional automatic scrolling when rows are inserted at the end. * * @warning Either the scroll-mode ScrollPerItem must be enabled, or the uniformRowHeight flag, for this to work efficiently. * @warning This currently only works with flat list models(todo). */ class KDEVPLATFORMUTIL_EXPORT FocusedTreeView : public QTreeView { Q_OBJECT public: explicit FocusedTreeView(QWidget* parent) ; - virtual ~FocusedTreeView(); + ~FocusedTreeView() override; /** * When enabled, automatically scroll to bottom when new rows are inserted at the end * and the end was previously visible. (Default: false) */ void setAutoScrollAtEnd(bool enable); - virtual void setModel(QAbstractItemModel* model) override; - virtual int sizeHintForColumn(int column) const override; + void setModel(QAbstractItemModel* model) override; + int sizeHintForColumn(int column) const override; private Q_SLOTS: void rowsAboutToBeInserted(const QModelIndex& parent, int first, int last); void rowsRemoved(const QModelIndex& parent, int first, int last); void delayedAutoScrollAndResize(); private: struct Private; std::unique_ptr d; }; } #endif // KDEVPLATFORM_FOCUSEDLISTVIEW_H diff --git a/util/foregroundlock.cpp b/util/foregroundlock.cpp index 2d76fe2dc8..30a2d493e0 100644 --- a/util/foregroundlock.cpp +++ b/util/foregroundlock.cpp @@ -1,242 +1,242 @@ /* Copyright 2010 David Nolden This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "foregroundlock.h" #include #include #include using namespace KDevelop; namespace { QMutex internalMutex; QMutex tryLockMutex; QMutex waitMutex; QMutex finishMutex; QWaitCondition condition; volatile QThread* holderThread = 0; volatile int recursion = 0; void lockForegroundMutexInternal() { if(holderThread == QThread::currentThread()) { // We already have the mutex ++recursion; }else{ internalMutex.lock(); Q_ASSERT(recursion == 0 && holderThread == 0); holderThread = QThread::currentThread(); recursion = 1; } } bool tryLockForegroundMutexInternal(int interval = 0) { if(holderThread == QThread::currentThread()) { // We already have the mutex ++recursion; return true; }else{ if(internalMutex.tryLock(interval)) { Q_ASSERT(recursion == 0 && holderThread == 0); holderThread = QThread::currentThread(); recursion = 1; return true; }else{ return false; } } } void unlockForegroundMutexInternal(bool duringDestruction = false) { /// Note: QThread::currentThread() might already be invalid during destruction. if (!duringDestruction) { Q_ASSERT(holderThread == QThread::currentThread()); } Q_ASSERT(recursion > 0); recursion -= 1; if(recursion == 0) { holderThread = 0; internalMutex.unlock(); } } } ForegroundLock::ForegroundLock(bool lock) : m_locked(false) { if(lock) relock(); } void KDevelop::ForegroundLock::relock() { Q_ASSERT(!m_locked); if(!QApplication::instance() || // Initialization isn't complete yet QThread::currentThread() == QApplication::instance()->thread() || // We're the main thread (deadlock might happen if we'd enter the trylock loop) holderThread == QThread::currentThread()) // We already have the foreground lock (deadlock might happen if we'd enter the trylock loop) { lockForegroundMutexInternal(); }else{ QMutexLocker lock(&tryLockMutex); while(!tryLockForegroundMutexInternal(10)) { // In case an additional event-loop was started from within the foreground, we send // events to the foreground to temporarily release the lock. class ForegroundReleaser : public DoInForeground { public: - virtual void doInternal() override { + void doInternal() override { // By locking the mutex, we make sure that the requester is actually waiting for the condition waitMutex.lock(); // Now we release the foreground lock TemporarilyReleaseForegroundLock release; // And signalize to the requester that we've released it condition.wakeAll(); // Allow the requester to actually wake up, by unlocking m_waitMutex waitMutex.unlock(); // Now wait until the requester is ready QMutexLocker lock(&finishMutex); } }; static ForegroundReleaser releaser; QMutexLocker lockWait(&waitMutex); QMutexLocker lockFinish(&finishMutex); QMetaObject::invokeMethod(&releaser, "doInternalSlot", Qt::QueuedConnection); // We limit the waiting time here, because sometimes it may happen that the foreground-lock is released, // and the foreground is waiting without an event-loop running. (For example through TemporarilyReleaseForegroundLock) condition.wait(&waitMutex, 30); if(tryLockForegroundMutexInternal()) { //success break; }else{ //Probably a third thread has creeped in and //got the foreground lock before us. Just try again. } } } m_locked = true; Q_ASSERT(holderThread == QThread::currentThread()); Q_ASSERT(recursion > 0); } bool KDevelop::ForegroundLock::isLockedForThread() { return QThread::currentThread() == holderThread; } bool KDevelop::ForegroundLock::tryLock() { if(tryLockForegroundMutexInternal()) { m_locked = true; return true; } return false; } void KDevelop::ForegroundLock::unlock() { Q_ASSERT(m_locked); unlockForegroundMutexInternal(); m_locked = false; } TemporarilyReleaseForegroundLock::TemporarilyReleaseForegroundLock() { Q_ASSERT(holderThread == QThread::currentThread()); m_recursion = 0; while(holderThread == QThread::currentThread()) { unlockForegroundMutexInternal(); ++m_recursion; } } TemporarilyReleaseForegroundLock::~TemporarilyReleaseForegroundLock() { for(int a = 0; a < m_recursion; ++a) lockForegroundMutexInternal(); Q_ASSERT(recursion == m_recursion && holderThread == QThread::currentThread()); } KDevelop::ForegroundLock::~ForegroundLock() { if(m_locked) unlock(); } bool KDevelop::ForegroundLock::isLocked() const { return m_locked; } namespace KDevelop { void DoInForeground::doIt() { if(QThread::currentThread() == QApplication::instance()->thread()) { // We're already in the foreground, just call the handler code doInternal(); }else{ QMutexLocker lock(&m_mutex); QMetaObject::invokeMethod(this, "doInternalSlot", Qt::QueuedConnection); m_wait.wait(&m_mutex); } } DoInForeground::~DoInForeground() { } DoInForeground::DoInForeground() { moveToThread(QApplication::instance()->thread()); } void DoInForeground::doInternalSlot() { VERIFY_FOREGROUND_LOCKED doInternal(); QMutexLocker lock(&m_mutex); m_wait.wakeAll(); } } // Important: The foreground lock has to be held by default, so lock it during static initialization static struct StaticLock { StaticLock() { lockForegroundMutexInternal(); } ~StaticLock() { unlockForegroundMutexInternal(true); } } staticLock; diff --git a/util/foregroundlock.h b/util/foregroundlock.h index 87de564496..6150ad7320 100644 --- a/util/foregroundlock.h +++ b/util/foregroundlock.h @@ -1,108 +1,108 @@ /* Copyright 2010 David Nolden This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef KDEVPLATFORM_FOREGROUNDLOCK_H #define KDEVPLATFORM_FOREGROUNDLOCK_H #include "utilexport.h" #include #include #include class QApplication; namespace KDevelop { /** * A locking object that locks the resources that are associated to the main thread. When this lock is held, * you can call any thread-unsafe functions, because the foreground thread is locked in an event. * * The lock always becomes available when the foreground thread stops processing events. * * @warning There is one simple rule you must always follow to prevent deadlocks: * @em Never lock anything before locking the foreground mutex!! * That also means that you must not take this lock in contexts where * you don't know what other mutexes might be locked. * * @warning Objects that have QObject as base always get the thread they were created in assigned (see thread affinity, QObject::moveToThread), * which seriously affects the objects functionality regarding signals/slots. * The foreground lock does not change the thread affinity, so holding the foreground lock does not fully equal being in the foreground. * It may generally be unsafe to call foreground functions that create QObjects from within the background. */ class KDEVPLATFORMUTIL_EXPORT ForegroundLock { public: explicit ForegroundLock(bool lock = true); ~ForegroundLock(); void unlock(); void relock(); bool tryLock(); /// Returns whether the current thread holds the foreground lock static bool isLockedForThread(); bool isLocked() const; private: ForegroundLock(const ForegroundLock& rhs); ForegroundLock& operator=(const ForegroundLock& rhs); bool m_locked; }; /** * Use this object if you want to temporarily release the foreground lock, * for example when sleeping in the foreground thread, or when waiting in the foreground * thread for a background thread which should get the chance to lock the foreground. * * While this object is alive, you _must not_ access any non-threadsafe resources * that belong to the foreground, and you must not start an event-loop. */ class KDEVPLATFORMUTIL_EXPORT TemporarilyReleaseForegroundLock { public: TemporarilyReleaseForegroundLock(); ~TemporarilyReleaseForegroundLock(); private: TemporarilyReleaseForegroundLock(const TemporarilyReleaseForegroundLock&); TemporarilyReleaseForegroundLock& operator=(const TemporarilyReleaseForegroundLock& rhs); int m_recursion; }; #define VERIFY_FOREGROUND_LOCKED Q_ASSERT(KDevelop::ForegroundLock::isLockedForThread()); class KDEVPLATFORMUTIL_EXPORT DoInForeground : public QObject { Q_OBJECT public: DoInForeground() ; - virtual ~DoInForeground() ; + ~DoInForeground() override ; void doIt() ; private Q_SLOTS: void doInternalSlot(); private: virtual void doInternal() = 0; QMutex m_mutex; QWaitCondition m_wait; }; } #endif diff --git a/util/jobstatus.h b/util/jobstatus.h index a949865f08..1c792f546d 100644 --- a/util/jobstatus.h +++ b/util/jobstatus.h @@ -1,70 +1,70 @@ /* * 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 . * */ #pragma once #include "utilexport.h" #include #include class KJob; namespace KDevelop { class JobStatusPrivate; /** * @brief Class for making KJobs exposable to the IStatus interface * * Using this class you use any KJob-based class as source for IStatus updates */ class KDEVPLATFORMUTIL_EXPORT JobStatus : public QObject, public IStatus { Q_OBJECT Q_INTERFACES(KDevelop::IStatus); public: /** * Construct a JobStatus observing the job @p job * * @note As soon as @p job finished, this object will be auto-deleted */ explicit JobStatus(KJob* job, const QString& statusName = QString(), QObject* parent = nullptr); - virtual ~JobStatus(); + ~JobStatus() override; QString statusName() const override; Q_SIGNALS: void clearMessage(KDevelop::IStatus*) override; void hideProgress(KDevelop::IStatus*) override; void showErrorMessage(const QString& message, int timeout = 0) override; void showMessage(KDevelop::IStatus*, const QString& message, int timeout = 0) override; void showProgress(KDevelop::IStatus*, int minimum, int maximum, int value) override; private: QScopedPointer const d; Q_PRIVATE_SLOT(d, void slotPercent(KJob*, unsigned long)); }; } diff --git a/util/kdevstringhandler.cpp b/util/kdevstringhandler.cpp index 59d671fd3f..fbb5f64015 100644 --- a/util/kdevstringhandler.cpp +++ b/util/kdevstringhandler.cpp @@ -1,168 +1,231 @@ /* This file is part of KDevelop Copyright 2009 Andreas Pakulat 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. This file mostly code takes from Qt's QSettings class, the copyright header from that file follows: **************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial Usage ** Licensees holding valid Qt Commercial licenses may use this file in ** accordance with the Qt Commercial License Agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Nokia. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain ** additional rights. These rights are described in the Nokia Qt LGPL ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this ** package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please ** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** **************************************************************************** */ #include "kdevstringhandler.h" #include #include #include #include #include #include #include namespace KDevelop { QString joinWithEscaping( const QStringList& input, const QChar& joinchar, const QChar& escapechar ) { QStringList tmp = input; return tmp.replaceInStrings( joinchar, QString( joinchar ) + QString( escapechar ) ).join( joinchar ); } QStringList splitWithEscaping( const QString& input, const QChar& splitchar, const QChar& escapechar ) { enum State { Normal, SeenEscape } state; state = Normal; QStringList result; QString currentstring; for( int i = 0; i < input.size(); i++ ) { switch( state ) { case Normal: if( input[i] == escapechar ) { state = SeenEscape; } else if( input[i] == splitchar ) { result << currentstring; currentstring = ""; } else { currentstring += input[i]; } break; case SeenEscape: currentstring += input[i]; state = Normal; break; } } if( !currentstring.isEmpty() ) { result << currentstring; } return result; } QVariant stringToQVariant(const QString& s) { // Taken from qsettings.cpp, stringToVariant() if (s.startsWith(QLatin1Char('@'))) { if (s.endsWith(QLatin1Char(')'))) { if (s.startsWith(QLatin1String("@Variant("))) { QByteArray a(s.toLatin1().mid(9)); QDataStream stream(&a, QIODevice::ReadOnly); stream.setVersion(QDataStream::Qt_4_4); QVariant result; stream >> result; return result; } } } return QVariant(); } QString qvariantToString(const QVariant& variant) { // Taken from qsettings.cpp, variantToString() QByteArray a; { QDataStream s(&a, QIODevice::WriteOnly); s.setVersion(QDataStream::Qt_4_4); s << variant; } QString result = QLatin1String("@Variant("); result += QString::fromLatin1(a.constData(), a.size()); result += QLatin1Char(')'); return result; } QString htmlToPlainText(const QString& s, HtmlToPlainTextMode mode) { switch (mode) { case FastMode: { QString result(s); result.remove(QRegExp("<[^>]+>")); return result; } case CompleteMode: { QTextDocument doc; doc.setHtml(s); return doc.toPlainText(); } } return QString(); // never reached } } +QString KDevelop::stripAnsiSequences(const QString& str) +{ + if (str.isEmpty()) { + return QString(); // fast path + } + + enum { + PLAIN, + ANSI_START, + ANSI_CSI, + ANSI_SEQUENCE, + ANSI_WAITING_FOR_ST, + ANSI_ST_STARTED + } state = PLAIN; + + QString result; + result.reserve(str.count()); + + foreach (const QChar c, str) { + const auto val = c.unicode(); + switch (state) { + case PLAIN: + if (val == 27) // 'ESC' + state = ANSI_START; + else if (val == 155) // equivalent to 'ESC'-'[' + state = ANSI_CSI; + else + result.append(c); + break; + case ANSI_START: + if (val == 91) // [ + state = ANSI_CSI; + else if (val == 80 || val == 93 || val == 94 || val == 95) // 'P', ']', '^' and '_' + state = ANSI_WAITING_FOR_ST; + else if (val >= 64 && val <= 95) + state = PLAIN; + else + state = ANSI_SEQUENCE; + break; + case ANSI_CSI: + if (val >= 64 && val <= 126) // Anything between '@' and '~' + state = PLAIN; + break; + case ANSI_SEQUENCE: + if (val >= 64 && val <= 95) // Anything between '@' and '_' + state = PLAIN; + break; + case ANSI_WAITING_FOR_ST: + if (val == 7) // 'BEL' + state = PLAIN; + else if (val == 27) // 'ESC' + state = ANSI_ST_STARTED; + break; + case ANSI_ST_STARTED: + if (val == 92) // '\' + state = PLAIN; + else + state = ANSI_WAITING_FOR_ST; + break; + } + } + return result; +} diff --git a/util/kdevstringhandler.h b/util/kdevstringhandler.h index 684798b27a..3dcce4592c 100644 --- a/util/kdevstringhandler.h +++ b/util/kdevstringhandler.h @@ -1,65 +1,71 @@ /* This file is part of KDevelop Copyright 2009 Andreas Pakulat 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 KDEVPLATFORM_KDEVSTRINGHANDLER_H #define KDEVPLATFORM_KDEVSTRINGHANDLER_H #include "utilexport.h" class QString; class QChar; class QStringList; class QVariant; namespace KDevelop { KDEVPLATFORMUTIL_EXPORT QStringList splitWithEscaping( const QString& input, const QChar& splitChar, const QChar& escapeChar ); KDEVPLATFORMUTIL_EXPORT QString joinWithEscaping( const QStringList& input, const QChar& joinChar, const QChar& escapeChar ); /** * convert the @p variant into a string which can then be stored * easily in a KConfig entry. This supports any QVariant type (including custom types) * for which there is a QDataStream operator defined * @returns a QString containing the data from the QVariant. */ KDEVPLATFORMUTIL_EXPORT QString qvariantToString( const QVariant& variant ); /** * convert the @p s into a QVariant, usually the string is read from KConfig. * This supports any QVariant type (including custom types) * for which there is a QDataStream operator defined * @returns a QVariant created from the bytearray */ KDEVPLATFORMUTIL_EXPORT QVariant stringToQVariant( const QString& s ); enum HtmlToPlainTextMode { FastMode, /**< Fast (conversion via regular expression) */ CompleteMode, /**< Slower, but with expected behavior (conversion via QTextDocument::toPlainText). This also replaces
with newline chars, for example. */ }; /** * Strip HTML tags from string @p s * * @return String no longer containing any HTML tags */ KDEVPLATFORMUTIL_EXPORT QString htmlToPlainText(const QString& s, HtmlToPlainTextMode mode = FastMode); + + /** + * Strip ANSI sequences from string @p str + */ + KDEVPLATFORMUTIL_EXPORT QString stripAnsiSequences(const QString& str); + } #endif // KDEVPLATFORM_KDEVSTRINGHANDLER_H diff --git a/util/multilevellistview.cpp b/util/multilevellistview.cpp index b5533e5eba..1c507b6bf8 100644 --- a/util/multilevellistview.cpp +++ b/util/multilevellistview.cpp @@ -1,456 +1,456 @@ /* This file is part of KDevelop Copyright 2012 Miha Čančula 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 "multilevellistview.h" #include #include #include #include #include /** * Interface to set the label of a model. */ class LabeledProxy { public: virtual ~LabeledProxy() { } void setLabel(const QString& label) { m_label = label; } protected: QString m_label; }; /** * The left-most view's model which only contains the root nodes of the source model. */ class RootProxyModel : public QSortFilterProxyModel, public LabeledProxy { Q_OBJECT public: RootProxyModel( QObject* parent = 0 ) : QSortFilterProxyModel( parent ) { } - virtual bool filterAcceptsRow( int /*source_row*/, const QModelIndex& source_parent ) const override + bool filterAcceptsRow( int /*source_row*/, const QModelIndex& source_parent ) const override { return !source_parent.isValid(); } - virtual QVariant headerData( int section, Qt::Orientation orientation, + QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override { if (sourceModel() && section == 0 && orientation == Qt::Horizontal && role == Qt::DisplayRole) { return m_label; } else { return QVariant(); } } }; /** * A class that automatically updates its contents based on the selection in another view. */ class SubTreeProxyModel : public KSelectionProxyModel, public LabeledProxy { Q_OBJECT public: explicit SubTreeProxyModel( QItemSelectionModel* selectionModel, QObject* parent = 0 ) : KSelectionProxyModel( selectionModel, parent ) {} - virtual QVariant headerData( int section, Qt::Orientation orientation, + QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override { if (sourceModel() && section == 0 && orientation == Qt::Horizontal && role == Qt::DisplayRole) { return m_label; } else { return QVariant(); } } - virtual Qt::ItemFlags flags(const QModelIndex& index) const override + Qt::ItemFlags flags(const QModelIndex& index) const override { Qt::ItemFlags ret = KSelectionProxyModel::flags(index); if (filterBehavior() == KSelectionProxyModel::SubTreesWithoutRoots && hasChildren(index)) { // we want to select child items ret &= ~Qt::ItemIsSelectable; } return ret; } }; using namespace KDevelop; class KDevelop::MultiLevelListViewPrivate { public: MultiLevelListViewPrivate(MultiLevelListView* view); ~MultiLevelListViewPrivate(); void viewSelectionChanged(const QModelIndex& current, const QModelIndex& previous); void lastViewsContentsChanged(); void ensureViewSelected(QTreeView* view); /** * @param index index in any of our proxy models * @return an index in the source model */ QModelIndex mapToSource(QModelIndex index); /** * @param index an index in the source model * @return an index in the view's model at level @p level */ QModelIndex mapFromSource(QModelIndex index, int level); MultiLevelListView* view; int levels; QList views; QList proxies; QList layouts; QAbstractItemModel* model; }; MultiLevelListViewPrivate::MultiLevelListViewPrivate(MultiLevelListView* view_) : view(view_) , levels(0) , model(0) { } MultiLevelListViewPrivate::~MultiLevelListViewPrivate() { } void MultiLevelListViewPrivate::viewSelectionChanged(const QModelIndex& current, const QModelIndex& previous) { if (!current.isValid()) { // ignore, as we should always have some kind of selection return; } // figure out which proxy this signal belongs to QAbstractProxyModel* proxy = qobject_cast( const_cast(current.model())); Q_ASSERT(proxy); // what level is this proxy in int level = -1; for(int i = 0; i < levels; ++i) { if (views.at(i)->model() == proxy) { level = i; break; } } Q_ASSERT(level >= 0 && level < levels); if (level + 1 == levels) { // right-most view if (current.child(0, 0).isValid()) { // select the first leaf node for this view QModelIndex idx = current; QModelIndex child = idx.child(0, 0); while(child.isValid()) { idx = child; child = idx.child(0, 0); } views.last()->setCurrentIndex(idx); return; } // signal that our actual selection has changed emit view->currentIndexChanged(mapToSource(current), mapToSource(previous)); } else { // some leftish view // ensure the next view's first item is selected QTreeView* treeView = views.at(level + 1); // we need to delay the call, because at this point the child view // will still have its old data which is going to be invalidated // right after this method exits // be we must not set the index to 0,0 here directly, since e.g. // MultiLevelListView::setCurrentIndex might have been used, which // sets a proper index already. QMetaObject::invokeMethod(view, "ensureViewSelected", Qt::QueuedConnection, Q_ARG(QTreeView*, treeView)); } } void MultiLevelListViewPrivate::lastViewsContentsChanged() { views.last()->expandAll(); } void MultiLevelListViewPrivate::ensureViewSelected(QTreeView* view) { if (!view->currentIndex().isValid()) { view->setCurrentIndex(view->model()->index(0, 0)); } } QModelIndex MultiLevelListViewPrivate::mapToSource(QModelIndex index) { if (!index.isValid()) { return index; } while(index.model() != model) { QAbstractProxyModel* proxy = qobject_cast( const_cast(index.model())); Q_ASSERT(proxy); index = proxy->mapToSource(index); Q_ASSERT(index.isValid()); } return index; } QModelIndex MultiLevelListViewPrivate::mapFromSource(QModelIndex index, int level) { if (!index.isValid()) { return index; } Q_ASSERT(index.model() == model); QAbstractProxyModel* proxy = qobject_cast(views.at(level)->model()); Q_ASSERT(proxy); // find all proxies between the source and our view QVector proxies; proxies << proxy; forever { QAbstractProxyModel* child = qobject_cast(proxy->sourceModel()); if (child) { proxy = child; proxies << proxy; } else { Q_ASSERT(proxy->sourceModel() == model); break; } } // iterate in reverse order to find the view's index for(int i = proxies.size() - 1; i >= 0; --i) { proxy = proxies.at(i); index = proxy->mapFromSource(index); Q_ASSERT(index.isValid()); } return index; } MultiLevelListView::MultiLevelListView(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) , d(new MultiLevelListViewPrivate(this)) { delete layout(); setLayout(new QHBoxLayout()); layout()->setContentsMargins(0, 0, 0, 0); qRegisterMetaType("QTreeView*"); } MultiLevelListView::~MultiLevelListView() { delete d; } int MultiLevelListView::levels() const { return d->levels; } void MultiLevelListView::setLevels(int levels) { qDeleteAll(d->views); qDeleteAll(d->proxies); qDeleteAll(d->layouts); d->views.clear(); d->proxies.clear(); d->layouts.clear(); d->levels = levels; QTreeView* previousView = 0; for (int i = 0; i < d->levels; ++i) { QVBoxLayout* levelLayout = new QVBoxLayout(); QTreeView* view = new QTreeView(this); view->setContentsMargins(0, 0, 0, 0); // only the right-most view is decorated view->setRootIsDecorated(i + 1 == d->levels); view->setHeaderHidden(false); view->setSelectionMode(QAbstractItemView::SingleSelection); if (!previousView) { // the root, i.e. left-most view RootProxyModel* root = new RootProxyModel(this); root->setDynamicSortFilter(true); d->proxies << root; root->setSourceModel(d->model); view->setModel(root); } else { SubTreeProxyModel* subTreeProxy = new SubTreeProxyModel(previousView->selectionModel(), this); if (i + 1 < d->levels) { // middel views only shows children of selection subTreeProxy->setFilterBehavior(KSelectionProxyModel::ChildrenOfExactSelection); } else { // right-most view shows the rest subTreeProxy->setFilterBehavior(KSelectionProxyModel::SubTreesWithoutRoots); } d->proxies << subTreeProxy; subTreeProxy->setSourceModel(d->model); // sorting requires another proxy in-between QSortFilterProxyModel* sortProxy = new QSortFilterProxyModel(subTreeProxy); sortProxy->setSourceModel(subTreeProxy); sortProxy->setDynamicSortFilter(true); view->setModel(sortProxy); } // view->setModel creates the selection model connect(view->selectionModel(), &QItemSelectionModel::currentChanged, this, [&] (const QModelIndex& current, const QModelIndex& previous) { d->viewSelectionChanged(current, previous); }); if (i + 1 == d->levels) { connect(view->model(), &QAbstractItemModel::rowsInserted, this, [&] { d->lastViewsContentsChanged(); }); } view->setSortingEnabled(true); view->sortByColumn(0, Qt::AscendingOrder); levelLayout->addWidget(view); layout()->addItem(levelLayout); d->layouts << levelLayout; d->views << view; previousView = view; } setModel(d->model); } QAbstractItemModel* MultiLevelListView::model() const { return d->model; } void MultiLevelListView::setModel(QAbstractItemModel* model) { d->model = model; foreach (LabeledProxy* proxy, d->proxies) { dynamic_cast(proxy)->setSourceModel(model); } if (model && !d->views.isEmpty()) { d->views.first()->setCurrentIndex(d->views.first()->model()->index(0, 0)); } } QTreeView* MultiLevelListView::viewForLevel( int level ) const { return d->views[level]; } void MultiLevelListView::addWidget(int level, QWidget* widget) { Q_ASSERT(level < d->levels); d->layouts[level]->addWidget(widget); } QModelIndex MultiLevelListView::currentIndex() const { return d->mapToSource(d->views.last()->currentIndex()); } void MultiLevelListView::setCurrentIndex(const QModelIndex& index) { // incoming index is for the original model Q_ASSERT(!index.isValid() || index.model() == d->model); const QModelIndex previous = currentIndex(); QModelIndex idx(index); QModelIndexList indexes; while (idx.isValid()) { indexes.prepend(idx); idx = idx.parent(); } for (int i = 0; i < d->levels; ++i) { QTreeView* view = d->views.at(i); if (indexes.size() <= i) { // select first item by default view->setCurrentIndex(view->model()->index(0, 0)); continue; } QModelIndex index; if (i + 1 == d->levels) { // select the very last index in the list (i.e. might be deep down in the actual tree) index = indexes.last(); } else { // select the first index for that level index = indexes.at(i); } view->setCurrentIndex(d->mapFromSource(index, i)); } emit currentIndexChanged(index, previous); } void MultiLevelListView::setRootIndex(const QModelIndex& index) { Q_ASSERT(!index.isValid() || index.model() == d->model); d->views.first()->setRootIndex(index); } void MultiLevelListView::setHeaderLabels(const QStringList& labels) { int n = qMin(d->levels, labels.size()); for (int i = 0; i < n; ++i) { d->proxies.at(i)->setLabel(labels[i]); } } void MultiLevelListView::setLastModelsFilterBehavior(KSelectionProxyModel::FilterBehavior filter) { if (d->proxies.isEmpty()) { return; } dynamic_cast(d->proxies.last())->setFilterBehavior(filter); } #include "multilevellistview.moc" #include "moc_multilevellistview.cpp" diff --git a/util/multilevellistview.h b/util/multilevellistview.h index 947cfc4b58..3c6fc661b1 100644 --- a/util/multilevellistview.h +++ b/util/multilevellistview.h @@ -1,152 +1,152 @@ /* This file is part of KDevelop Copyright 2012 Miha Čančula 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 KDEVPLATFORM_MULTILEVELLISTVIEW_H #define KDEVPLATFORM_MULTILEVELLISTVIEW_H #include #include #include "utilexport.h" class QTreeView; class QModelIndex; class QAbstractItemModel; namespace KDevelop { /** * A view for displaying a tree structure in a series of list views. * * A MultiLevelListView can have any number of levels, with one list view for each level. * Selecting an item at one level causes that item to become the root of the next level. * * For compatibility and convenience, this class has methods and signals similar to those of * QAbstractItemView, such as setModel(), setRootIndex() and currentIndexChanged(). */ class KDEVPLATFORMUTIL_EXPORT MultiLevelListView : public QWidget { Q_OBJECT public: /** * Creates a new MultiLevelListView with parent @p parent. * * Call setLevels() afterwards to set the number of list views. * * @param parent parent widget * @param f window flags, passed to QWidget */ explicit MultiLevelListView(QWidget* parent = 0, Qt::WindowFlags f = 0); /** * Default destructor */ - virtual ~MultiLevelListView(); + ~MultiLevelListView() override; /** * @return the number of list view */ int levels() const; /** * Sets the number of levels, i.e. the number of list views visible, to @p levels * @param levels the new number of levels */ void setLevels(int levels); /** * @return the model displayed by this view, or 0 if none was set * @sa QAbstractItemView::model() */ QAbstractItemModel* model() const; /** * Sets the model to be displayed by this view. * * @param model the model to be displayed * @sa QAbstractItemView::setModel() */ void setModel(QAbstractItemModel* model); /** * Provides access to the QTreeView objects used internally. * Returns the view for level @p level of the tree structure. * * @param level the level of the tree structure shown by the returned view */ QTreeView* viewForLevel(int level) const; /** * The current index of the view. * * The current index is determined as the current index of the last list view. * * @sa QAbstractItemView::currentIndex() */ QModelIndex currentIndex() const; /** * Adds the widget @p widget under the list view for level @p level. * This function can be used to insert custom widgets into the view hierarchy. * * @param level specifies where to place the widget * @param widget the widget to add */ void addWidget(int level, QWidget* widget); void setHeaderLabels(const QStringList& labels); /** * Set the filter behavior of the last model. By default, SubTreesWithoutRoots * is used and only leafs are selectable in the view for that model. */ void setLastModelsFilterBehavior(KSelectionProxyModel::FilterBehavior filter); signals: /** * Notified that the current index has changed from @p previous to @p current * * @param current the new current index * @param previous the previous index * * @sa currentIndex(), QItemSelectionModel::currentChanged() */ void currentIndexChanged(const QModelIndex& current, const QModelIndex& previous); public slots: /** * Sets the root index of the entire view to @p index. * * @sa QAbstractItemView::setRootIndex() */ void setRootIndex(const QModelIndex& index); /** * Sets the current index to @p index. * * @sa currentIndex(), QAbstractItemView::setCurrentIndex() */ void setCurrentIndex(const QModelIndex& index); private: friend class MultiLevelListViewPrivate; class MultiLevelListViewPrivate* const d; Q_PRIVATE_SLOT(d, void viewSelectionChanged(const QModelIndex& current, const QModelIndex& previous)) Q_PRIVATE_SLOT(d, void lastViewsContentsChanged()) Q_PRIVATE_SLOT(d, void ensureViewSelected(QTreeView* view)) }; } #endif // KDEVPLATFORM_MULTILEVELLISTVIEW_H diff --git a/util/objectlist.h b/util/objectlist.h index fa42eb0a87..beec1bf805 100644 --- a/util/objectlist.h +++ b/util/objectlist.h @@ -1,137 +1,137 @@ /* * Copyright 2014 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 KDEVPLATFORM_OBJECTLIST_H #define KDEVPLATFORM_OBJECTLIST_H #include #include #include "utilexport.h" namespace KDevelop { /** * @brief Class for tracking a set of alive objects inheriting from QObject. * * Add individual objects via the append() method to have their lifetime being monitored by this class. * In case one of the tracked objects is destroyed, it is removed from the list. * * This means this class always contains a set of valid pointers to QObject instances. * The up-to-date list can be access via the data() method. * * @note You are *not* being notified if an item is removed from the list. * The purpose of this class is to provide a simple mechanism to keep track of a set of *alive* objects * * @sa append() * @sa data() */ class KDEVPLATFORMUTIL_EXPORT ObjectListTracker : public QObject { Q_OBJECT public: enum CleanupBehavior { NoCleanupWhenDone, ///< Do nothing when this object is destructed CleanupWhenDone ///< Delete list of items when this object is destructed }; explicit ObjectListTracker(CleanupBehavior behavior = NoCleanupWhenDone, QObject* parent = 0); - virtual ~ObjectListTracker(); + ~ObjectListTracker() override; /** * Append and track object @p object * * In case @p object is destroyed, it gets removed from the list * * @note If @p object is already tracked, this operation is a no-op */ void append(QObject* object); /** * Remove and no longer track object @p object * * @return False if object @p object wasn't tracked or null, otherwise true */ bool remove(QObject* object); /** * Delete all objects currently tracked and clears the list */ void deleteAll(); /** * Accessor towards to the internal list of currently tracked objects */ const QList& data() const; private: void objectDestroyed(QObject*); private: struct Private; QScopedPointer const d; }; /** * @brief Template-based wrapper around ObjectListTracker for tracking a set of objects inheriting from QObject * * Provides a type-safe way to access and mutate ObjectListTracker * * @sa KDevelop::ObjectListTracker */ template class ObjectList { public: ObjectList(ObjectListTracker::CleanupBehavior behavior = ObjectListTracker::NoCleanupWhenDone) : m_tracker(behavior) { }; void append(T* object) { m_tracker.append(object); } bool remove(T* object) { return m_tracker.remove(object); } void deleteAll() { m_tracker.deleteAll(); } /** * Accessor to the up-to-date list inside the object tracker */ QList data() const { // This is considered safe, as QList and QList have the same memory layout // also see http://comments.gmane.org/gmane.comp.lib.qt.general/38943 return *reinterpret_cast*>(&m_tracker.data()); } private: ObjectListTracker m_tracker; }; } #endif // KDEVPLATFORM_OBJECTLIST_H diff --git a/util/placeholderitemproxymodel.h b/util/placeholderitemproxymodel.h index d11001d529..06c9bfc370 100644 --- a/util/placeholderitemproxymodel.h +++ b/util/placeholderitemproxymodel.h @@ -1,118 +1,118 @@ /* * Copyright 2013 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 KDEVPLATFORM_PLACEHOLDERITEMPROXYMODEL_H #define KDEVPLATFORM_PLACEHOLDERITEMPROXYMODEL_H #include "utilexport.h" #include #include namespace KDevelop { /** * Proxy model adding a placeholder item for new entries * * This is mostly a QIdentityProxyModel, with one additional row added at the end * * Example use: * * @code * PlaceholderItemProxyModel* proxyModel = new PlaceholderItemProxyModel; * proxyModel->setSourceModel(new MyItemModel); * proxyModel->setColumnHint(0, "(Add new entry)"); * connect(proxyModel, SIGNAL(dataInserted(...), SLOT(handleDataInserted(...)); * @endcode * * In this case MyItemModel has exactly two entries, "Item1" and "Item2" * * This will end up in PlaceholderItemProxyModel holding the following indices: * - "Item1" (from source model) * - "Item2" (from source model) * - "(Add new entry)" (from PlaceholderItemProxyModel) * * In case the last entry is edited, and a non-empty value is supplied, * dataInserted() is emitted to notify the user about newly created rows. * The user then has to make sure the signal is handled accordingly and * new items are added to the source model. * * @see dataInserted * * @note WARNING: This implementation is only suitable for flat models * It will fall apart when you use a tree model as source */ class KDEVPLATFORMUTIL_EXPORT PlaceholderItemProxyModel : public QIdentityProxyModel { Q_OBJECT public: explicit PlaceholderItemProxyModel(QObject* parent = 0); - virtual ~PlaceholderItemProxyModel(); + ~PlaceholderItemProxyModel() override; QVariant columnHint(int column) const; /** * Set the hint value for @p column to @p hint * * This text is going to be displayed in the place holder item row * * Only columns with non-empty hints are clickable and editable and * eventually cause the dataInserted() signal to be triggered */ void setColumnHint(int column, const QVariant& hint); - virtual void setSourceModel(QAbstractItemModel* sourceModel) override; + void setSourceModel(QAbstractItemModel* sourceModel) override; - virtual Qt::ItemFlags flags(const QModelIndex& index) const override; - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; - virtual QVariant data(const QModelIndex& proxyIndex, int role = Qt::DisplayRole) const override; - virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; - virtual QModelIndex parent(const QModelIndex& child) const override; - virtual QModelIndex sibling(int row, int column, const QModelIndex& idx) const override; - virtual QModelIndex buddy(const QModelIndex& index) const override; - virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + Qt::ItemFlags flags(const QModelIndex& index) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& proxyIndex, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; + QModelIndex parent(const QModelIndex& child) const override; + QModelIndex sibling(int row, int column, const QModelIndex& idx) const override; + QModelIndex buddy(const QModelIndex& index) const override; + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; - virtual QModelIndex mapToSource(const QModelIndex& proxyIndex) const override; + QModelIndex mapToSource(const QModelIndex& proxyIndex) const override; /** * Implement in subclass. * * @return True in case the input was valid, and the filter should notify * external observers via the dataInserted signal. * * By default, this method returns true only in case @p value is non-empty * * @sa dataInserted() */ virtual bool validateRow(const QModelIndex& index, const QVariant& value) const; Q_SIGNALS: void dataInserted(int column, const QVariant& values); private: struct Private; QScopedPointer const d; }; } #endif // KDEVPLATFORM_PLACEHOLDERITEMPROXYMODEL_H diff --git a/util/processlinemaker.h b/util/processlinemaker.h index 58334a8ec0..b5e5d061ba 100644 --- a/util/processlinemaker.h +++ b/util/processlinemaker.h @@ -1,120 +1,120 @@ /* This file is part of the KDE project Copyright 2002 John Firebaugh Copyright 2007 Andreas Pakulat Copyright 2007 Oswald Buddenhagen 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 _PROCESSLINEMAKER_H_ #define _PROCESSLINEMAKER_H_ #include #include "utilexport.h" /** @file processlinemaker.h Utility objects for process output views. */ class QProcess; class QStringList; /** Convenience class to catch output of QProcess. */ namespace KDevelop { class KDEVPLATFORMUTIL_EXPORT ProcessLineMaker : public QObject { Q_OBJECT public: explicit ProcessLineMaker( QObject* parent = 0 ); explicit ProcessLineMaker( QProcess* process, QObject* parent = 0 ); - ~ProcessLineMaker(); + ~ProcessLineMaker() override; /** * clears out the internal buffers, this drops any data without * emitting the related signal */ void discardBuffers(); /** * Flush the data from the buffers and then clear them. * This should be called once when the process has * exited to make sure all data that was received from the * process is properly converted and emitted. * * Note: Connecting this class to the process finished signal * is not going to work, as the user of this class will do * that itself too and possibly delete the process, making * it impossible to fetch the last output. */ void flushBuffers(); public Q_SLOTS: /** * This should be used (instead of hand-crafted code) when * you need to do custom things with the process output * before feeding it to the linemaker and have it convert * it to QString lines. * @param buffer the output from the process */ void slotReceivedStdout( const QByteArray& buffer ); /** * This should be used (instead of hand-crafted code) when * you need to do custom things with the process error output * before feeding it to the linemaker and have it convert * it to QString lines. * @param buffer the output from the process */ void slotReceivedStderr( const QByteArray& buffer ); Q_SIGNALS: /** * Emitted whenever the process prints something * to its standard output. The output is converted * to a QString using fromLocal8Bit() and will * be split on '\n'. * @param lines the lines that the process printed */ void receivedStdoutLines( const QStringList& lines ); /** * Emitted whenever the process prints something * to its error output. The output is converted * to a QString using fromLocal8Bit() and will * be split on '\n'. * @param lines the lines that the process printed */ void receivedStderrLines( const QStringList& lines ); private: Q_PRIVATE_SLOT(d, void slotReadyReadStdout( ) ) Q_PRIVATE_SLOT(d, void slotReadyReadStderr( ) ) class ProcessLineMakerPrivate* const d; friend class ProcessLineMakerPrivate; }; } #endif diff --git a/util/projecttestjob.h b/util/projecttestjob.h index 557818df4a..02ea53b1d8 100644 --- a/util/projecttestjob.h +++ b/util/projecttestjob.h @@ -1,123 +1,123 @@ /* * This file is part of KDevelop * * Copyright 2012 Miha Čančula * * 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. */ #ifndef KDEVPLATFORM_PROJECTTESTJOB_H #define KDEVPLATFORM_PROJECTTESTJOB_H #include #include "utilexport.h" namespace KDevelop { class IProject; class ITestSuite; struct TestResult; /** * A combined result of a project test job * * @sa ProjectTestJob * **/ struct KDEVPLATFORMUTIL_EXPORT ProjectTestResult { ProjectTestResult() : total(0) , passed(0) , failed(0) , error(0) {} /** * The total number of test suites launched in this job **/ int total; /** * The number of passed test suites in this job. **/ int passed; /** * The number of failed test suites in this job. **/ int failed; /** * The number of errors in this job. **/ int error; }; /** * @brief A job that tests an entire project and reports the total result * * Launches all test suites in the specified project without raising the output window. * Instead of providing individual test results, it combines and simplifies them. * **/ class KDEVPLATFORMUTIL_EXPORT ProjectTestJob : public KJob { Q_OBJECT public: /** * Create a project test job * * @param project The project to be tested * @param parent This job's parent object, or 0 for no parent. * **/ explicit ProjectTestJob(IProject* project, QObject* parent = 0); /** * Destructor * **/ - virtual ~ProjectTestJob(); + ~ProjectTestJob() override; /** * Start this job. **/ - virtual void start() override; + void start() override; /** * @brief The result of this job * * This function only returns a correnct result after all the tests are completed. * It is therefore best to call this after the KJob::result() signal is emitted. * * @sa ProjectTestResult **/ ProjectTestResult testResult(); protected: - virtual bool doKill() override; + bool doKill() override; private: struct Private; QScopedPointer d; Q_PRIVATE_SLOT(d, void runNext()); Q_PRIVATE_SLOT(d, void gotResult(KDevelop::ITestSuite* suite, const KDevelop::TestResult& result)); }; } Q_DECLARE_TYPEINFO(KDevelop::ProjectTestResult, Q_MOVABLE_TYPE); #endif // KDEVPLATFORM_PROJECTTESTJOB_H diff --git a/util/richtextpushbutton.h b/util/richtextpushbutton.h index 59186394c5..5f3edc5df1 100644 --- a/util/richtextpushbutton.h +++ b/util/richtextpushbutton.h @@ -1,57 +1,57 @@ /* Copyright 2010 Unknown Author (Qt Centre) Copyright 2010 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 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 KDEVPLATFORM_RICHTEXTPUSHBUTTON_H #define KDEVPLATFORM_RICHTEXTPUSHBUTTON_H #include #include #include #include "utilexport.h" namespace KDevelop { class KDEVPLATFORMUTIL_EXPORT RichTextPushButton : public QPushButton { Q_OBJECT public: explicit RichTextPushButton(QWidget *parent = 0); void setHtml(const QString &text); void setText(const QString &text); QString text() const; - virtual QSize sizeHint() const override; + QSize sizeHint() const override; signals: public slots: protected: void paintEvent(QPaintEvent *) override; private: QString htmlText; bool isRichText; QStyleOptionButton getStyleOption() const; }; } #endif // KDEVPLATFORM_RICHTEXTPUSHBUTTON_H diff --git a/util/tests/test_foregroundlock.cpp b/util/tests/test_foregroundlock.cpp index dfad63bb19..929de01e2a 100644 --- a/util/tests/test_foregroundlock.cpp +++ b/util/tests/test_foregroundlock.cpp @@ -1,89 +1,89 @@ /* Copyright 2010 Milian Wolff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "test_foregroundlock.h" #include #include #include "../foregroundlock.h" QTEST_MAIN(KDevelop::TestForegroundLock) using namespace KDevelop; //BEGIN Helper Threads class TryLockThread : public QThread { Q_OBJECT public: - virtual void run() override { + void run() override { ForegroundLock lock(false); for(int i = 0; i < 1000; ++i) { if (lock.tryLock()) { lock.unlock(); } QThread::usleep(qrand() % 20); } } }; void TestForegroundLock::testTryLock_data() { QTest::addColumn("numThreads"); for (int i = 1; i <= 10; ++i) { QTest::newRow(qPrintable(QString::number(i))) << i; } } void TestForegroundLock::testTryLock() { QFETCH(int, numThreads); QList threads; for (int i = 0; i < numThreads; ++i) { threads << new TryLockThread; } ForegroundLock lock(true); foreach(TryLockThread* thread, threads) { thread->start(); } lock.unlock(); while(true) { bool running = false; foreach(TryLockThread* thread, threads) { if (thread->isRunning()) { running = true; break; } } if (!running) { break; } lock.relock(); QThread::usleep(10); lock.unlock(); } } #include "moc_test_foregroundlock.cpp" #include "test_foregroundlock.moc" diff --git a/util/tests/test_stringhandler.cpp b/util/tests/test_stringhandler.cpp index a7854c78a4..e7c791d6f5 100644 --- a/util/tests/test_stringhandler.cpp +++ b/util/tests/test_stringhandler.cpp @@ -1,56 +1,75 @@ /* * Copyright 2014 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 "test_stringhandler.h" #include "kdevstringhandler.h" #include QTEST_MAIN(TestStringHandler); using namespace KDevelop; Q_DECLARE_METATYPE(HtmlToPlainTextMode) void TestStringHandler::testHtmlToPlainText() { QFETCH(QString, html); QFETCH(HtmlToPlainTextMode, mode); QFETCH(QString, expectedPlainText); QString plainText = htmlToPlainText(html, mode); QCOMPARE(plainText, expectedPlainText); } void TestStringHandler::testHtmlToPlainText_data() { QTest::addColumn("html"); QTest::addColumn("mode"); QTest::addColumn("expectedPlainText"); QTest::newRow("simple-fast") << "

bar()

a
foo
" << KDevelop::FastMode << "bar() a foo"; QTest::newRow("simple-complete") << "

bar()

a
foo
" << KDevelop::CompleteMode << "bar() \na\nfoo"; } + +void TestStringHandler::testStripAnsiSequences() +{ + QFETCH(QString, input); + QFETCH(QString, expectedOutput); + + const auto output = stripAnsiSequences(input); + QCOMPARE(output, expectedOutput); +} + +void TestStringHandler::testStripAnsiSequences_data() +{ + QTest::addColumn("input"); + QTest::addColumn("expectedOutput"); + + QTest::newRow("simple") + << QStringLiteral("foo bar:") + << "foo bar:"; +} \ No newline at end of file diff --git a/util/tests/test_stringhandler.h b/util/tests/test_stringhandler.h index 5c1a07858b..4635fbf38a 100644 --- a/util/tests/test_stringhandler.h +++ b/util/tests/test_stringhandler.h @@ -1,37 +1,39 @@ /* * Copyright 2014 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 TESTSTRINGHANDLER_H #define TESTSTRINGHANDLER_H #include class TestStringHandler : public QObject { Q_OBJECT private Q_SLOTS: void testHtmlToPlainText(); void testHtmlToPlainText_data(); + void testStripAnsiSequences(); + void testStripAnsiSequences_data(); }; #endif // TESTSTRINGHANDLER_H diff --git a/vcs/dvcs/dvcsjob.h b/vcs/dvcs/dvcsjob.h index c909fbbf3d..32335136ae 100644 --- a/vcs/dvcs/dvcsjob.h +++ b/vcs/dvcs/dvcsjob.h @@ -1,230 +1,230 @@ /*************************************************************************** * This file was partly taken from KDevelop's cvs plugin * * Copyright 2002-2003 Christian Loose * * Copyright 2007 Robert Gruber * * * * Adapted for DVCS * * Copyright 2008 Evgeniy Ivanov * * Copyright 2010 Aleix Pol Gonzalez * * * * 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_DVCS_JOB_H #define KDEVPLATFORM_DVCS_JOB_H #include #include #include #include #include "../vcsjob.h" class QDir; struct DVcsJobPrivate; /** * This class is capable of running our dvcs commands. * Most of all DVcsJob are created in DVCS executors, but executed in DistributedVersionControlPlugin or * any managers like BranchManager. * @note Connect to KJob::result(KJob*) to be notified when the job finished. * * How to create DVcsJob: * @code * DVcsJob* job = new DVcsJob(vcsplugin); * * job->setDirectory(workDir); * *job << "git-rev-parse"; * foreach(const QString &arg, args) // *job << args can be used instead! * *job << arg; * return job; * * return error_cmd(i18n("could not create the job")); * @endcode * * Usage example 1: * @code * VcsJob* j = add(QList() << a << b << c, IBasicVersionControl::Recursive); * DVcsJob* job = qobject_cast(j); * connect(job, SIGNAL(result(KJob*) ), * this, SIGNAL(jobFinished(KJob*) )); * ICore::self()->runController()->registerJob(job); * @endcode * * Usage example 2, asyunchronous: * @code * DVcsJob* branchJob = d->branch(repo, baseBranch, newBranch); * * if (job->exec() && job->status() == KDevelop::VcsJob::JobSucceeded) * return true; * else * //something, maybe even just * return false * @endcode * * @author Robert Gruber * @author Evgeniy Ivanov */ namespace KDevelop { class KDEVPLATFORMVCS_EXPORT DVcsJob : public KDevelop::VcsJob { Q_OBJECT public: explicit DVcsJob(const QDir& workingDir, KDevelop::IPlugin* parent=0, KDevelop::OutputJob::OutputJobVerbosity verbosity = KDevelop::OutputJob::Verbose); - virtual ~DVcsJob(); + ~DVcsJob() override; /** * Returns current working directory. */ QDir directory() const; /** * Call this method to set command to execute and its arguments. * @note Don't forget <<"one two"; is not the same as <<"one"<<"two"; Use one word(command, arg) per one QString! */ DVcsJob& operator<<(const QString& arg); /** * Overloaded convenience function. * @see operator<<(const QString& arg). */ DVcsJob& operator<<(const char* arg); /** * Overloaded convenience function. * @see operator<<(const QString& arg). */ DVcsJob& operator<<(const QStringList& args); /** * Overloaded operator << for url's, can be used to pass files and * makes arguments absolute to the process working directory * * Override if you need to treat paths beffore adding them as parameters. */ virtual DVcsJob& operator<<(const QUrl& arg); /** * @see operator<<(const QUrl& arg). */ DVcsJob& operator<<(const QList& args); /** * Call this method to start this job. * @note Default communication mode is KProcess::AllOutput. * @see Use setCommunicationMode() to override the default communication mode. */ - virtual void start() override; + void start() override; /** * In some cases it's needed to specify the communication mode between the * process and the job object. This is for instance done for the "git status" * command. If stdout and stderr are processed as separate streams, their signals * do not always get emitted in correct order by KProcess, which will lead to a * screwed up output. * @note Default communication mode is KProcess::SeparateChannels. */ void setCommunicationMode(KProcess::OutputChannelMode comm); /** * @return The command that is executed when calling start(). */ QStringList dvcsCommand() const; /** * @return The whole output of the job as a string. (Might fail on binary data) */ QString output() const; /** * @return The whole binary output of the job */ QByteArray rawOutput() const; /** * @return The whole binary stderr output of the job. */ QByteArray errorOutput() const; /** * Ignore a non-zero exit code depending on @p ignore. */ void setIgnoreError(bool ignore); // Begin: KDevelop::VcsJob /** * Sets executions results. * In most cases this method is used by IDVCSexecutor * @see fetchResults() */ virtual void setResults(const QVariant &res); /** * Returns execution results stored in QVariant. * Mostly used in vcscommitdialog. * @see setResults(const QVariant &res) */ - virtual QVariant fetchResults() override; + QVariant fetchResults() override; /** * Returns JobStatus * @see KDevelop::VcsJob::JobStatus */ - virtual KDevelop::VcsJob::JobStatus status() const override; + KDevelop::VcsJob::JobStatus status() const override; /** * Returns pointer to IPlugin (which was used to create a job). */ - virtual KDevelop::IPlugin* vcsPlugin() const override; + KDevelop::IPlugin* vcsPlugin() const override; // End: KDevelop::VcsJob KProcess *process(); void displayOutput(const QString& output); public Q_SLOTS: /** * Cancel slot. */ void cancel(); Q_SIGNALS: void readyForParsing(KDevelop::DVcsJob *job); protected Q_SLOTS: virtual void slotProcessError( QProcess::ProcessError ); private Q_SLOTS: void slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus); void slotReceivedStdout(); protected: - virtual bool doKill() override; + bool doKill() override; private: void jobIsReady(); DVcsJobPrivate* const d; }; } #endif diff --git a/vcs/dvcs/dvcsplugin.h b/vcs/dvcs/dvcsplugin.h index f40a777f10..d2e2e56a9f 100644 --- a/vcs/dvcs/dvcsplugin.h +++ b/vcs/dvcs/dvcsplugin.h @@ -1,104 +1,104 @@ /*************************************************************************** * Copyright 2008 Evgeniy Ivanov * * * * 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_DVCS_PLUGIN_H #define KDEVPLATFORM_DVCS_PLUGIN_H #include #include #include #include #include "dvcsevent.h" #include #include #include class QMenu; namespace KDevelop { struct DistributedVersionControlPluginPrivate; class DVcsJob; /** * DistributedVersionControlPlugin is a base class for git/hg/bzr plugins. This class implements * KDevelop::IBasicVersionControl, KDevelop::IDistributedVersionControl and KDevelop::IPlugin (contextMenuExtension). * DistributedVersionControlPlugin class uses IDVCSexecutor to get all jobs * from real DVCS plugins like Git. It is based on KDevelop's CVS plugin (also looks like svn plugin is it's relative too). * @note Create only special items in contextMenuExtension, all standard menu items are created in vcscommon plugin! */ class KDEVPLATFORMVCS_EXPORT DistributedVersionControlPlugin : public IPlugin, public IDistributedVersionControl, public IBranchingVersionControl { Q_OBJECT Q_INTERFACES(KDevelop::IBasicVersionControl KDevelop::IDistributedVersionControl KDevelop::IBranchingVersionControl) public: DistributedVersionControlPlugin(QObject *parent, const QString& componentName); - virtual ~DistributedVersionControlPlugin(); + ~DistributedVersionControlPlugin() override; // Begin: KDevelop::IBasicVersionControl /** Used in KDevelop's appwizardplugin (creates import widget) */ - virtual VcsImportMetadataWidget* createImportMetadataWidget(QWidget* parent) override; + VcsImportMetadataWidget* createImportMetadataWidget(QWidget* parent) override; // From KDevelop::IPlugin /** Creates context menu * @note Create only special items here (like checkout), all standard menu items are created in vcscommon plugin! */ - virtual ContextMenuExtension contextMenuExtension(Context*) override; + ContextMenuExtension contextMenuExtension(Context*) override; /** * Parses the output generated by a @code dvcs log @endcode command and * fills the given QList with all commits infos found in the given output. * @param job The finished job of a @code dvcs log @endcode call * @param revisions Will be filled with all revision infos found in @p jobOutput * TODO: Change it to pass the results in @code job->getResults() @endcode */ virtual void parseLogOutput(const DVcsJob * job, QList& revisions) const = 0; /** Returns the list of all commits (in all branches). * @see CommitView and CommitViewDelegate to see how this list is used. */ virtual QList getAllCommits(const QString &repo) = 0; /** * When a plugin wants to add elements to the vcs menu, this method can be * overridden. */ virtual void additionalMenuEntries(QMenu* menu, const QList& urls); public Q_SLOTS: //slots for context menu void ctxBranchManager(); void ctxRevHistory(); protected: /** Checks if dirPath is located in DVCS repository */ virtual bool isValidDirectory(const QUrl &dirPath) = 0; private: DistributedVersionControlPluginPrivate * const d; }; } #endif diff --git a/vcs/dvcs/ui/branchmanager.h b/vcs/dvcs/ui/branchmanager.h index 532e023146..c5670d8975 100644 --- a/vcs/dvcs/ui/branchmanager.h +++ b/vcs/dvcs/ui/branchmanager.h @@ -1,60 +1,60 @@ /*************************************************************************** * Copyright 2008 Evgeniy Ivanov * * * * 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_BRANCH_MANAGER_H #define KDEVPLATFORM_BRANCH_MANAGER_H #include class KJob; namespace Ui { class BranchDialogBase; } namespace KDevelop { class BranchesListModel; class DistributedVersionControlPlugin; } class BranchManager : public QDialog { Q_OBJECT public: BranchManager(const QString& repository, KDevelop::DistributedVersionControlPlugin* executor, QWidget *parent = 0); - ~BranchManager(); + ~BranchManager() override; signals: void checkedOut(KJob*); private slots: void createBranch(); void deleteBranch(); void renameBranch(); void checkoutBranch(); private: QString m_repository; KDevelop::DistributedVersionControlPlugin* m_dvcPlugin; Ui::BranchDialogBase* m_ui; KDevelop::BranchesListModel* m_model; }; #endif diff --git a/vcs/dvcs/ui/dvcsimportmetadatawidget.h b/vcs/dvcs/ui/dvcsimportmetadatawidget.h index 0ea2d70c86..52a32c802f 100644 --- a/vcs/dvcs/ui/dvcsimportmetadatawidget.h +++ b/vcs/dvcs/ui/dvcsimportmetadatawidget.h @@ -1,64 +1,64 @@ /*************************************************************************** * Copyright 2007 Robert Gruber * * Copyright 2007 Andreas Pakulat * * * * Adapted for Git * * Copyright 2008 Evgeniy Ivanov * * * * Pimpl-ed and exported * * Copyright 2014 Maciej Poleski * * * * 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_DVCSIMPORTMETADATAWIDGET_H #define KDEVPLATFORM_DVCSIMPORTMETADATAWIDGET_H #include namespace Ui { class DvcsImportMetadataWidget; } class DvcsImportMetadataWidgetPrivate; /** * Asks the user for all options needed to import an existing directory into * a Git repository * @author Robert Gruber */ class KDEVPLATFORMVCS_EXPORT DvcsImportMetadataWidget : public KDevelop::VcsImportMetadataWidget { Q_OBJECT Q_DECLARE_PRIVATE(DvcsImportMetadataWidget) public: explicit DvcsImportMetadataWidget(QWidget* parent=0); - virtual ~DvcsImportMetadataWidget(); + ~DvcsImportMetadataWidget() override; - virtual QUrl source() const override; - virtual KDevelop::VcsLocation destination() const override; - virtual QString message() const override; //Is not used, it returns an empty string - virtual void setSourceLocation( const KDevelop::VcsLocation& ) override; - virtual void setSourceLocationEditable( bool ) override; - virtual bool hasValidData() const override; + QUrl source() const override; + KDevelop::VcsLocation destination() const override; + QString message() const override; //Is not used, it returns an empty string + void setSourceLocation( const KDevelop::VcsLocation& ) override; + void setSourceLocationEditable( bool ) override; + bool hasValidData() const override; private: DvcsImportMetadataWidgetPrivate *const d_ptr; }; #endif diff --git a/vcs/dvcs/ui/revhistory/commitView.h b/vcs/dvcs/ui/revhistory/commitView.h index 52a5e4b334..c962733ddc 100644 --- a/vcs/dvcs/ui/revhistory/commitView.h +++ b/vcs/dvcs/ui/revhistory/commitView.h @@ -1,62 +1,62 @@ /*************************************************************************** * Copyright 2008 Evgeniy Ivanov * * * * 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_COMMIT_VIEW_H #define KDEVPLATFORM_COMMIT_VIEW_H #include #include enum ViewColumns { GRAPH_COLUMN = 0, SLOG_COLUMN = 1, AUTHOR_COLUMN = 2, DATE_COLUMN = 3 }; class CommitView : public QTreeView { Q_OBJECT public: explicit CommitView(QWidget *parent = 0); - ~CommitView() {}; + ~CommitView() override {}; // void setLineHeight(int h) { lineHeight = h; } int getLineHeight(const QModelIndex & index) {return rowHeight(index);} private: // int lineHeight; }; class CommitViewDelegate : public QItemDelegate { Q_OBJECT public: CommitViewDelegate(CommitView* _view, QObject* parent); void paint(QPainter* p, const QStyleOptionViewItem& o, const QModelIndex &i) const override; private: void paintGraph(QPainter* p, const QStyleOptionViewItem& o, const QModelIndex &i) const; void paintGraphLane(QPainter* p, int type, int x1, int x2, const int height, const QColor& col, const QBrush& back) const; private: CommitView* view; }; #endif diff --git a/vcs/dvcs/ui/revhistory/commitlogmodel.h b/vcs/dvcs/ui/revhistory/commitlogmodel.h index e6a915ef49..5d0ef84b8a 100644 --- a/vcs/dvcs/ui/revhistory/commitlogmodel.h +++ b/vcs/dvcs/ui/revhistory/commitlogmodel.h @@ -1,67 +1,67 @@ /*************************************************************************** * Copyright 2008 Evgeniy Ivanov * * * * 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_COMMITLOGMODEL_H #define KDEVPLATFORM_COMMITLOGMODEL_H #include #include #include #include namespace KDevelop { class DistributedVersionControlPlugin; } class QStringList; class CommitLogModel : public QAbstractItemModel { Q_OBJECT public: CommitLogModel(KDevelop::DistributedVersionControlPlugin* plugin, const QString& repo, QObject* parent = 0); - ~CommitLogModel() {}; + ~CommitLogModel() override {}; QVariant data(const QModelIndex &index, int role) const override; Qt::ItemFlags flags(const QModelIndex& index) const override; QVariant headerData(int s, Qt::Orientation o, int role = Qt::DisplayRole) const override; QModelIndex index(int r, int c, const QModelIndex& par = QModelIndex()) const override; QModelIndex parent(const QModelIndex& index) const override; int rowCount(const QModelIndex& par = QModelIndex()) const override; int columnCount(const QModelIndex&) const override; int branchCount(const int) const {return branchCnt;} QList getProperties(const int i) const {return revs[i].getProperties();} private slots: void initializeModel(); private: QStringList headerInfo; QList revs; int branchCnt; QString m_repo; KDevelop::DistributedVersionControlPlugin* m_plugin; }; #endif diff --git a/vcs/interfaces/icontentawareversioncontrol.h b/vcs/interfaces/icontentawareversioncontrol.h index 4b6d71b168..57b92498ba 100644 --- a/vcs/interfaces/icontentawareversioncontrol.h +++ b/vcs/interfaces/icontentawareversioncontrol.h @@ -1,80 +1,80 @@ /* This file is part of KDevelop * * Copyright 2013 Sven Brauch * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef KDEVPLATFORM_ICONTENTAWAREVERSIONCONTROL_H #define KDEVPLATFORM_ICONTENTAWAREVERSIONCONTROL_H #include #include #include namespace KTextEditor { class Document; } namespace KDevelop { class KDEVPLATFORMVCS_EXPORT CheckInRepositoryJob : public KJob { Q_OBJECT public: explicit CheckInRepositoryJob(KTextEditor::Document* document); - virtual ~CheckInRepositoryJob(); + ~CheckInRepositoryJob() override; KTextEditor::Document* document() const; public slots: /// Abort this request. void abort(); signals: void finished(bool canRecreate); protected: struct CheckInRepositoryJobPrivate* d; }; /** * This interface is used by version control systems which can tell whether a given * blob of data is stored in the repository or not, such as git. * This information is used to reload files automatically if that involves no data loss. */ class IContentAwareVersionControl { public: virtual ~IContentAwareVersionControl() {}; /** * @brief Determines whether the given data is stored in the VCS' repository. * * @param document Document to search for in the repository * @returns CheckInRepositoryJob request object to track get notified when this finishes. * The request object deletes itself after finished() was emitted. */ virtual CheckInRepositoryJob* isInRepository(KTextEditor::Document* document) = 0; }; } Q_DECLARE_INTERFACE( KDevelop::IContentAwareVersionControl, "org.kdevelop.IContentAwareVersionControl" ) #endif diff --git a/vcs/models/brancheslistmodel.h b/vcs/models/brancheslistmodel.h index 1026bd1f41..20a650fd08 100644 --- a/vcs/models/brancheslistmodel.h +++ b/vcs/models/brancheslistmodel.h @@ -1,74 +1,74 @@ /*************************************************************************** * Copyright 2008 Evgeniy Ivanov * * Copyright 2012 Aleix Pol Gonzalez * * * * 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_BRANCHESLISTMODEL_H #define KDEVPLATFORM_BRANCHESLISTMODEL_H #include #include #include namespace KDevelop { class IBranchingVersionControl; class IProject; class BranchesListModelPrivate; class KDEVPLATFORMVCS_EXPORT BranchesListModel : public QStandardItemModel { Q_OBJECT Q_PROPERTY(KDevelop::IProject* project READ project WRITE setProject) Q_PROPERTY(QString currentBranch READ currentBranch WRITE setCurrentBranch NOTIFY currentBranchChanged) public: enum Roles { CurrentRole = Qt::UserRole+1 }; explicit BranchesListModel(QObject* parent = 0); - ~BranchesListModel(); + ~BranchesListModel() override; void initialize(KDevelop::IBranchingVersionControl* dvcsplugin, const QUrl& repo); - virtual QHash roleNames() const override; + QHash roleNames() const override; Q_INVOKABLE void createBranch(const QString& baseBranch, const QString& newBranch); Q_INVOKABLE void removeBranch(const QString& branch); QUrl repository() const; KDevelop::IBranchingVersionControl* interface(); void refresh(); QString currentBranch() const; void setCurrentBranch(const QString& branch); KDevelop::IProject* project() const; void setProject(KDevelop::IProject* p); public slots: void resetCurrent(); signals: void currentBranchChanged(); private: const QScopedPointer d; }; } #endif // KDEVPLATFORM_BRANCHESLISTMODEL_H diff --git a/vcs/models/vcsannotationmodel.h b/vcs/models/vcsannotationmodel.h index 7afaca3cf0..16252335f3 100644 --- a/vcs/models/vcsannotationmodel.h +++ b/vcs/models/vcsannotationmodel.h @@ -1,64 +1,64 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2007 Andreas Pakulat * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_VCSANNOTATIONMODEL_H #define KDEVPLATFORM_VCSANNOTATIONMODEL_H #include #include #include "../vcsrevision.h" #include #include class QModelIndex; template class QList; namespace KDevelop { class VcsAnnotation; class VcsAnnotationLine; class VcsJob; class KDEVPLATFORMVCS_EXPORT VcsAnnotationModel : public KTextEditor::AnnotationModel { Q_OBJECT public: VcsAnnotationModel( VcsJob* job, const QUrl&, QObject*, const QColor& foreground = QColor(Qt::black), const QColor& background = QColor(Qt::white) ); - virtual ~VcsAnnotationModel(); + ~VcsAnnotationModel() override; VcsRevision revisionForLine(int line) const; QVariant data( int line, Qt::ItemDataRole role = Qt::DisplayRole ) const override; private: Q_PRIVATE_SLOT( d, void addLines( KDevelop::VcsJob*) ) class VcsAnnotationModelPrivate* const d; friend class VcsAnnotationModelPrivate; QColor foreground; QColor background; }; } #endif diff --git a/vcs/models/vcseventmodel.h b/vcs/models/vcseventmodel.h index e97f63446c..035eb08cb4 100644 --- a/vcs/models/vcseventmodel.h +++ b/vcs/models/vcseventmodel.h @@ -1,70 +1,70 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2007 Andreas Pakulat * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_VCSEVENTMODEL_H #define KDEVPLATFORM_VCSEVENTMODEL_H #include #include class QUrl; class KJob; namespace KDevelop { class VcsRevision; class IBasicVersionControl; class VcsEvent; class KDEVPLATFORMVCS_EXPORT VcsEventModel : public QAbstractTableModel { Q_OBJECT public: enum Column { RevisionColumn, SummaryColumn, AuthorColumn, DateColumn, ColumnCount, }; VcsEventModel( KDevelop::IBasicVersionControl* iface, const KDevelop::VcsRevision& rev, const QUrl& url, QObject* parent ); - ~VcsEventModel(); + ~VcsEventModel() override; int rowCount( const QModelIndex& = QModelIndex() ) const override; int columnCount( const QModelIndex& parent = QModelIndex() ) const override; QVariant data( const QModelIndex&, int role = Qt::DisplayRole ) const override; QVariant headerData( int, Qt::Orientation, int role = Qt::DisplayRole ) const override; KDevelop::VcsEvent eventForIndex( const QModelIndex& ) const; - virtual void fetchMore(const QModelIndex& parent) override; - virtual bool canFetchMore(const QModelIndex& parent) const override; + void fetchMore(const QModelIndex& parent) override; + bool canFetchMore(const QModelIndex& parent) const override; private slots: void jobReceivedResults( KJob* job ); private: void addEvents( const QList& ); class VcsEventModelPrivate* const d; }; } #endif diff --git a/vcs/models/vcsitemeventmodel.h b/vcs/models/vcsitemeventmodel.h index 9b860e71ff..e4ac69b748 100644 --- a/vcs/models/vcsitemeventmodel.h +++ b/vcs/models/vcsitemeventmodel.h @@ -1,48 +1,48 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2007 Andreas Pakulat * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_VCSITEMEVENTMODEL_H #define KDEVPLATFORM_VCSITEMEVENTMODEL_H #include #include template class QList; namespace KDevelop { class VcsItemEvent; class KDEVPLATFORMVCS_EXPORT VcsItemEventModel : public QStandardItemModel { Q_OBJECT public: explicit VcsItemEventModel( QObject* parent ); - ~VcsItemEventModel(); + ~VcsItemEventModel() override; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; void addItemEvents( const QList& ); KDevelop::VcsItemEvent itemEventForIndex( const QModelIndex& ) const; }; } #endif diff --git a/vcs/vcspluginhelper.h b/vcs/vcspluginhelper.h index 3807d66c46..14b9ce05d3 100644 --- a/vcs/vcspluginhelper.h +++ b/vcs/vcspluginhelper.h @@ -1,87 +1,87 @@ /*************************************************************************** * Copyright 2008 Andreas Pakulat * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_VCSPLUGINHELPER_H #define KDEVPLATFORM_VCSPLUGINHELPER_H #include "vcsexport.h" #include #include "vcsrevision.h" class KJob; class QAction; class QActionGroup; class QMenu; namespace KTextEditor { class View; class Document; } using KTextEditor::View; namespace KDevelop { class VcsDiff; class IPlugin; class IBasicVersionControl; class Context; class ContextMenuExtension; class VcsCommitDialog; class ProjectBaseItem; class KDEVPLATFORMVCS_EXPORT VcsPluginHelper : public QObject { Q_OBJECT public: VcsPluginHelper(IPlugin * parent, IBasicVersionControl * vcs); - virtual ~VcsPluginHelper(); + ~VcsPluginHelper() override; void setupFromContext(KDevelop::Context*); void addContextDocument(const QUrl& url); QList contextUrlList() const; QMenu* commonActions(); public Q_SLOTS: void commit(); void add(); void revert(); void history(const VcsRevision& rev = VcsRevision::createSpecialRevision( VcsRevision::Base )); void annotation(); void annotationContextMenuAboutToShow( KTextEditor::View* view, QMenu* menu, int line); void diffToBase(); void diffForRev(); void diffForRevGlobal(); void update(); void pull(); void push(); void diffJobFinished(KJob* job); void revertDone(KJob* job); void disposeEventually(KTextEditor::Document*); void disposeEventually(View*, bool); private Q_SLOTS: void delayedModificationWarningOn(); private: void diffForRev(const QUrl& url); struct VcsPluginHelperPrivate; QScopedPointer d; }; } // namespace KDevelop #endif diff --git a/vcs/widgets/standardvcslocationwidget.h b/vcs/widgets/standardvcslocationwidget.h index 55fd271ffb..6925f12505 100644 --- a/vcs/widgets/standardvcslocationwidget.h +++ b/vcs/widgets/standardvcslocationwidget.h @@ -1,50 +1,50 @@ /* KDevPlatform Vcs Support * * Copyright 2010 Aleix Pol * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef KDEVPLATFORM_STANDARDVCSLOCATIONWIDGET_H #define KDEVPLATFORM_STANDARDVCSLOCATIONWIDGET_H #include #include class QUrl; class KUrlRequester; namespace KDevelop { class KDEVPLATFORMVCS_EXPORT StandardVcsLocationWidget : public VcsLocationWidget { Q_OBJECT public: explicit StandardVcsLocationWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); - virtual VcsLocation location() const override; - virtual bool isCorrect() const override; + VcsLocation location() const override; + bool isCorrect() const override; QUrl url() const; - virtual QString projectName() const override; + QString projectName() const override; public slots: void textChanged(const QString& str); private: KUrlRequester* m_urlWidget; }; } #endif // KDEVPLATFORM_STANDARDVCSLOCATIONWIDGET_H diff --git a/vcs/widgets/vcscommitdialog.h b/vcs/widgets/vcscommitdialog.h index 3920594d47..68811666c6 100644 --- a/vcs/widgets/vcscommitdialog.h +++ b/vcs/widgets/vcscommitdialog.h @@ -1,46 +1,46 @@ /*************************************************************************** * Copyright 2007 Dukju Ahn * * Copyright 2011 Andrey Batyiev * * * * 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. * * * ***************************************************************************/ #ifndef KDEVPLATFORM_VCS_COMMITDIALOG_H #define KDEVPLATFORM_VCS_COMMITDIALOG_H #include #include namespace KDevelop { class VcsStatusInfo; class IPatchSource; class KDEVPLATFORMVCS_EXPORT VcsCommitDialog : public QDialog { Q_OBJECT public: explicit VcsCommitDialog( IPatchSource *patchSource, QWidget *parent = 0 ); - virtual ~VcsCommitDialog(); + ~VcsCommitDialog() override; ///Sets the commit candidates void setCommitCandidates( const QList& statuses ); void setRecursive( bool ); bool recursive() const; private slots: void ok(); void cancel(); private: class VcsCommitDialogPrivate* const d; }; } #endif diff --git a/vcs/widgets/vcsdiffpatchsources.h b/vcs/widgets/vcsdiffpatchsources.h index 2da5529274..8668480479 100644 --- a/vcs/widgets/vcsdiffpatchsources.h +++ b/vcs/widgets/vcsdiffpatchsources.h @@ -1,133 +1,133 @@ /* Copyright 2009 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. */ /** * This is an internal header */ #ifndef KDEVPLATFORM_VCSDIFFPATCHSOURCES_H #define KDEVPLATFORM_VCSDIFFPATCHSOURCES_H #include #include "vcs/vcsstatusinfo.h" #include "vcs/vcsjob.h" #include class KTextEdit; class KComboBox; namespace KDevelop { class VcsCommitDialog; class IBasicVersionControl; class VcsDiff; } class QWidget; class VCSDiffUpdater { public: virtual ~VCSDiffUpdater(); virtual KDevelop::VcsDiff update() const = 0; virtual KDevelop::IBasicVersionControl* vcs() const = 0; virtual QUrl url() const = 0; }; class KDEVPLATFORMVCS_EXPORT VCSStandardDiffUpdater : public VCSDiffUpdater { public: VCSStandardDiffUpdater(KDevelop::IBasicVersionControl* vcs, QUrl url); - virtual ~VCSStandardDiffUpdater(); - virtual KDevelop::VcsDiff update() const override; - virtual KDevelop::IBasicVersionControl* vcs() const override { return m_vcs; } - virtual QUrl url() const override { return m_url; } + ~VCSStandardDiffUpdater() override; + KDevelop::VcsDiff update() const override; + KDevelop::IBasicVersionControl* vcs() const override { return m_vcs; } + QUrl url() const override { return m_url; } private: KDevelop::IBasicVersionControl* m_vcs; QUrl m_url; }; class KDEVPLATFORMVCS_EXPORT VCSDiffPatchSource : public KDevelop::IPatchSource { public: /// The ownership of the updater is taken explicit VCSDiffPatchSource(VCSDiffUpdater* updater); explicit VCSDiffPatchSource(const KDevelop::VcsDiff& diff); - virtual ~VCSDiffPatchSource(); + ~VCSDiffPatchSource() override; - virtual QUrl baseDir() const override ; + QUrl baseDir() const override ; - virtual QUrl file() const override ; + QUrl file() const override ; - virtual QString name() const override ; + QString name() const override ; - virtual uint depth() const override ; + uint depth() const override ; - virtual void update() override ; + void update() override ; - virtual bool isAlreadyApplied() const override { return true; } + bool isAlreadyApplied() const override { return true; } QMap additionalSelectableFiles() const override ; QUrl m_base, m_file; QString m_name; VCSDiffUpdater* m_updater; QList m_infos; QMap m_selectable; private: void updateFromDiff(KDevelop::VcsDiff diff); uint m_depth = 0; }; class KDEVPLATFORMVCS_EXPORT VCSCommitDiffPatchSource : public VCSDiffPatchSource { Q_OBJECT public: /// The ownership of the updater is taken explicit VCSCommitDiffPatchSource(VCSDiffUpdater* updater); - ~VCSCommitDiffPatchSource() ; + ~VCSCommitDiffPatchSource() override ; QStringList oldMessages() const; - virtual bool canSelectFiles() const override ; + bool canSelectFiles() const override ; - virtual QWidget* customWidget() const override ; + QWidget* customWidget() const override ; - virtual QString finishReviewCustomText() const override ; + QString finishReviewCustomText() const override ; - virtual bool canCancel() const override; + bool canCancel() const override; - virtual void cancelReview() override; + void cancelReview() override; - virtual bool finishReview(QList< QUrl > selection) override ; + bool finishReview(QList< QUrl > selection) override ; QList infos() const { return m_infos; } Q_SIGNALS: void reviewFinished(QString message, QList selection); void reviewCancelled(QString message); public: QPointer m_commitMessageWidget; QPointer m_commitMessageEdit; KDevelop::IBasicVersionControl* m_vcs; KComboBox* m_oldMessages; public slots: void addMessageToHistory(const QString& message); void oldMessageChanged(QString); void jobFinished(KJob*); }; ///Sends the diff to the patch-review plugin. ///Returns whether the diff was shown successfully. bool KDEVPLATFORMVCS_EXPORT showVcsDiff(KDevelop::IPatchSource* vcsDiff); #endif // KDEVPLATFORM_VCSDIFFPATCHSOURCES_H diff --git a/vcs/widgets/vcsdiffwidget.h b/vcs/widgets/vcsdiffwidget.h index 66f99bcdf1..38a32de2e2 100644 --- a/vcs/widgets/vcsdiffwidget.h +++ b/vcs/widgets/vcsdiffwidget.h @@ -1,47 +1,47 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2007 Andreas Pakulat * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_VCSDIFFWIDGET_H #define KDEVPLATFORM_VCSDIFFWIDGET_H #include #include namespace KDevelop { class VcsJob; class VcsRevision; class KDEVPLATFORMVCS_EXPORT VcsDiffWidget : public QWidget { Q_OBJECT public: explicit VcsDiffWidget( KDevelop::VcsJob*, QWidget* parent = 0 ); - ~VcsDiffWidget(); + ~VcsDiffWidget() override; void setRevisions( const KDevelop::VcsRevision&, const KDevelop::VcsRevision& ); private: Q_PRIVATE_SLOT(d, void diffReady( KDevelop::VcsJob* ) ) class VcsDiffWidgetPrivate* const d; }; } #endif diff --git a/vcs/widgets/vcseventwidget.h b/vcs/widgets/vcseventwidget.h index d9bb3cf703..c2b7d33735 100644 --- a/vcs/widgets/vcseventwidget.h +++ b/vcs/widgets/vcseventwidget.h @@ -1,56 +1,56 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2007 Dukju Ahn * * Copyright 2007 Andreas Pakulat * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_VCSEVENTWIDGET_H #define KDEVPLATFORM_VCSEVENTWIDGET_H #include #include class QPoint; class QModelIndex; class QUrl; namespace KDevelop { class VcsRevision; class IBasicVersionControl; class KDEVPLATFORMVCS_EXPORT VcsEventWidget : public QWidget { Q_OBJECT public: VcsEventWidget( const QUrl& url, const VcsRevision& rev, KDevelop::IBasicVersionControl* iface, QWidget* parent = 0 ); - virtual ~VcsEventWidget(); + ~VcsEventWidget() override; private: Q_PRIVATE_SLOT(d, void diffToPrevious()) Q_PRIVATE_SLOT(d, void diffRevisions()) Q_PRIVATE_SLOT(d, void eventViewCustomContextMenuRequested( const QPoint &point )) Q_PRIVATE_SLOT(d, void eventViewClicked( const QModelIndex &index )) Q_PRIVATE_SLOT(d, void currentRowChanged(const QModelIndex&, const QModelIndex& )) Q_PRIVATE_SLOT(d, void copyRevision()) class VcsEventWidgetPrivate* const d; }; } #endif diff --git a/vcs/widgets/vcsimportmetadatawidget.h b/vcs/widgets/vcsimportmetadatawidget.h index 7336d43ccf..4925469c18 100644 --- a/vcs/widgets/vcsimportmetadatawidget.h +++ b/vcs/widgets/vcsimportmetadatawidget.h @@ -1,67 +1,67 @@ /*************************************************************************** * This file is part of KDevelop * * Copyright 2007 Andreas Pakulat * * * * 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 Library 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. * ***************************************************************************/ #ifndef KDEVPLATFORM_VCSIMPORTMETADATAWIDGET_H #define KDEVPLATFORM_VCSIMPORTMETADATAWIDGET_H #include #include #include class QUrl; namespace KDevelop { class VcsLocation; class KDEVPLATFORMVCS_EXPORT VcsImportMetadataWidget : public QWidget { Q_OBJECT public: explicit VcsImportMetadataWidget( QWidget* parent ); - virtual ~VcsImportMetadataWidget(); + ~VcsImportMetadataWidget() override; virtual QUrl source() const = 0; virtual VcsLocation destination() const = 0; virtual QString message() const = 0; /** * Check whether the given data is valid. * @returns true if all data in the widget is valid */ virtual bool hasValidData() const = 0; /** * Select whether the widget should re-use the last part of the source location * for the destination. The default implementation simply ignores this setting. */ virtual void setUseSourceDirForDestination( bool ) {} Q_SIGNALS: void changed(); public Q_SLOTS: virtual void setSourceLocation( const VcsLocation& ) = 0; virtual void setSourceLocationEditable( bool ) = 0; }; } #endif //kate: space-indent on; indent-width 4; replace-tabs on; auto-insert-doxygen on; indent-mode cstyle;