!72 更加开放的插件v2

Merge pull request !72 from matheuter/cmake-plugins-dev
This commit is contained in:
爬山虎 2023-04-27 08:00:00 +00:00 committed by Gitee
commit 8b89fa423e
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
19 changed files with 1998 additions and 12 deletions

113
src/actor.h Normal file
View File

@ -0,0 +1,113 @@
#ifndef _ACTOR_H_
#define _ACTOR_H_
#include <cstdint>
#include <string>
#include <memory>
#include <tuple>
#include <functional>
#include "functiontraits.h"
class Actor : public std::enable_shared_from_this<Actor>
{
public:
using Ptr = std::shared_ptr<Actor>;
using FunctionWapper = std::function<void(void*, void*)>;
public:
Actor(){}
~Actor(){}
template<typename Function>
void operator+=(Function&& function_any) noexcept
{
m_invokeFunctionWapper = { std::bind(&invoker<Function>::apply, function_any, std::placeholders::_1, std::placeholders::_2) };
}
template<typename Function>
void registerFunction(Function&& function_any) noexcept
{
m_invokeFunctionWapper = { std::bind(&invoker<Function>::apply, function_any, std::placeholders::_1, std::placeholders::_2) };
}
template<typename ... Args>
void invoke(Args&& ... args) const noexcept
{
auto args_tuple = std::make_tuple(std::forward<Args>(args)...);
m_invokeFunctionWapper(&args_tuple, nullptr);
}
template<typename R, typename ... Args>
R invoke(Args&& ...args) const
{
using tuple_args_type = std::tuple<Args...>;
char data[sizeof(tuple_args_type)];
std::tuple<Args...>* tuples_pointer = new (data) tuple_args_type;
*tuples_pointer = std::make_tuple(std::forward<Args>(args)...);
R return_value;
m_invokeFunctionWapper(tuples_pointer, &return_value);
return return_value;
}
public:
/**
* @brief This struct encapsulates a function,
* essentially storing the return value and parameters in two variables
* which can unify the way the function is stored.
*/
template<typename Function>
struct invoker
{
/**
* @brief
*/
static inline void apply(const Function& func, void* bl, void* result)
{
using tuple_type = typename function_traits<Function>::tuple_type;
const tuple_type* tp = static_cast<tuple_type*>(bl);
call(func, *tp, result);
}
/**
* @brief
*/
template<typename F, typename ... Args>
static typename std::enable_if<std::is_void<typename std::result_of<F(Args...)>::type>::value>::type
call(const F& f, const std::tuple<Args...>& tp, void*)
{
call_helper(f, std::make_index_sequence<sizeof... (Args)>{}, tp);
}
/**
* @brief
*/
template<typename F, typename ... Args>
static typename std::enable_if<!std::is_void<typename std::result_of<F(Args...)>::type>::value>::type
call(const F& f, const std::tuple<Args...>& tp, void* result)
{
auto r = call_helper(f, std::make_index_sequence<sizeof... (Args)>{}, tp);
*(decltype(r)*)result = r;
}
/**
* @brief
*/
template<typename F, size_t... I, typename ... Args>
static auto call_helper(const F& f, const std::index_sequence<I...>& h, const std::tuple<Args...>& tup)
{
return f(std::get<I>(tup)...);
}
};
private:
/**
* @note m_invokeFunctions is an anonymous lamba expression that encapsulates a function
* Functions include Lamba expressions, member functions, funtor, ordinary functions, and function Pointers
*/
FunctionWapper m_invokeFunctionWapper;
};
#endif

54
src/actorprocessor.cpp Normal file
View File

@ -0,0 +1,54 @@
#include "actorprocessor.h"
ActorProcessor::ActorProcessor():
m_actorMap(new std::unordered_map<std::string, Actor*>)
{}
ActorProcessor::~ActorProcessor()
{
for (auto& item : (*m_actorMap))
{
if(item.second != nullptr)
delete item.second;
}
if (m_actorMap)
delete m_actorMap;
}
void ActorProcessor::registerActor(const std::string &route, Actor *actor)
{
m_actorMap->insert(std::make_pair(route,actor));
}
void ActorProcessor::removeActor(const std::string &route)
{
auto iter = (*m_actorMap).find(route);
if(iter != m_actorMap->end())
{
m_actorMap->erase(route);
delete iter->second;
}
}
Actor *ActorProcessor::findActor(const std::string &route)
{
auto iter = (*m_actorMap).find(route);
if(iter != m_actorMap->end())
{
return (*m_actorMap)[route];
}
return nullptr;
}
bool ActorProcessor::resetActor(const std::string &route, Actor *actor)
{
auto iter = (*m_actorMap).find(route);
if(iter != m_actorMap->end())
{
m_actorMap->erase(route);
delete iter->second;
return true;
}
return false;
}

50
src/actorprocessor.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef _PROCESSOR_H
#define _PROCESSOR_H
#include <string>
#include <functional>
#include <map>
#include <iostream>
#include <unordered_map>
#include "actor.h"
class ActorProcessor
{
public:
ActorProcessor();
~ActorProcessor();
public:
/**
* @brief Register the callback function and construct the anonymous function with std::bind
*/
template<typename ... Args>
void invoke(const std::string& route,Args&& ... args) const noexcept
{
if (m_actorMap->find(route) != m_actorMap->end())
(*m_actorMap)[route]->invoke(std::forward<Args>(args)...);
}
template<typename R, typename ... Args>
R invoke(const std::string& route,Args&& ...args) const
{
if (m_actorMap->find(route) != m_actorMap->end())
return (*m_actorMap)[route]->invoke(std::forward<Args>(args)...);
return nullptr;
}
void registerActor(const std::string& route, Actor*actor);
void removeActor(const std::string& route);
Actor* findActor(const std::string& route);
bool resetActor(const std::string& route,Actor*actor);
private:
std::unordered_map<std::string, Actor*>* m_actorMap;
private:
ActorProcessor(ActorProcessor&&)=delete;
ActorProcessor& operator=(const ActorProcessor&)=delete;
};
#endif // EVENTPROCESSOR_H

View File

