diff --git a/juci/CMakeLists.txt b/juci/CMakeLists.txt index 6f9a517..9d13438 100644 --- a/juci/CMakeLists.txt +++ b/juci/CMakeLists.txt @@ -1,8 +1,10 @@ cmake_minimum_required (VERSION 2.8.4) set(project_name juci) +set(module juci_to_python_api) project (${project_name}) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") INCLUDE(FindPkgConfig) @@ -28,7 +30,7 @@ endif() #Boost_INCLUDE_DIRS - Boost include directories #Boost_LIBRARY_DIRS - Link directories for Boost libraries #Boost_LIBRARIES - Boost component libraries to be linked -find_package(Boost 1.5 REQUIRED) +find_package(Boost 1.5 REQUIRED COMPONENTS python) #If boost is not found if(${Boost_FOUND}) @@ -60,20 +62,33 @@ else() endif() + + # name of the executable on Windows will be example.exe add_executable(${project_name} -# list of every needed file to create the executable - keybindings - menu - source - window - juci -#there is no need for extentions - ) + #list of every needed file to create the executable + keybindings + menu + source + window + juci + api + #there is no need for extentions + ) + +add_library(${module} SHARED + + api.h + api_ext.cc + ) # dependencies include_directories(${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS} ${GTKMM_INCLUDE_DIRS}) -link_directories(${GTKMM_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS}) +link_directories(${GTKMM_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${PYTHON_INCLUDE_DIRS}) +#module: +set_target_properties(${module} PROPERTIES PREFIX "") +target_link_libraries(${module} ${PYTHON_LIBRARIES} ${Boost_LIBRARIES}) +#executable: target_link_libraries(${project_name} ${GTKMM_LIBRARIES} ${Boost_LIBRARIES} ${PYTHON_LIBRARIES}) diff --git a/juci/api.h b/juci/api.h new file mode 100644 index 0000000..ef84968 --- /dev/null +++ b/juci/api.h @@ -0,0 +1,77 @@ +#include +#include +#include +// +// Plugin API +// +namespace juci_api{ + // + // calls from python to C++ + // + namespace cpp{ + + // + // Replaceword: + // replaces a word in the editor with a string + // + void ReplaceWord(const std::string word_){ + //TODO implement api::ReplaceWord / change string to iter? + //some_namespace::controller::replaceWord(word_*); + std::cout << "unimplemented function: 'api::ReplaceWord()' called" + << std::endl; + } + + // + // ReplaceLine: + // Replaces a line in the editor with a string + // + void ReplaceLine(const std::string line_){ + //TODO implement api::ReplaceLine / change string to iter? + //some_namespace::controller::replaceLine(line_); + std::cout << "unimplemented function: 'api::ReplaceLine()' called" + << std::endl; + } + + }//namespace cpp + + // + // calls from C++ to Python + // + namespace py{ + const std::string g_project_root("~/bachelor/app/juci/"); + //helpers + boost::python::api::object openPythonScript(const std::string path, + boost::python::api::object python_name_space) { + std::string temp = g_project_root + path + ".py"; + boost::python::str the_path(temp); + return boost::python::exec_file(the_path, python_name_space);//, python_name_space); + } + + //void snippet(std::string& word); + + void plugin(const std::string& plugin_name){ + try{ + /* initialize python interpreter */ + Py_Initialize(); + boost::python::api::object main_module = boost::python::import("__main__"); + boost::python::api::object main_namespace = main_module.attr("__dict__"); + + /* runs script from python */ + //boost::python::object ignored1 = setPythonVar("word", word, main_namespace); + boost::python::api::object ignored2 = openPythonScript(plugin_name, main_namespace); + /* extracts desired values */ + //boost::python::object pySnippet = boost::python::eval("getSnippet()", main_namespace); + //word = boost::python::extract(pySnippet); + /* add snippet to textView */ + //TODO add snippet + }catch(boost::python::error_already_set const&){ + PyErr_Print(); + } + } + + }// py + +}//juci_api + + + diff --git a/juci/api_ext.cc b/juci/api_ext.cc new file mode 100644 index 0000000..922b86b --- /dev/null +++ b/juci/api_ext.cc @@ -0,0 +1,8 @@ +#include "api.h" + +BOOST_PYTHON_MODULE(jucy_to_python_api) { + using namespace boost::python; + // text editing + def("replaceLine", &juci_api::cpp::ReplaceLine); + def("replaceWord", &juci_api::cpp::ReplaceWord); + }// module::juci diff --git a/juci/juci.h b/juci/juci.h index 715d466..6eb5018 100644 --- a/juci/juci.h +++ b/juci/juci.h @@ -14,7 +14,8 @@ public: Gtk::Box window_box_; std::shared_ptr source(); private: - Menu::Controller menu; + Keybindings::Controller keybindings_; + Menu::Controller menu_; Source::Controller source_; /*signal handler*/ void onSystemQuit(); diff --git a/juci/menu.cc b/juci/menu.cc index c298010..9d028f2 100644 --- a/juci/menu.cc +++ b/juci/menu.cc @@ -7,7 +7,7 @@ Menu::Model::Model() { ui_string_ = - " " + " " " " " " " " @@ -47,18 +47,18 @@ Menu::Model::Model() { Menu::Model::~Model() { } -/***********************************/ -/* VIEW */ -/***********************************/ + +// VIEW + Menu::View::View(Gtk::Orientation orientation) : view_(orientation) { } -Glib::RefPtr Menu::View::view( +Gtk::Box& Menu::View::view( Glib::RefPtr ui_manager) { view_.pack_start(*ui_manager->get_widget("/MenuBar"), Gtk::PACK_SHRINK); - return Glib::RefPtr(&view_); + return view_; } Menu::View::~View() { @@ -87,6 +87,7 @@ Menu::Controller::Controller(Keybindings::Controller keybindings) : [this]() { OnFileNewCCFile(); }); + keybindings_.action_group()->add(Gtk::Action::create("FileNewH", Gtk::Stock::NEW, "New h file", "Create a new h file"), Gtk::AccelKey("h"), @@ -168,6 +169,10 @@ Menu::Controller::Controller(Keybindings::Controller keybindings) : Menu::Controller::~Controller() { } +Gtk::Box& Menu::Controller::view() { + return menu_view_.view(keybindings_.ui_manager()); +} + void Menu::Controller::OnFileNewEmptyfile() { std::cout << "New file clicked" << std::endl; //TODO(Oyvang) Legg til funksjon @@ -179,14 +184,14 @@ void Menu::Controller::OnFileNewCCFile() { } void Menu::Controller::OnFileNewHeaderFile() { - std::cout << "New cc file clicked" << std::endl; + std::cout << "New header file clicked" << std::endl; //TODO(Oyvang) Legg til funksjon } void Menu::Controller::OnSystemQuit() { //TODO(Oyvang, Zalox, Forgie) Add everything that needs to be done before quiting /*Quit the system*/ - Gtk::Main::quit(); //TODO(Oyvang, Zalox, Forgie) methode is depricated, find a better solution. + } void Menu::Controller::OnPluginAddSnippet() { diff --git a/juci/menu.h b/juci/menu.h index 9c5be84..caa9e98 100644 --- a/juci/menu.h +++ b/juci/menu.h @@ -19,7 +19,7 @@ namespace Menu { public: explicit View(Gtk::Orientation orient); virtual ~View(); - Glib::RefPtr view(Glib::RefPtr ui_manager); + Gtk::Box& view(Glib::RefPtr ui_manager); protected: Gtk::Box view_; @@ -29,7 +29,7 @@ namespace Menu { public: explicit Controller(Keybindings::Controller keybindings); virtual ~Controller(); - + Gtk::Box& view(); private: Keybindings::Controller keybindings_; View menu_view_; diff --git a/juci/plugin/CMakeLists.txt b/juci/plugin/CMakeLists.txt new file mode 100644 index 0000000..2b05816 --- /dev/null +++ b/juci/plugin/CMakeLists.txt @@ -0,0 +1,57 @@ +cmake_minimum_required (VERSION 2.4) +set(project_name plugin) +project (${project_name}) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") + +include(FindPkgConfig) + +#Boost_FOUND - True if headers and requested libraries were found +#Boost_INCLUDE_DIRS - Boost include directories +#Boost_LIBRARY_DIRS - Link directories for Boost libraries +#Boost_LIBRARIES - Boost component libraries to be linked +find_package(Boost 1.55 REQUIRED COMPONENTS python system ) + +if(!${Boost_FOUND}) + message(FATAL_ERROR "Boost libraries not found") +endif() + +#GTKMM_FOUND - True if headers and requested libraries were found +#GTKMM_INCLUDE_DIRS - GTKMM include directories +#GTKMM_LIBRARY_DIRS - Link directories for GTKMM libraries +#GTKMM_LIBRARIES - GTKMM component libraries to be linked +pkg_check_modules(GTKMM REQUIRED gtkmm-3.0) + +if(!${GTKMM_FOUND}) + message(FATAL_ERROR "Gtkmm not found") +endif() + +#PYTHONLIBS_FOUND - True if headers and requested libraries were found +#PYTHON_INCLUDE_DIRS - GTKMM include directories +#PYTHON_LIBRARIES - GTKMM component libraries to be linked +#$PYTHONLIBS_VERSION_STRING - ersion string +find_package(PythonLibs 2.7 REQUIRED) + +if(!${PYTHONLIBS_FOUND}) + message(FATAL_ERROR "Pythonlibs not found") +else() + message("Found python libs ${PYTHONLIBS_VERSION_STRING}") +endif() + +ADD_LIBRARY(plugintest_ext MODULE + plugin.h + plugin.cc + plugin_ext.cc + ) + +set_target_properties(plugintest_ext PROPERTIES PREFIX "") +target_link_libraries(plugintest_ext ${Boost_LIBRARIES}) + +add_executable(${project_name} + plugin.h + plugin.cc + ) + +include_directories(${PYTHON_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${GTKMM_INCLUDE_DIRS}) +link_directories(${GTKMM_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${PYTHON_LIBRARIES}) +target_link_libraries(${project_name} ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} ${GTKMM_LIBRARIES}) \ No newline at end of file diff --git a/juci/plugin/plugin.cc b/juci/plugin/plugin.cc new file mode 100644 index 0000000..1a76f57 --- /dev/null +++ b/juci/plugin/plugin.cc @@ -0,0 +1,118 @@ +#include "plugin.h" + +//////////////////////////////////////////////////////////////////////////////// +// +// setPythonVar: +// initiates a string value (k_var_value) to a declared variable name +// (k_var_name) within a given namespace(python_name_space) +// +//////////////////////////////////////////////////////////////////////////////// + +bp::object Plugin::setPythonVar(const std::string k_var_name, + const std::string k_var_value, + bp::object python_name_space ) { + std::string temp = k_var_name + " = \"" + k_var_value + "\""; + bp::str the_var(temp); + return bp::exec(the_var, python_name_space); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// openPythonScript: +// Opens a python plugin script within a file path and a python namespace +// +//////////////////////////////////////////////////////////////////////////////// + +bp::object Plugin::openPythonScript(const std::string path, + bp::object python_name_space) { + std::string temp = g_project_root + "plugins/" + path + "/" + path + ".py"; + bp::str the_path(temp); + return bp::exec_file(the_path, python_name_space); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// for testing purposes only +// +//////////////////////////////////////////////////////////////////////////////// + +std::string Plugin::get_test_value2(){ + return "STRING FROM WITHIN C++"; +} + +/* public functions */ + + +//////////////////////////////////////////////////////////////////////////////// +// +// snippet: +// takes a std::string and converts it into a matching snippet +// if no matching snippet, returns the same string +// +//////////////////////////////////////////////////////////////////////////////// + +void Plugin::snippet(std::string& word){ + try{ + /* initialize python interpreter */ + Py_Initialize(); + bp::object main_module = bp::import("__main__"); + bp::object main_namespace = main_module.attr("__dict__"); + + /* runs script from python */ + bp::object ignored1 = setPythonVar("word", word, main_namespace); + bp::object ignored2 = openPythonScript(__func__, main_namespace); + + /* extracts desired values */ + bp::object pySnippet = bp::eval("getSnippet()", main_namespace); + word = bp::extract(pySnippet); + /* add snippet to textView */ + //TODO add snippet + + }catch(bp::error_already_set const&){ + PyErr_Print(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// +// get_test_value: +// for testing purposes +// uses a python module generated from c++ +// calls c++ function from python +// returns string to c++ from python +// prints the string from python within c++ +// +//////////////////////////////////////////////////////////////////////////////// + + void Plugin::get_test_value(){ + try{ + /* initialize python interpreter */ + Py_Initialize(); + bp::object main_module = bp::import("__main__"); + bp::object main_namespace = main_module.attr("__dict__"); + + /* runs script from python */ + const std::string path("test"); + bp::object ignored2 = openPythonScript(path, main_namespace); + + /* extracts desired values */ + bp::object pySnippet = bp::eval("get_test_value()", main_namespace); + std::string mword = bp::extract(pySnippet); + /* add snippet to textView */ + std::cout << mword << std::endl; + //TODO add snippet + + }catch(bp::error_already_set const&){ + PyErr_Print(); + } + } + +int main(int argc, char *argv[]) +{ + std::string word("ifelse"); + Plugin::snippet(word); + //Plugin::get_test_value(); + std::cout << word << std::endl; + return 0; + +} diff --git a/juci/plugin/plugin.h b/juci/plugin/plugin.h new file mode 100644 index 0000000..0c6e1aa --- /dev/null +++ b/juci/plugin/plugin.h @@ -0,0 +1,28 @@ +#ifndef JUCI_PLUGIN_H_ +#define JUCI_PLUGIN_H_ + +#include +#include + +#include +#include + +namespace bp = boost::python; + +const std::string g_project_root("~/q6/testing/plugin/"); +//TODO (forgie) get current working directory.. + +class Plugin{ + public: + static void snippet(std::string& word); + static void get_test_value(); + static std::string get_test_value2(); + private: + static bp::object setPythonVar(const std::string varName, + const std::string varValue, + bp::object python_name_space); + static bp::object openPythonScript(const std::string path, + bp::object python_name_space); +}; + +#endif // JUCI_PLUGIN_H_ diff --git a/juci/plugin/plugin_ext.cc b/juci/plugin/plugin_ext.cc new file mode 100644 index 0000000..5067e10 --- /dev/null +++ b/juci/plugin/plugin_ext.cc @@ -0,0 +1,8 @@ +#include "plugin.h" +#include +using namespace boost::python; + +BOOST_PYTHON_MODULE(plugintest_ext) +{ + def("get_test_value2", &Plugin::get_test_value2); +} diff --git a/juci/plugin/randomtext.txt b/juci/plugin/randomtext.txt new file mode 100644 index 0000000..4bbb4f6 --- /dev/null +++ b/juci/plugin/randomtext.txt @@ -0,0 +1,39 @@ +/* +void theprogram() +{ + std::string input; + std::cout << "Enter string to transform: "; + std::getline(std::cin, input); + //std::string inttransformed = CallPythonPlugIn(input); + std::cout << "The transformed string is: " << input << std::endl; +} + +int test1() +{ + try{ + Py_Initialize(); + object main_module = import("__main__"); + object main_namespace = main_module.attr("__dict__"); + object ignored = exec("result = 5 ** 2", main_namespace); + int five_squared = extract(main_namespace["result"]); + + printf("%d\n", five_squared); + + return five_squared; + } + catch(error_already_set const&){ + PyErr_Print(); + } + + return -1; +} + +void test2(int theNum, int &test) +{ + int seven = 7; + + test = 7+ theNum; + + std::cout << theNum << std::endl; +} +*/ diff --git a/juci/window.cc b/juci/window.cc index 2fb07c7..4e27b3b 100644 --- a/juci/window.cc +++ b/juci/window.cc @@ -2,14 +2,15 @@ Window::Window() : window_box_(Gtk::ORIENTATION_HORIZONTAL), - menu() { + menu_(keybindings_) { set_title("example juCi++"); set_default_size(600, 600); // window_box_.add(*source_.sourceview()); add(window_box_); - add_accel_group(menu.ui_manager()->get_accel_group()); - window_box_.pack_start(menu.view()); + add_accel_group(keybindings_.ui_manager()->get_accel_group()); + window_box_.pack_start(menu_.view()); show_all_children(); + } std::shared_ptr Window::source() {