@ -32,6 +32,8 @@
#include "pluginmgr.h"
#include "plugin.h"
#include "pluginGl.h"
#include "actor.h"
#include "actorprocessor.h"
#endif
#ifdef Q_OS_WIN
@ -1211,6 +1213,10 @@ CCNotePad::CCNotePad(bool isMainWindows, QWidget *parent)
restoreGeometry(lastGeo);
}
#endif
#ifdef NO_PLUGIN
processor = new ActorProcessor();
#endif
}
CCNotePad::~CCNotePad()
@ -1751,6 +1757,7 @@ void CCNotePad::onPlugFound(NDD_PROC_DATA& procData, QMenu* pUserData)
pAction->setText(procData.m_strPlugName);
pAction->setData(procData.m_strFilePath);
connect(pAction, &QAction::triggered, this, &CCNotePad::onPlugWork);
connect(pAction, &QAction::triggered, this, &CCNotePad::onPlugWorkV2);
}
else if (procData.m_menuType == 1)
{
@ -1761,6 +1768,7 @@ void CCNotePad::onPlugFound(NDD_PROC_DATA& procData, QMenu* pUserData)
//菜单句柄通过procData传递到插件中
procData.m_rootMenu = pluginMenu;
sendParaToPlugin(procData);
sendParaToPluginV2(procData);
}
else
{
@ -1796,6 +1804,39 @@ void CCNotePad::onPlugWork(bool check)
}
}
//真正执行插件的工作
void CCNotePad::onPlugWorkV2(bool check)
{
qDebug() << "test1";
QAction* pAct = dynamic_cast<QAction*>(sender());
if (pAct != nullptr)
{
QString plugPath = pAct->data().toString();
QLibrary* pLib = new QLibrary(plugPath);
NDD_PROC_MAIN_V2_CALLBACK pMainCallBack;
pMainCallBack = (NDD_PROC_MAIN_V2_CALLBACK)pLib->resolve("NDD_PROC_MAIN_V2");
if (pMainCallBack != NULL)
{
std::function<QsciScintilla* ()> foundCallBack = std::bind(&CCNotePad::getCurEditView, this);
Actor* actor = new Actor;
actor->registerFunction([this](QString name, int num){openFile(name,num);});
processor->registerActor("openFile",actor);
pMainCallBack(this, plugPath, processor, nullptr);
}
else
{
ui.statusBar->showMessage(tr("plugin %1 load failed !").arg(plugPath), 10000);
}
}
}
//把插件需要的参数,传递到插件中去
void CCNotePad::sendParaToPlugin(NDD_PROC_DATA& procData)
{
@ -1818,6 +1859,32 @@ void CCNotePad::sendParaToPlugin(NDD_PROC_DATA& procData)
}
}
void CCNotePad::sendParaToPluginV2(NDD_PROC_DATA& procData)
{
qDebug() <<"test5";
QString plugPath = procData.m_strFilePath;
QLibrary* pLib = new QLibrary(plugPath);
NDD_PROC_MAIN_V2_CALLBACK pMainCallBack;
pMainCallBack = (NDD_PROC_MAIN_V2_CALLBACK)pLib->resolve("NDD_PROC_MAIN_V2");
if (pMainCallBack != NULL)
{
Actor* actor = new Actor;
actor->registerFunction([this](QString name, int num){openFile(name,num);});
processor->registerActor("openFile",actor);
pMainCallBack(this, plugPath, processor, &procData);
}
else
{
ui.statusBar->showMessage(tr("plugin %1 load failed !").arg(plugPath), 10000);
}
}
void CCNotePad::loadPluginProcs(QString strLibDir, QMenu* pMenu)
{
std::function<void(NDD_PROC_DATA&, QMenu*)> foundCallBack = std::bind(&CCNotePad::onPlugFound, this, std::placeholders::_1, std::placeholders::_2);

View File

@ -34,6 +34,7 @@ struct HexFileMgr;
struct TextFileMgr;
struct BigTextEditFileMgr;
class QtLangSet;
class ActorProcessor;
static const char* Tail_Thread = "tailthread";
@ -349,8 +350,10 @@ private slots:
void on_loadReceneFile();
void slot_pluginMgr();
#ifdef NO_PLUGIN
void onPlugWorkV2(bool check);
void onPlugWork(bool check);
void sendParaToPlugin(NDD_PROC_DATA& procData);
void sendParaToPluginV2(NDD_PROC_DATA& procData);
#endif
void slot_showWebAddr(bool check);
void slot_langFileSuffix();
@ -524,6 +527,10 @@ private:
QSharedMemory* m_shareMem;
#ifdef NO_PLUGIN
//actor执行与存储单元
ActorProcessor* processor;
#endif
//最近打开的对比文件和目录列表。做一个环形区

81
src/functiontraits.h Normal file
View File

@ -0,0 +1,81 @@
#ifndef FUNCTIONTRAITS_H
#define FUNCTIONTRAITS_H
#include <utility>
#include <functional>
#include <algorithm>
#include <tuple>
template<typename T>
struct function_traits;
template<typename ReturnType, typename... Args>
struct function_traits<ReturnType(Args...)>
{
public:
enum {
value = sizeof...(Args)
};
using function_type = ReturnType(*)(Args...);
using return_type = ReturnType;
using stl_function_type = std::function<function_type>;
using function_pointer_type = ReturnType(*)(Args...);
using lambda_function_type = ReturnType(*)(Args...);
using tuple_type = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> ;
using bare_tuple_type = std::tuple<std::remove_const_t<std::remove_reference_t<Args>>...>;
template<std::size_t N, typename = typename std::enable_if<(N < value)>::type>
using args = typename std::tuple_element<N, std::tuple<Args...>>;
template <std::size_t N>
struct arguments
{
static_assert(N < value, "[error]:invalid parameter index.");
using type = typename std::tuple_element<N, std::tuple<Args...>>::type;
};
};
template<typename ReturnType, typename... Args>
struct function_traits<ReturnType(*)(Args...)> : function_traits<ReturnType(Args...)> {};
template<typename ReturnType, typename... Args>
struct function_traits<std::function<ReturnType(Args...)>> : function_traits<ReturnType(Args...)> {};
template <typename ReturnType, typename ClassType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...)> : function_traits<ReturnType(Args...)>{};
template <typename ReturnType, typename ClassType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const> : function_traits<ReturnType(Args...)> {};
template <typename ReturnType, typename ClassType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) volatile> : function_traits<ReturnType(Args...)> {};
template <typename ReturnType, typename ClassType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const volatile> : function_traits<ReturnType(Args...)> {};
template<typename Callable>
struct function_traits : function_traits<decltype(&Callable::operator())> {};
template<typename Function>
typename function_traits<Function>::stl_function_type
function_cast(const Function& lambda)
{
return static_cast<typename function_traits<Function>::stl_function_type>(std::forward<Function>(lambda));
}
template<typename Function>
typename function_traits<Function>::stl_function_type
function_cast(Function&& lambda)
{
return static_cast<typename function_traits<Function>::stl_function_type>(lambda);
}
template<typename Function>
typename function_traits<Function>::function_pointer_type
function_cast(const Function& lambda)
{
return static_cast<typename function_traits<Function>::pointer>(lambda);
}
#endif // FUNCTIONTRAITS_H

View File

@ -4,7 +4,9 @@
class QMenu;
class QsciScintilla;
class QWidget;
class ActorProcessor;
typedef int (*NDD_PROC_MAIN_CALLBACK)(QWidget* parent, const QString& strFileName, std::function<QsciScintilla*()>getCurEdit, NDD_PROC_DATA* procData);
typedef int (*NDD_PROC_MAIN_V2_CALLBACK)(QWidget* parent, const QString& strFileName,ActorProcessor*processor, NDD_PROC_DATA* procData);
int loadProc(const QString& strDirOut, std::function<void(NDD_PROC_DATA&, QMenu*)> funcallback, QMenu* pUserData);

View File

@ -1,4 +1,4 @@

option(USE_NOTEPAD_PLUGIN "构建 Notepad-- 内部插件" ON)
option(USE_NOTEPAD_PLUGIN_BASE "构建 Notepad-- 内部的插件基础模板" OFF)
@ -19,12 +19,12 @@ if(USE_NOTEPAD_PLUGIN)
add_subdirectory(template-plugins/base-secondary-menu-ui-plugin-v1)
endif(USE_NOTEPAD_PLUGIN_BASE)
# opencc 项目(基于 git)
add_subdirectory(opencc-demo-plugin)
#
add_subdirectory(versionUpdate)
#
add_subdirectory(external-plugin)
# # opencc 项目(基于 git)
# add_subdirectory(opencc-demo-plugin)
# #
# add_subdirectory(versionUpdate)
# #
# add_subdirectory(external-plugin)
# Linux
if(UNIX AND NOT APPLE)
@ -33,6 +33,6 @@ if(USE_NOTEPAD_PLUGIN)
endif(UNIX AND NOT APPLE)
# TTS
add_subdirectory(TTS-plugin)
add_subdirectory(filetreeview)
endif(USE_NOTEPAD_PLUGIN)

View File

@ -0,0 +1,74 @@
set(LOCAL_PLUGIN_NAME "filetreeview")
# TTS-plugin
# TTS-plugin
# 1. TTS-plugin
# 2. TTS-plugin
if(TRUE)
# TTS-plugin
spark_file_glob(LocalSources
./*.h ./*.cpp ./*.ui
)
spark_add_library(${LOCAL_PLUGIN_NAME} SHARED ${LocalSources})
target_include_directories(${LOCAL_PLUGIN_NAME} PRIVATE
${PROJECT_SOURCE_DIR}/src
${PROJECT_SOURCE_DIR}/src/cceditor
${PROJECT_SOURCE_DIR}/src/qscint/src
${PROJECT_SOURCE_DIR}/src/qscint/src/Qsci
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/src
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/include
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/lexlib
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/boostregex
)
# target_link_libraries(${LOCAL_PLUGIN_NAME} QSci)
target_link_QSci(${LOCAL_PLUGIN_NAME})
if(USE_QT6)
# target_link_qt6_Core5Compat(${LOCAL_PLUGIN_NAME}) # : Qt6 使 Core5Compat Qt5
# target_link_qt6_PrintSupport(${LOCAL_PLUGIN_NAME})
# target_link_qt6_XmlPatterns(${LOCAL_PLUGIN_NAME}) # Bug
else()
# target_link_qt5_PrintSupport(${LOCAL_PLUGIN_NAME})
# target_link_qt5_XmlPatterns(${LOCAL_PLUGIN_NAME})
endif(USE_QT6)
# Notepad-- plugin
set_target_properties(${LOCAL_PLUGIN_NAME}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin
LIBRARY_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin
ARCHIVE_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin)
# bin/plugin 每个位置或许都不一样(特别是 Linux)
# install(TARGETS ${LOCAL_PLUGIN_NAME} DESTINATION bin/plugin)
endif(TRUE)
# ----------------- TTS-plugin ----------------- #
if(WIN32 AND NOTEPAD_BUILD_BY_SHARED)
# Windows QScintilla
target_compile_definitions(${LOCAL_PLUGIN_NAME}
PRIVATE
NOTEPAD_PLUGIN_MANAGER
QSCINTILLA_DLL # Windows 使 QSci Q_DECL_IMPORT
# QSCINTILLA_EXPORT Q_DECL_IMPORT
)
else()
# Windows QScintilla
target_compile_definitions(${LOCAL_PLUGIN_NAME}
PRIVATE
NOTEPAD_PLUGIN_MANAGER
# QSCINTILLA_DLL # Windows 使 QSci Q_DECL_IMPORT
# QSCINTILLA_EXPORT Q_DECL_IMPORT
)
endif(WIN32 AND NOTEPAD_BUILD_BY_SHARED)
if(UNIX)
# Unix/Linux
target_compile_definitions(${LOCAL_PLUGIN_NAME}
PRIVATE
NOTEPAD_PLUGIN_MANAGER
)
endif(UNIX)

View File

@ -0,0 +1,125 @@
/**
** This file is part of ndd plugin file tree view
** Copyright ji wang <matheuter@gmail.com>.
**
** This program 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 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#ifndef _ACTOR_H_
#define _ACTOR_H_
#include <cstdint>
#include <string>
#include <memory>
#include <tuple>
#include <functional>
#include "functiontraits.h"
/**
* @brief Actor class, which encapsulates the event model
* @note enable_shared_from_this allows us to get safe Pointers internally
*/
class Actor : public std::enable_shared_from_this<Actor>
{
public:
using Ptr = std::shared_ptr<Actor>;
using FunctionWapper = std::function<void(void*, void*)>;
public:
Actor(){}
~Actor(){}
/**
* @brief Register the callback function and construct the anonymous function with std::bind
*/
template<typename Function>
void registerFunction(Function&& function_any) noexcept
{
m_invokeFunctionWapper = { std::bind(&invoker<Function>::apply, function_any, std::placeholders::_1, std::placeholders::_2) };
}
/**
* @brief Register the callback function and construct the anonymous function with std::bind
*/
template<typename ... Args>
void invoke(Args&& ... args) const noexcept
{
auto args_tuple = std::make_tuple(std::forward<Args>(args)...);
m_invokeFunctionWapper(&args_tuple, nullptr);
}
/**
* @brief Register the callback function and construct the anonymous function with std::bind
*/
template<typename R, typename ... Args>
R invoke(Args&& ...args) const
{
using tuple_args_type = std::tuple<Args...>;
char data[sizeof(tuple_args_type)];
std::tuple<Args...>* tuples_pointer = new (data) tuple_args_type;
*tuples_pointer = std::make_tuple(std::forward<Args>(args)...);
R return_value;
m_invokeFunctionWapper(tuples_pointer, &return_value);
return return_value;
}
public:
/**
* @brief This struct encapsulates a function,
* essentially storing the return value and parameters in two variables
* which can unify the way the function is stored.
*/
template<typename Function>
struct invoker
{
static inline void apply(const Function& func, void* bl, void* result)
{
using tuple_type = typename function_traits<Function>::tuple_type;
const tuple_type* tp = static_cast<tuple_type*>(bl);
call(func, *tp, result);
}
template<typename F, typename ... Args>
static typename std::enable_if<std::is_void<typename std::result_of<F(Args...)>::type>::value>::type
call(const F& f, const std::tuple<Args...>& tp, void*)
{
call_helper(f, std::make_index_sequence<sizeof... (Args)>{}, tp);
}
template<typename F, typename ... Args>
static typename std::enable_if<!std::is_void<typename std::result_of<F(Args...)>::type>::value>::type
call(const F& f, const std::tuple<Args...>& tp, void* result)
{
auto r = call_helper(f, std::make_index_sequence<sizeof... (Args)>{}, tp);
*(decltype(r)*)result = r;
}
template<typename F, size_t... I, typename ... Args>
static auto call_helper(const F& f, const std::index_sequence<I...>& h, const std::tuple<Args...>& tup)
{
return f(std::get<I>(tup)...);
}
};
private:
/**
* @note m_invokeFunctions is an anonymous lamba expression that encapsulates a function
* Functions include Lamba expressions, member functions, funtor, ordinary functions, and function Pointers
*/
FunctionWapper m_invokeFunctionWapper;
};
#endif

View File

@ -0,0 +1,85 @@
/**
** This file is part of ndd plugin file tree view
** Copyright ji wang <matheuter@gmail.com>.
**
** This program 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 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#include "actorprocessor.h"
ActorProcessor::ActorProcessor():
m_actorMap(new std::unordered_map<std::string, Actor*>)
{}
/**
* @brief
*/
ActorProcessor::~ActorProcessor()
{
for (auto& item : (*m_actorMap))
{
if(item.second != nullptr)
delete item.second;
}
if (m_actorMap)
delete m_actorMap;
}
/**
* @brief
*/
void ActorProcessor::registerActor(const std::string &route, Actor *actor)
{
m_actorMap->insert(std::make_pair(route,actor));
}
/**
* @brief
*/
void ActorProcessor::removeActor(const std::string &route)
{
auto iter = (*m_actorMap).find(route);
if(iter != m_actorMap->end())
{
m_actorMap->erase(route);
delete iter->second;
}
}
/**
* @brief
*/
Actor *ActorProcessor::findActor(const std::string &route)
{
auto iter = (*m_actorMap).find(route);
if(iter != m_actorMap->end())
{
return (*m_actorMap)[route];
}
return nullptr;
}
/**
* @brief
*/
bool ActorProcessor::resetActor(const std::string &route, Actor *actor)
{
auto iter = (*m_actorMap).find(route);
if(iter != m_actorMap->end())
{
m_actorMap->erase(route);
delete iter->second;
return true;
}
return false;
}

View File

@ -0,0 +1,67 @@
/**
** This file is part of ndd plugin file tree view
** Copyright ji wang <matheuter@gmail.com>.
**
** This program 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 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#ifndef _PROCESSOR_H
#define _PROCESSOR_H
#include <string>
#include <functional>
#include <map>
#include <iostream>
#include <unordered_map>
#include "actor.h"
class ActorProcessor
{
public:
ActorProcessor();
~ActorProcessor();
public:
template<typename ... Args>
void invoke(const std::string& route,Args&& ... args) const noexcept
{
if (m_actorMap->find(route) != m_actorMap->end())
(*m_actorMap)[route]->invoke(std::forward<Args>(args)...);
}
template<typename R, typename ... Args>
R invoke(const std::string& route,Args&& ...args) const
{
if (m_actorMap->find(route) != m_actorMap->end())
return (*m_actorMap)[route]->invoke(std::forward<Args>(args)...);
return nullptr;
}
void registerActor(const std::string& route, Actor*actor);
void removeActor(const std::string& route);
Actor* findActor(const std::string& route);
bool resetActor(const std::string& route,Actor*actor);
private:
std::unordered_map<std::string, Actor*>* m_actorMap;
private:
ActorProcessor(ActorProcessor&&)=delete;
ActorProcessor& operator=(const ActorProcessor&)=delete;
};
#endif // EVENTPROCESSOR_H

View File

@ -0,0 +1,526 @@
#include "filesystemmodel.h"
#include <QFileInfo>
#include <QDir>
#include <QIcon>
#include <QFont>
#include <QFileIconProvider>
#include <QFileSystemWatcher>
#include <QMutexLocker>
#include <QDebug>
FileNode::FileNode(FileSystemModel *model) :
m_model(model),
m_parent(0),
m_children(0),
m_bWatcher(false)
{
}
FileNode::FileNode(FileSystemModel *model, const QString &path, FileNode *parent) :
m_model(model),
m_parent(parent),
m_children(0),
m_path(path),
m_bWatcher(false)
{
QFileInfo info(path);
if (m_model->isRootPathNodeFillPath() && parent && parent->getNodeParent() == 0) {
m_text = QDir::toNativeSeparators(info.filePath());
} else {
m_text = info.fileName();
}
}
FileNode::~FileNode()
{
clear();
if (m_children) {
delete m_children;
}
if (m_bWatcher) {
m_model->removeWatcher(m_path);
}
}
QList<FileNode*>* FileNode::getChildrenList()
{
if (m_children == 0) {
m_children = new QList<FileNode*>();
if (!m_path.isEmpty()) {
QFileInfo info(m_path);
if (info.isDir()) {
QDir dir(m_path);
foreach(QFileInfo childInfo, dir.entryInfoList(this->m_model->filter(),this->m_model->dirSort())) {
if (!this->m_model->isShowHideFiles() && childInfo.isDir() && childInfo.fileName().startsWith(".")) {
continue;
}
m_children->append(new FileNode(this->m_model,childInfo.filePath(),this));
}
}
}
if (!m_children->isEmpty() && !m_bWatcher) {
m_bWatcher = true;
m_model->addWatcher(m_path);
}
}
return m_children;
}
FileNode* FileNode::getNodeParent()
{
return m_parent;
}
FileNode* FileNode::getChild(int row)
{
return getChildrenList()->at(row);
}
int FileNode::childCount()
{
return getChildrenList()->count();
}
int FileNode::row() const
{
if (m_parent) {
return m_parent->getChildrenList()->indexOf(const_cast<FileNode*>(this));
}
return 0;
}
QString FileNode::getNodePath() const
{
return m_path;
}
QString FileNode::text() const
{
return m_text;
}
bool FileNode::isDir() const
{
return QFileInfo(m_path).isDir();
}
bool FileNode::isFile() const
{
return QFileInfo(m_path).isFile();
}
QFileInfo FileNode::getFileInformation() const
{
return QFileInfo(m_path);
}
bool FileNode::isExist() const
{
return QFileInfo(m_path).exists();
}
void FileNode::clear()
{
if (m_children) {
qDeleteAll(m_children->begin(),m_children->end());
m_children->clear();
}
}
void FileNode::reload()
{
clear();
if (m_children == 0) {
m_children = new QList<FileNode*>();
}
if (!m_path.isEmpty()) {
QFileInfo info(m_path);
if (info.isDir()) {
QDir dir(m_path);
foreach(QFileInfo childInfo, dir.entryInfoList(this->m_model->filter(),this->m_model->dirSort())) {
if (!this->m_model->isShowHideFiles() && childInfo.isDir() && childInfo.fileName().startsWith(".")) {
continue;
}
m_children->append(new FileNode(this->m_model,childInfo.filePath(),this));
}
}
}
if (!m_children->isEmpty() && !m_bWatcher) {
m_bWatcher = true;
m_model->addWatcher(m_path);
}
}
FileNode *FileNode::findPath(const QString &path)
{
if (!path.startsWith(m_path)) {
return 0;
}
if (path == m_path) {
return this;
}
QStringList nameList = path.right(path.length()-m_path.length()).split("/",QString::SkipEmptyParts);
FileNode *parent = this;
bool find = false;
foreach (QString name,nameList) {
find = false;
QList<FileNode*>* chilren = parent->getChildrenList();
for (int i = 0; i < chilren->count(); i++) {
FileNode *node = chilren->at(i);
if (!node->isDir()) {
continue;
}
if (node->m_text == name) {
parent = node;
find = true;
break;
}
}
if (!find) {
return 0;
}
}
return parent;
}
FileSystemModel::FileSystemModel(QObject *parent) :
QAbstractItemModel(parent),
m_rootNode(new FileNode(this)),
m_iconProvider(new QFileIconProvider),
m_fileWatcher(0)
{
m_dirFilter = QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot;
m_sorts = QDir::DirsFirst | QDir::Name | QDir::IgnoreCase;// | QDir::Type;
// connect(m_fileWatcher,SIGNAL(directoryChanged(QString)),this,SLOT(directoryChanged(QString)));
}
FileSystemModel::~FileSystemModel()
{
delete m_rootNode;
delete m_iconProvider;
if (m_fileWatcher) {
delete m_fileWatcher;
}
}
void FileSystemModel::reloadDirectory(const QString &path)
{
this->beginResetModel();
QDir dir(path);
bool b = dir.exists();
if (!b) {
m_fileWatcher->removePath(path);
}
foreach(QModelIndex index,this->findPaths(path)) {
FileNode *node = nodeFromIndex(index);
if (b) {
node->reload();
} else {
FileNode *parent = node->getNodeParent();
if (parent) {
parent->reload();
}
}
}
this->endResetModel();
}
FileNode *FileSystemModel::nodeFromIndex(const QModelIndex &index) const
{
if (index.isValid()) {
return static_cast<FileNode*>(index.internalPointer());
}
return m_rootNode;
}
void FileSystemModel::setStartIndex(const QModelIndex &index)
{
m_startPath = filePath(index);
}
void FileSystemModel::setStartPath(const QString &path)
{
m_startPath = path;
}
QModelIndex FileSystemModel::startIndex() const
{
return findPath(m_startPath);
}
QString FileSystemModel::startPath() const
{
return m_startPath;
}
QString FileSystemModel::filePath(const QModelIndex &index) const
{
return nodeFromIndex(index)->getNodePath();
}
void FileSystemModel::setFilter(QDir::Filters filters)
{
if (m_dirFilter != filters) {
m_dirFilter = filters;
this->reload();
}
}
void FileSystemModel::setDirSort(QDir::SortFlags flags)
{
if (m_sorts != flags) {
m_sorts = flags;
this->reload();
}
}
QDir::Filters FileSystemModel::filter() const
{
return m_dirFilter;
}
bool FileSystemModel::isShowHideFiles() const
{
return m_dirFilter & QDir::Hidden;
}
QDir::SortFlags FileSystemModel::dirSort() const
{
return m_sorts;
}
void FileSystemModel::clear()
{
this->beginResetModel();
m_rootNode->clear();
m_pathList.clear();
m_startPath.clear();
this->endResetModel();
}
void FileSystemModel::reload()
{
this->setRootPathList(this->rootPathList());
}
void FileSystemModel::setRootPath(const QString &path)
{
this->setRootPathList(QStringList() << path);
}
bool FileSystemModel::removeRootPath(const QString &path)
{
QString pathName = QDir::fromNativeSeparators(path);
FileNode *node = 0;
int index = -1;
for (int i = 0; i < m_rootNode->childCount(); i++) {
node = m_rootNode->getChildrenList()->at(i);
if (node && (node->getNodePath() == pathName)) {
index = i;
break;
}
}
if (index == -1) {
return false;
}
if (!m_pathList.removeAll(pathName)) {
return false;
}
this->beginRemoveRows(QModelIndex(),index,index);
m_rootNode->getChildrenList()->removeAt(index);
delete node;
this->endRemoveRows();
return true;
}
bool FileSystemModel::addRootPath(const QString &path)
{
QString pathName = QDir::fromNativeSeparators(QDir::cleanPath(path));
if (m_pathList.contains(pathName)) {
return false;
}
this->beginInsertRows(QModelIndex(),m_rootNode->childCount(),m_rootNode->childCount());
m_pathList.append(pathName);
m_rootNode->getChildrenList()->append(new FileNode(this,pathName,m_rootNode));
this->endInsertRows();
return true;
}
void FileSystemModel::setRootPathList(const QStringList &pathList)
{
this->beginResetModel();
m_rootNode->clear();
m_fileWatcherMap.clear();
m_pathList.clear();
if (m_fileWatcher) {
disconnect(m_fileWatcher,0);
delete m_fileWatcher;
}
m_fileWatcher = new QFileSystemWatcher;
connect(m_fileWatcher,SIGNAL(directoryChanged(QString)),this,SIGNAL(direcotryChanged(QString)));
foreach (QString path, pathList) {
m_pathList.append(QDir::fromNativeSeparators(QDir::cleanPath(path)));
}
m_pathList.removeDuplicates();
foreach(QString path, m_pathList) {
m_rootNode->getChildrenList()->append(new FileNode(this,path,m_rootNode));
}
if (m_startPath.isEmpty() && !pathList.isEmpty()) {
m_startPath = pathList.first();
}
this->endResetModel();
}
QStringList FileSystemModel::rootPathList() const
{
return m_pathList;
}
QModelIndex FileSystemModel::findPathHelper(const QString &path, const QModelIndex &parentIndex) const
{
FileNode *node = nodeFromIndex(parentIndex);
if (!path.startsWith(node->getNodePath())) {
return QModelIndex();
}
if (path == node->getNodePath()) {
return parentIndex;
}
QStringList nameList = path.right(path.length()-node->getNodePath().length()).split("/",QString::SkipEmptyParts);
QModelIndex parent = parentIndex;
bool find = false;
int count = nameList.count();
for (int i = 0; i < count; i++) {
find = false;
for (int j = 0; j < this->rowCount(parent); j++) {
QModelIndex index = this->index(j,0,parent);
FileNode *node = nodeFromIndex(index);
if ( ( (i == count-1) || node->isDir()) && node->text() == nameList.at(i)) {
parent = index;
find = true;
break;
}
}
if (!find) {
return QModelIndex();
}
}
return parent;
}
QList<QModelIndex> FileSystemModel::findPaths(const QString &path) const
{
QList<QModelIndex> list;
QString cpath = QDir::fromNativeSeparators(QDir::cleanPath(path));
for (int i = 0; i < this->rowCount(); i++) {
QModelIndex find = findPathHelper(cpath,this->index(i,0));
if (find.isValid()) {
list.append(find);
}
}
return list;
}
QModelIndex FileSystemModel::findPath(const QString &path) const
{
QList<QModelIndex> list = this->findPaths(path);
if (!list.isEmpty()) {
return list.last();
}
return QModelIndex();
}
int FileSystemModel::rowCount(const QModelIndex &parent) const
{
FileNode *node = nodeFromIndex(parent);
return node->childCount();
}
int FileSystemModel::columnCount(const QModelIndex&) const
{
return 1;
}
QModelIndex FileSystemModel::parent(const QModelIndex &child) const
{
FileNode *node = nodeFromIndex(child);
FileNode *parent = node->getNodeParent();
if (parent == m_rootNode) {
return QModelIndex();
}
return createIndex(parent->row(),0,parent);
}
QModelIndex FileSystemModel::index(int row, int column,const QModelIndex &parent) const
{
if (!hasIndex(row,column,parent))
return QModelIndex();
FileNode *node = nodeFromIndex(parent);
return createIndex(row,column,node->getChild(row));
}
QVariant FileSystemModel::data(const QModelIndex &index, int role) const
{
FileNode *node = nodeFromIndex(index);
if (!node) {
return QVariant();
}
switch(role) {
case Qt::DisplayRole:
return node->text();
case Qt::ToolTipRole:
return QDir::toNativeSeparators(node->getNodePath());
case Qt::DecorationRole:
return m_iconProvider->icon(node->getFileInformation());
/*
case Qt::FontRole: {
QFont font;
if (node->path() == m_startPath) {
font.setBold(true);
}
return font;
}
*/
}
return QVariant();
}
bool FileSystemModel::isRootPathNode(FileNode *node) const
{
return node->getNodeParent() == m_rootNode;
}
bool FileSystemModel::isRootPathNodeFillPath() const
{
return false;
}
void FileSystemModel::addWatcher(const QString &path)
{
QMutexLocker _(&m_mutex);
QString cpath = QDir::fromNativeSeparators(QDir::cleanPath(path));
int value = m_fileWatcherMap[cpath];
value++;
m_fileWatcherMap[cpath] = value;
if (value > 1) {
return;
}
m_fileWatcher->addPath(path);
}
void FileSystemModel::removeWatcher(const QString &path)
{
QMutexLocker _(&m_mutex);
QString cpath = QDir::fromNativeSeparators(QDir::cleanPath(path));
int value = m_fileWatcherMap[cpath];
value--;
m_fileWatcherMap[cpath] = value;
if (value == 0) {
m_fileWatcher->removePath(cpath);
}
}

View File

@ -0,0 +1,193 @@
#ifndef FILESYSTEMMODEL_H
#define FILESYSTEMMODEL_H
#include <QAbstractItemModel>
#include <QStringList>
#include <QIcon>
#include <QFileInfo>
#include <QDir>
#include <QMutex>
class FileSystemModel;
class QFileSystemWatcher;
class QFileIconProvider;
class QFileSystemWatcher;
class QTreeView;
class FileNode
{
public:
FileNode(FileSystemModel *model);
FileNode(FileSystemModel *model,const QString &path, FileNode *parent);
virtual ~FileNode();
// 返回父节点
FileNode* getNodeParent();
// 按照index返回
FileNode* getChild(int row);
//! returns the number of children this node has.
int childCount();
//! returns the row number of this node.
int row() const;
//! returns a list of all the children of this node. The list will be empty if this node has no children.
QList<FileNode*>* getChildrenList();
//! returns the path of this node.
QString getNodePath() const;
//! returns the text of this node.
QString text() const;
//! returns the QFileInfo for this node.
QFileInfo getFileInformation() const;
//! returns true if this node exists on the file system.
bool isExist() const;
//! returns true if this node is a directory.
bool isDir() const;
//! returns true if this node is a file.
bool isFile() const;
//! clears this node.
void clear();
//! recreates the node from the file system.
void reload();
//! returns the node for the path specified.
FileNode *findPath(const QString &path);
protected:
//! The FileSystemModel is a QAbstractItemModel that provides a hierarchical view of the file system.
FileSystemModel *m_model;
//! The FileNode is a node in the tree of FileNodes.
FileNode *m_parent;
//! The list of FileNodes.
QList<FileNode*> *m_children;
//! The path of the FileNode.
QString m_path;
//! The text of the FileNode.
QString m_text;
//!< true if this node is being watched. If so, the model will watch the node and will need to be manually updated.
bool m_bWatcher;
};
class FileSystemModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit FileSystemModel(QObject *parent = 0);
~FileSystemModel();
void clear();
void reload();
void setFilter(QDir::Filters filters);
void setDirSort(QDir::SortFlags flags);
QDir::Filters filter() const;
bool isShowHideFiles() const;
QDir::SortFlags dirSort() const;
bool removeRootPath(const QString &path);
bool addRootPath(const QString &path);
void setRootPathList(const QStringList &pathList);
void setRootPath(const QString &path);
QStringList rootPathList() const;
QList<QModelIndex> findPaths(const QString &path) const;
QModelIndex findPath(const QString &path) const;
QString filePath(const QModelIndex &index) const;
FileNode *nodeFromIndex(const QModelIndex &index) const;
void setStartIndex(const QModelIndex &index);
void setStartPath(const QString &path);
QModelIndex startIndex() const;
QString startPath() const;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
virtual QModelIndex parent(const QModelIndex &child) const;
virtual QModelIndex index(int row, int column,const QModelIndex &parent = QModelIndex()) const;
virtual QVariant data(const QModelIndex &index, int role) const;
bool isRootPathNode(FileNode *node) const;
bool isRootPathNodeFillPath() const;
void addWatcher(const QString &path);
void removeWatcher(const QString &path);
signals:
void direcotryChanged(QString);
public slots:
void reloadDirectory(const QString &path);
protected:
//! Finds the node at the given \a path in the model.
QModelIndex findPathHelper(const QString &path, const QModelIndex &parentIndex) const;
//! The list of paths that are currently being watched.
QStringList m_pathList;
//! The root node of the model.
FileNode *m_rootNode;
//! The path to the directory to watch.
QString m_startPath;
//! The file icon provider.
QFileIconProvider *m_iconProvider;
//! The file system watcher.
QFileSystemWatcher *m_fileWatcher;
//! A map of watched files and their watcher indices.
QMap<QString,int> m_fileWatcherMap;
//! The tree view.
QTreeView *m_treeView;
//! The filters to apply to the directory.
QDir::Filters m_dirFilter;
//! The sort order to apply to the directory.
QDir::SortFlags m_sorts;
//! The mutex to protect the model.
QMutex m_mutex;
};
#endif // FILESYSTEMMODEL_H

View File

@ -0,0 +1,195 @@
/**
** This file is part of ndd plugin file tree view
** Copyright ji wang <matheuter@gmail.com>.
**
** This program 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 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#include "filetreeview.h"
#include <QTreeView>
#include <QJsonObject>
#include <QFileDialog>
#include <QMenu>
#include <QApplication>
#include <QMessageBox>
#include <QProcess>
#include"actorprocessor.h"
#include "filesystemmodel.h"
class FileTreeViewPrivate
{
public:
FileTreeViewPrivate(FileTreeView *parent):
q_ptr(parent)
{}
public:
ActorProcessor* m_processor;
QMenu* m_fileMenu;
QMenu* m_dirMenu;
QWidget* m_notepadWidget;
private:
FileTreeView * const q_ptr;
Q_DECLARE_PUBLIC(FileTreeView);
};
FileTreeView::FileTreeView(QWidget *parent):
d_ptr(new FileTreeViewPrivate(this)),
QTreeView(parent)
{
bindAction();
setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, SIGNAL(doubleClicked(QModelIndex)),this, SLOT(slotDoubleCliecked(QModelIndex)));
connect(this,SIGNAL(customContextMenuRequested(const QPoint &)),this, SLOT(slotCustomContextMenu(const QPoint &)));
}
FileTreeView::~FileTreeView()
{}
void FileTreeView::onNewWorkspaceItem(bool)
{
QString srcDirPath = QFileDialog::getExistingDirectory(
this, "choose src Directory",
"/");
if (srcDirPath.isEmpty()){
return;
}
FileSystemModel* model = static_cast<FileSystemModel*> (this->model());
model->addRootPath(srcDirPath);
model->reload();
this->update();
}
void FileTreeView::slotCustomContextMenu(const QPoint & pos)
{
Q_D(FileTreeView);
auto model = static_cast<FileSystemModel*>(this->model());
auto index= this->indexAt(pos);
if (model->nodeFromIndex(index)->isDir()){
d->m_dirMenu->exec(QCursor::pos());
}
else {
d->m_fileMenu->exec(QCursor::pos());
}
}
void FileTreeView::slotTerminal(bool)
{
}
void FileTreeView::slotNewFile(bool)
{
}
void FileTreeView::slotRemoveFile(bool)
{
}
void FileTreeView::slotAddDir(bool)
{
}
void FileTreeView::slotRemoveDir(bool)
{
Q_D(FileTreeView);
auto model = static_cast<FileSystemModel*>(this->model());
auto index= this->currentIndex();
if (model->nodeFromIndex(index)->isDir()){
(d->m_dirMenu)->exec(QCursor::pos());
}
else {
(d->m_fileMenu)->exec(QCursor::pos());
}
}
void FileTreeView::slotupdateDir(bool)
{
auto model = static_cast<FileSystemModel*>(this->model());
auto index= this->currentIndex();
if (model->nodeFromIndex(index)->isDir()){
model->reloadDirectory(model->nodeFromIndex(index)->getNodePath());
}
}
void FileTreeView::initMenuFile(QMenu *menu)
{
Q_D(FileTreeView);
d->m_fileMenu = menu;
}
void FileTreeView::initDirMenu(QMenu *menu)
{
Q_D(FileTreeView);
d->m_dirMenu = menu;
}
void FileTreeView::bindAction()
{
Q_D(FileTreeView);
QMenu* fileTreeMenu = new QMenu("menu",this);
QMenu* dirTreeMenu = new QMenu("file",this);
QAction *fileRename = new QAction(tr("Rename"),fileTreeMenu);
QAction *fileDelete = new QAction(tr("Delete"),fileTreeMenu);
QAction *fileOpenInExporter = new QAction(tr("OpenInExporter"),fileTreeMenu);
QAction *removeDir = new QAction(tr("Remove Dir"),dirTreeMenu);
QAction *update = new QAction(tr("Update"),dirTreeMenu);
QAction *fold = new QAction(tr("Fold Dir"),dirTreeMenu);
QAction *unfold = new QAction(tr("Unfold Dir"),dirTreeMenu);
QAction *terminal = new QAction(tr("terminal"));
d->m_dirMenu = dirTreeMenu;
d->m_dirMenu->addActions({removeDir,update,fold,unfold,terminal});
d->m_fileMenu = fileTreeMenu;
d->m_fileMenu->addActions({fileRename,fileDelete,fileOpenInExporter,terminal});
}
void FileTreeView::setActorProcessor(ActorProcessor *processor)
{
Q_D(FileTreeView);
d->m_processor = processor;
}
void FileTreeView::setMainWindow(QWidget *notepadWidget)
{
Q_D(FileTreeView);
d->m_notepadWidget = notepadWidget;
}
void FileTreeView::slotCliecked(const QModelIndex &index)
{
}
void FileTreeView::slotDoubleCliecked(const QModelIndex &index)
{
Q_D(FileTreeView);
auto model = static_cast<FileSystemModel*>(this->model());
if (model->nodeFromIndex(index)->isDir()){
}
else {
d->m_processor->invoke("openFile",model->nodeFromIndex(index)->getNodePath(),-1);
}
}

View File

@ -0,0 +1,72 @@
/**
** This file is part of ndd plugin file tree view
** Copyright ji wang <matheuter@gmail.com>.
**
** This program 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 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#ifndef WORKSPACE_H
#define WORKSPACE_H
#include <QObject>
#include <QTreeView>
class QModelIndex;
class QWidget;
class QMenu;
class ActorProcessor;
class FileTreeViewPrivate;
class FileTreeView : public QTreeView
{
Q_OBJECT
public:
FileTreeView(QWidget* parent = nullptr);
~FileTreeView();
void initMenuFile(QMenu*);
void initDirMenu(QMenu*);
void bindAction();
void setActorProcessor(ActorProcessor*processor);
void setMainWindow(QWidget* notepadWidget);
public slots:
void onNewWorkspaceItem(bool);
void slotCliecked(const QModelIndex &);
void slotDoubleCliecked(const QModelIndex &);
void slotCustomContextMenu(const QPoint &);
void slotTerminal(bool);
void slotNewFile(bool);
void slotRemoveFile(bool);
void slotAddDir(bool);
void slotRemoveDir(bool);
void slotupdateDir(bool);
signals:
void signalNewFile();
void signalRemoveFile();
void signalAddDir();
private:
FileTreeViewPrivate * const d_ptr;
Q_DECLARE_PRIVATE(FileTreeView);
FileTreeView(const FileTreeView &) = delete;
FileTreeView &operator=(const FileTreeView &) = delete;
};
#endif // WORKSPACE_H

View File

@ -0,0 +1,77 @@
#include <qobject.h>
#include <qstring.h>
#include <pluginGl.h>
#include <functional>
#include <qsciscintilla.h>
#include <QAction>
#include <QDebug>
#include "filetreeviewplugin.h"
#include "actorprocessor.h"
#define NDD_EXPORTDLL
#if defined(Q_OS_WIN)
#if defined(NDD_EXPORTDLL)
#define NDD_EXPORT __declspec(dllexport)
#else
#define NDD_EXPORT __declspec(dllimport)
#endif
#else
#define NDD_EXPORT __attribute__((visibility("default")))
#endif
#ifdef __cplusplus
extern "C" {
#endif
NDD_EXPORT bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData);
//NDD_EXPORT int NDD_PROC_MAIN(QWidget* pNotepad, const QString& strFileName, std::function<QsciScintilla* ()>getCurEdit, NDD_PROC_DATA* procData);
NDD_EXPORT int NDD_PROC_MAIN_V2(QWidget* pNotepad, const QString& strFileName,ActorProcessor* processor, NDD_PROC_DATA* procData);
#ifdef __cplusplus
}
#endif
static NDD_PROC_DATA s_procData;
static QWidget* s_pMainNotepad = nullptr;
std::function<QsciScintilla* ()> s_getCurEdit;
bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData)
{
if(pProcData == NULL)
{
return false;
}
pProcData->m_strPlugName = QObject::tr("File Tree");
pProcData->m_strComment = QObject::tr("file tree plugin");
pProcData->m_version = QString("1.0");
pProcData->m_auther = QString("matheuter@gmail.com");
pProcData->m_menuType = 1;
return true;
}
int NDD_PROC_MAIN_V2(QWidget* pNotepad, const QString& strFileName,ActorProcessor* processor,NDD_PROC_DATA* pProcData)
{
qDebug() << "test plugin";
//务必拷贝一份pProcData在外面会释放。
if (pProcData != nullptr)
{
s_procData = *pProcData;
}
else
{
return -1;
}
s_pMainNotepad = pNotepad;
FileTreeViewPlugin* plugin = new FileTreeViewPlugin();
plugin->setPluginModulePath(strFileName);
plugin->setActorProcessor(processor);
plugin->setTopMenu(pProcData->m_rootMenu);
plugin->setMenuActions(s_procData.m_rootMenu);
plugin->setNotepad(s_pMainNotepad);
return 0;
}

View File

@ -0,0 +1,139 @@
#include "filetreeviewplugin.h"
#include <QDockWidget>
#include <QObject>
#include <QAction>
#include <QFileInfo>
#include <QMainWindow>
#include <QDir>
#include <QTreeView>
#include <QDebug>
/**
** This file is part of ndd plugin file tree view
** Copyright ji wang <matheuter@gmail.com>.
**
** This program 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 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#include <qsciscintilla.h>
#include "filetreeview.h"
#include "filesystemmodel.h"
#include "qheaderview.h"
#include "actorprocessor.h"
class FileTreeViewPluginPrivate
{
public:
FileTreeViewPluginPrivate(FileTreeViewPlugin *parent):
q_ptr(parent)
{}
public:
ActorProcessor* m_processor;
QWidget* m_notepadWidget;
QMenu* m_topMenu;
QString m_pluginModulePath;
QDockWidget* m_dockWidget;
FileTreeView*m_treeview;
FileSystemModel * m_model;
std::function<QsciScintilla* ()> getCurrentEditFunc;
private:
FileTreeViewPlugin * const q_ptr;
Q_DECLARE_PUBLIC(FileTreeViewPlugin);
};
FileTreeViewPlugin::FileTreeViewPlugin(QObject *parent):
d_ptr(new FileTreeViewPluginPrivate(this))
{}
FileTreeViewPlugin::~FileTreeViewPlugin()
{
}
void FileTreeViewPlugin::setActorProcessor(ActorProcessor *processor)
{
Q_D(FileTreeViewPlugin);
d->m_processor = processor;
}
void FileTreeViewPlugin::setPluginModulePath(const QString &newPluginModulePath)
{
Q_D(FileTreeViewPlugin);
d->m_pluginModulePath = newPluginModulePath;
}
void FileTreeViewPlugin::bindAction()
{
}
void FileTreeViewPlugin::setTopMenu(QMenu *newTopMenu)
{
Q_D(FileTreeViewPlugin);
d->m_topMenu = newTopMenu;
}
void FileTreeViewPlugin::setNotepad(QWidget *newNotepad)
{
Q_D(FileTreeViewPlugin);
d->m_notepadWidget = newNotepad;
}
void FileTreeViewPlugin::setMenuActions(QMenu *menu)
{
Q_D(FileTreeViewPlugin);
QAction* pAction = new QAction("File Tree", menu);
menu->addAction(pAction);
connect(pAction, SIGNAL(triggered()),this,SLOT(slotMenuItemClick()));
}
void FileTreeViewPlugin::setCurrentEditFunc(std::function<QsciScintilla *()> func)
{
Q_D(FileTreeViewPlugin);
d->getCurrentEditFunc = func;
}
void FileTreeViewPlugin::slotMenuItemClick()
{
Q_D(FileTreeViewPlugin);
auto action = qobject_cast<QAction*>(sender());
auto mainWindow = dynamic_cast<QMainWindow*>(d->m_notepadWidget);
if (!mainWindow)
return;
if (!d->m_dockWidget) {
d->m_dockWidget = new QDockWidget(mainWindow);
mainWindow->addDockWidget(Qt::LeftDockWidgetArea, d->m_dockWidget);
d->m_treeview = new FileTreeView();
d->m_treeview->setActorProcessor(d->m_processor);
d->m_treeview->setMainWindow(d->m_notepadWidget);
d->m_treeview->header()->setVisible(false);
d->m_model = new FileSystemModel(d->m_treeview);
d->m_model->setRootPath("C:");
QAction* pAction = new QAction("Open Fold", d->m_topMenu);
d->m_topMenu->addAction(pAction);
connect(pAction, SIGNAL(triggered(bool)),d->m_treeview,SLOT(onNewWorkspaceItem(bool)));
d->m_treeview->setModel(d->m_model);
d->m_dockWidget->setWidget(d->m_treeview);
}
if (!d->m_dockWidget->isVisible())
d->m_dockWidget->show();
}

View File

@ -0,0 +1,59 @@
/**
** This file is part of ndd plugin file tree view
** Copyright ji wang <matheuter@gmail.com>.
**
** This program 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 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
#ifndef FILETREEWIDGET_H
#define FILETREEWIDGET_H
#include <QWidget>
#include <QMenu>
#include <QString>
class QsciScintilla;
class FileTreeViewPluginPrivate;
class ActorProcessor;
class FileTreeViewPlugin :public QObject
{
Q_OBJECT
public:
FileTreeViewPlugin(QObject *parent = nullptr);
~FileTreeViewPlugin();
public:
void setActorProcessor(ActorProcessor*processor);
void setMenuActions(QMenu *menu);
void setCurrentEditFunc(std::function<QsciScintilla* ()> func);
void setNotepad(QWidget *newNotepad);
void setTopMenu(QMenu *newTopMenu);
void setPluginModulePath(const QString &newPluginModulePath);
private:
void bindAction();
public slots:
void slotMenuItemClick();
private:
FileTreeViewPluginPrivate * const d_ptr;
Q_DECLARE_PRIVATE(FileTreeViewPlugin);
FileTreeViewPlugin(const FileTreeViewPlugin &) = delete;
FileTreeViewPlugin &operator=(const FileTreeViewPlugin &) = delete;
};
#endif // FILETREEWIDGET_H