Browse Source

Cleanup of sourcefile

merge-requests/365/head
Jørgen Lien Sellæg 11 years ago
parent
commit
3045c728cc
  1. 3
      src/api.cc
  2. 61
      src/config.cc
  3. 152
      src/directories.cc
  4. 79
      src/directories.h
  5. 68
      src/files.h
  6. 2
      src/juci.cc
  7. 2
      src/juci.h
  8. 6
      src/menu.cc
  9. 1
      src/menu.h
  10. 146
      src/notebook.cc
  11. 16
      src/notebook.h
  12. 73
      src/source.cc
  13. 15
      src/source.h
  14. 106
      src/sourcefile.cc
  15. 31
      src/sourcefile.h
  16. 528
      src/window.cc
  17. 11
      src/window.h

3
src/api.cc

@ -205,8 +205,7 @@ void libjuci::IterToWordEnd(Gtk::TextIter &iter) {
}
Glib::RefPtr<Gtk::TextBuffer> libjuci::BufferFromNotebook() {
return Glib::RefPtr<Gtk::TextBuffer>(PluginApi::notebook
->CurrentSourceView()->get_buffer());
return Glib::RefPtr<Gtk::TextBuffer>(PluginApi::notebook->get_current_view()->get_buffer());
}
Gtk::TextIter libjuci::IterFromNotebook() {

61
src/config.cc

@ -1,11 +1,9 @@
#include "singletons.h"
#include "config.h"
#include "logging.h"
#include <fstream>
#include <string>
#include <vector>
#include <exception>
#include "files.h"
#include "sourcefile.h"
MainConfig::MainConfig() {
find_or_create_config_files();
@ -22,12 +20,9 @@ void MainConfig::find_or_create_config_files() {
for (auto &file : files) {
auto path = boost::filesystem::path(Singleton::config_dir() + file);
if (!boost::filesystem::is_regular_file(path)) {
std::ofstream output;
output.open(path.string());
if (file == "config.json") output << configjson;
if (file == "plugins.py") output << pluginspy;
if (file == "menu.xml") output << menuxml;
output.close();
if (file == "config.json") juci::filesystem::save(path, configjson);
if (file == "plugins.py") juci::filesystem::save(path, pluginspy);
if (file == "menu.xml") juci::filesystem::save(path, menuxml);
}
}
}
@ -39,41 +34,28 @@ void MainConfig::GenerateSource() {
auto source_json = cfg.get_child("source");
auto syntax_json = source_json.get_child("syntax");
auto colors_json = source_json.get_child("colors");
auto extensions_json = source_json.get_child("extensions");
auto visual_json = source_json.get_child("visual");
for (auto &i : visual_json) {
if (i.first == "background") {
if (i.first == "background")
source_cfg->background = i.second.get_value<std::string>();
}
else if (i.first == "background_selected") {
else if (i.first == "background_selected")
source_cfg->background_selected = i.second.get_value<std::string>();
}
else if (i.first == "background_tooltips") {
else if (i.first == "background_tooltips")
source_cfg->background_tooltips = i.second.get_value<std::string>();
}
else if (i.first == "show_line_numbers") {
else if (i.first == "show_line_numbers")
source_cfg->show_line_numbers = i.second.get_value<std::string>() == "1" ? true : false;
}
else if (i.first == "highlight_current_line") {
else if (i.first == "highlight_current_line")
source_cfg->highlight_current_line = i.second.get_value<std::string>() == "1" ? true : false;
}
else if (i.first == "font") {
else if (i.first == "font")
source_cfg->font = i.second.get_value<std::string>();
}
}
source_cfg->tab_size = source_json.get<unsigned>("tab_size");
for (unsigned c = 0; c < source_cfg->tab_size; c++) {
for (unsigned c = 0; c < source_cfg->tab_size; c++)
source_cfg->tab+=" ";
}
for (auto &i : colors_json) {
for (auto &i : colors_json)
source_cfg->tags[i.first]=i.second.get_value<std::string>();
}
for (auto &i : syntax_json) {
for (auto &i : syntax_json)
source_cfg->types[i.first]=i.second.get_value<std::string>();
}
for (auto &i : extensions_json) {
source_cfg->extensions.emplace_back(i.second.get_value<std::string>());
}
DEBUG("Source cfg fetched");
}
@ -82,12 +64,10 @@ void MainConfig::GenerateTerminalCommands() {
boost::property_tree::ptree source_json = cfg.get_child("project");
boost::property_tree::ptree compile_commands_json = source_json.get_child("compile_commands");
boost::property_tree::ptree run_commands_json = source_json.get_child("run_commands");
for (auto &i : compile_commands_json) {
for (auto &i : compile_commands_json)
terminal_cfg->compile_commands.emplace_back(i.second.get_value<std::string>());
}
for (auto &i : run_commands_json) {
for (auto &i : run_commands_json)
terminal_cfg->run_command=(i.second.get_value<std::string>()); //TODO: run_commands array->one run_command?
}
}
void MainConfig::GenerateKeybindings() {
@ -97,12 +77,7 @@ void MainConfig::GenerateKeybindings() {
std::cerr << "menu.xml not found" << std::endl;
throw;
}
std::ifstream input(path.string());
std::string line;
if (input.is_open()) {
while (getline(input, line))
menu->ui += line;
}
menu->ui = juci::filesystem::open(path);
boost::property_tree::ptree keys_json = cfg.get_child("keybindings");
for (auto &i : keys_json) {
auto key=i.second.get_value<std::string>();
@ -118,8 +93,8 @@ void MainConfig::GenerateDirectoryFilter() {
boost::property_tree::ptree ignore_json = dir_json.get_child("ignore");
boost::property_tree::ptree except_json = dir_json.get_child("exceptions");
for ( auto &i : except_json )
dir_cfg->AddException(i.second.get_value<std::string>());
dir_cfg->exceptions.emplace_back(i.second.get_value<std::string>());
for ( auto &i : ignore_json )
dir_cfg->AddIgnore(i.second.get_value<std::string>());
dir_cfg->ignored.emplace_back(i.second.get_value<std::string>());
DEBUG("Directory filter fetched");
}

152
src/directories.cc

@ -1,104 +1,109 @@
#include "directories.h"
#include "sourcefile.h"
#include "logging.h"
#include "singletons.h"
#include <algorithm>
#include "boost/algorithm/string.hpp"
Directories::Controller::Controller() {
namespace sigc {
SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
}
Directories::Directories() {
DEBUG("adding treeview to scrolledwindow");
m_ScrolledWindow.add(m_TreeView);
m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
add(tree_view);
set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
tree_store = Gtk::TreeStore::create(column_record);
tree_view.set_model(tree_store);
tree_view.append_column("", column_record.name);
tree_store->set_sort_column(0, Gtk::SortType::SORT_ASCENDING);
tree_view.signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column){
INFO("Directory navigation");
auto iter = tree_store->get_iter(path);
if (iter) {
Gtk::TreeModel::Row row = *iter;
std::string upath = Glib::ustring(row[column_record.path]);
boost::filesystem::path fs_path(upath);
if (boost::filesystem::is_directory(fs_path)) {
tree_view.row_expanded(path) ? tree_view.collapse_row(path) : tree_view.expand_row(path, false);
} else {
std::stringstream sstm;
sstm << row[column_record.path];
if(on_row_activated)
on_row_activated(sstm.str());
}
}
});
}
void Directories::Controller::
open_folder(const boost::filesystem::path& dir_path) {
void Directories::open_folder(const boost::filesystem::path& dir_path) {
INFO("Open folder");
m_refTreeModel = Gtk::TreeStore::create(view());
m_TreeView.set_model(m_refTreeModel);
m_TreeView.remove_all_columns();
DEBUG("Getting project name from CMakeLists.txt");
std::string project_name = GetCmakeVarValue(dir_path, "project");
m_TreeView.append_column(project_name, view().m_col_name);
int row_id = 0;
Gtk::TreeModel::Row row;
DEBUG("Listing directories");
list_dirs(dir_path, row, row_id);
DEBUG("Sorting directories");
m_refTreeModel->set_sort_column(0, Gtk::SortType::SORT_ASCENDING);
tree_store->clear();
tree_view.get_column(0)->set_title(get_cmakelists_variable(dir_path, "project"));
add_paths(dir_path, Gtk::TreeModel::Row(), 0);
DEBUG("Folder opened");
}
bool Directories::Controller::IsIgnored(std::string path) {
bool Directories::ignored(std::string path) {
DEBUG("Checking if file-/directory is filtered");
std::transform(path.begin(), path.end(), path.begin(), ::tolower);
if (Singleton::Config::directories()->IsException(path)) {
return false;
for(std::string &i : Singleton::Config::directories()->exceptions) {
if(i == path)
return false;
}
if (Singleton::Config::directories()->IsIgnored(path)) {
return true;
for(auto &i : Singleton::Config::directories()->ignored) {
if(path.find(i, 0) != std::string::npos)
return true;
}
return false;
}
void Directories::Controller::
list_dirs(const boost::filesystem::path& dir_path,
Gtk::TreeModel::Row &parent,
unsigned row_id) {
void Directories::add_paths(const boost::filesystem::path& dir_path, const Gtk::TreeModel::Row &parent, unsigned row_id) {
boost::filesystem::directory_iterator end_itr;
Gtk::TreeModel::Row child;
Gtk::TreeModel::Row row;
DEBUG("");
// Fill the treeview
for ( boost::filesystem::directory_iterator itr( dir_path );
itr != end_itr;
++itr ) {
if (!IsIgnored(itr->path().filename().string())) {
for(boost::filesystem::directory_iterator itr(dir_path);itr != end_itr;++itr) {
if (!ignored(itr->path().filename().string())) {
if (boost::filesystem::is_directory(itr->status())) {
if (count(itr->path().string()) > count(dir_path.string())) { // is child
child = *(m_refTreeModel->append(parent.children()));
if (boost::filesystem::canonical(itr->path()) > boost::filesystem::canonical(dir_path)) { // is child
child = *(tree_store->append(parent.children()));
std::string col_id("a"+itr->path().filename().string());
child[view().m_col_id] = col_id;
child[view().m_col_name] = itr->path().filename().string();
child[view().m_col_path] = itr->path().string();
list_dirs(itr->path(), child, row_id);
child[column_record.id] = col_id;
child[column_record.name] = itr->path().filename().string();
child[column_record.path] = itr->path().string();
add_paths(itr->path(), child, row_id);
} else {
row = *(m_refTreeModel->append());
row = *(tree_store->append());
std::string col_id("a"+itr->path().filename().string());
row[view().m_col_path] = itr->path().string();
row[view().m_col_id] = col_id;
row[view().m_col_name] = itr->path().filename().string();
list_dirs(itr->path(), parent, row_id);
row[column_record.path] = itr->path().string();
row[column_record.id] = col_id;
row[column_record.name] = itr->path().filename().string();
add_paths(itr->path(), parent, row_id);
}
} else { // is a file
child = *(m_refTreeModel->append(parent.children()));
child = *(tree_store->append(parent.children()));
std::string col_id("b"+itr->path().filename().string());
child[view().m_col_id] = col_id;
child[view().m_col_name] = itr->path().filename().string();
child[view().m_col_path] = itr->path().string();
child[column_record.id] = col_id;
child[column_record.name] = itr->path().filename().string();
child[column_record.path] = itr->path().string();
}
}
}
}
int Directories::Controller::count(const std::string path) {
int count = 0;
for (size_t i = 0; i < path.size(); i++)
if (path[i] == '/')
count++;
return count;
}
std::string Directories::Controller::
GetCmakeVarValue(const boost::filesystem::path& dir_path, std::string command_name) {
std::string Directories::get_cmakelists_variable(const boost::filesystem::path& dir_path, std::string command_name) {
INFO("fetches cmake variable value for: "+command_name);
std::string project_name;
std::string project_name_var;
boost::filesystem::directory_iterator end_itr;
for (boost::filesystem::directory_iterator itr( dir_path );
itr != end_itr;
++itr ) {
for (boost::filesystem::directory_iterator itr( dir_path );itr != end_itr;++itr ) {
if (itr->path().filename().string() == "CMakeLists.txt") {
std::ifstream ifs(itr->path().string());
std::string line;
while (std::getline(ifs, line)) {
for (auto &line : juci::filesystem::lines(itr->path())) {
if (line.find(command_name+"(", 0) != std::string::npos
|| line.find(command_name+" (", 0) != std::string::npos ) {
size_t variable_start = line.find("{", 0);
@ -133,8 +138,7 @@ GetCmakeVarValue(const boost::filesystem::path& dir_path, std::string command_na
}
}
}
std::ifstream ifs2(itr->path().string());
while (std::getline(ifs2, line)) {
for (auto &line : juci::filesystem::lines(itr->path())) {
if (line.find("set(", 0) != std::string::npos
|| line.find("set (", 0) != std::string::npos) {
if( line.find(project_name_var, 0) != std::string::npos) {
@ -155,25 +159,3 @@ GetCmakeVarValue(const boost::filesystem::path& dir_path, std::string command_na
INFO("Couldn't find value in CMakeLists.txt");
return "no project name";
}
void Directories::Config::AddIgnore(std::string filter) {
ignore_list_.push_back(filter);
}
void Directories::Config::AddException(std::string filter) {
exception_list_.push_back(filter);
}
bool Directories::Config::IsIgnored(std::string str) {
for ( auto &i : ignore_list() )
if (str.find(i, 0) != std::string::npos)
return true;
return false;
}
bool Directories::Config::IsException(std::string str) {
for ( std::string &i : exception_list() )
if (i == str)
return true;
return false;
}

79
src/directories.h

@ -2,69 +2,42 @@
#define JUCI_DIRECTORIES_H_
#include <gtkmm.h>
#include <glib.h>
#include <vector>
#include <string>
#include "boost/filesystem.hpp"
#include "boost/algorithm/string.hpp"
#include <utility>
#include <algorithm>
#include <iostream>
#include <fstream>
namespace Directories {
class Directories : public Gtk::ScrolledWindow {
public:
class Config {
public:
std::vector<std::string> ignore_list() { return ignore_list_; }
std::vector<std::string> exception_list() { return exception_list_; }
void AddIgnore(std::string filter);
void AddException(std::string filter);
bool IsException(std::string path);
bool IsIgnored(std::string path);
private:
std::vector<std::string> ignore_list_;
std::vector<std::string> exception_list_;
std::vector<std::string> ignored;
std::vector<std::string> exceptions;
};
class View : public Gtk::TreeModel::ColumnRecord {
class ColumnRecord : public Gtk::TreeModel::ColumnRecord {
public:
View() {
add(m_col_id);
add(m_col_name);
add(m_col_path);
ColumnRecord() {
add(id);
add(name);
add(path);
}
Gtk::TreeModelColumn<Glib::ustring> m_col_id;
Gtk::TreeModelColumn<Glib::ustring> m_col_name;
Gtk::TreeModelColumn<Glib::ustring> m_col_path;
Gtk::TreeModelColumn<Glib::ustring> id;
Gtk::TreeModelColumn<Glib::ustring> name;
Gtk::TreeModelColumn<Glib::ustring> path;
};
class Model { };
class Controller {
public:
Controller();
View& view() { return view_;}
Model& model() { return model_;}
Gtk::ScrolledWindow& widget() {return m_ScrolledWindow;}
void open_folder(const boost::filesystem::path& dir_path);
void list_dirs(const boost::filesystem::path& dir_path,
Gtk::TreeModel::Row &row, unsigned depth);
std::string GetCmakeVarValue(const boost::filesystem::path& dir_path, std::string command_name);
int count(const std::string path);
// Child widgets:
Gtk::Box m_VBox;
Gtk::ScrolledWindow m_ScrolledWindow;
Gtk::TreeView m_TreeView;
Glib::RefPtr<Gtk::TreeStore> m_refTreeModel;
bool IsIgnored(std::string path);
Directories();
void open_folder(const boost::filesystem::path& dir_path);
std::string get_cmakelists_variable(const boost::filesystem::path& dir_path, std::string command_name);
private:
View view_;
Model model_;
std::function<void(const std::string &file)> on_row_activated;
protected:
void on_treeview_row_activated(const Gtk::TreeModel::Path& path,
Gtk::TreeViewColumn* column);
};
} // namespace Directories
private:
void add_paths(const boost::filesystem::path& dir_path, const Gtk::TreeModel::Row &row, unsigned depth);
Gtk::TreeView tree_view;
Glib::RefPtr<Gtk::TreeStore> tree_store;
ColumnRecord column_record;
bool ignored(std::string path);
};
#endif // JUCI_DIRECTORIES_H_

68
src/files.h

@ -155,3 +155,71 @@ const std::string pluginspy =
" juci.initPlugin(current_file) \n"
"loadplugins() \n";
const std::string snippetpy =
"#!/usr/bin/python \n"
"#snippet plugin \n"
"import juci_to_python_api as juci, inspect \n"
" \n"
"def initPlugin(): \n"
" juci.addMenuElement(\"Snippet\") \n"
" juci.addSubMenuElement(\"SnippetMenu\", #name of parent menu \n"
" \"Insert snippet\", #menu description \n"
" \"insertSnippet()\", #function to execute \n"
" inspect.getfile(inspect.currentframe()), #plugin path \n"
" \"<control><alt>space\") \n"
"snippets = {} \n"
" \n"
"snippets[\"for\"] = \"\"\"\ \n"
"for(int i=0; i<v.size(); i++) { \n"
" // std::cout << v[i] << std::endl; \n"
" // Write code here \n"
"} \n"
"\"\"\" \n"
" \n"
"snippets[\"if\"] = \"\"\"\ \n"
"if(true) { \n"
" // Write code here \n"
"} \n"
"\"\"\" \n"
" \n"
"snippets[\"ifelse\"] = \"\"\"\ \n"
"if(false) { \n"
" // Write code here \n"
"} else { \n"
" // Write code here \n"
"} \n"
"\"\"\" \n"
" \n"
"snippets[\"while\"] = \"\"\"\ \n"
"while(condition) { \n"
" // Write code here \n"
"} \n"
"\"\"\" \n"
" \n"
"snippets[\"main\"] = \"\"\"\ \n"
"int main(int argc, char *argv[]) { \n"
" //Do something \n"
"} \n"
"\"\"\" \n"
" \n"
"snippets[\"hello\"] = \"\"\"\ \n"
"#include <iostream> \n"
" \n"
"int main(int argc, char *argv[]) { \n"
" std::cout << \"Hello, world! << std::endl; \n"
"} \n"
"\"\"\" \n"
" \n"
"def getSnippet(word): \n"
" try: \n"
" output = snippets[word] \n"
" except KeyError: \n"
" output = word \n"
" return output \n"
" \n"
"def insertSnippet(): \n"
" theWord=juci.getWord() \n"
" output=getSnippet(theWord) \n"
" juci.replaceWord(output) \n";

2
src/juci.cc

@ -40,7 +40,7 @@ void Juci::on_activate() {
window->directories.open_folder(directory);
}
for(auto &f: files)
window->notebook.open_file(f);
window->notebook.open(f);
}
int main(int argc, char *argv[]) {

2
src/juci.h

@ -1,7 +1,6 @@
#ifndef JUCI_JUCI_H_
#define JUCI_JUCI_H_
#include "config.h"
#include "window.h"
#include "logging.h"
@ -13,7 +12,6 @@ public:
void on_activate();
private:
MainConfig main_config;
std::unique_ptr<Window> window;
std::string directory;
std::vector<std::string> files;

6
src/menu.cc

@ -7,7 +7,7 @@ Menu::Menu() : box(Gtk::ORIENTATION_VERTICAL) {
action_group = Gtk::ActionGroup::create();
ui_manager = Gtk::UIManager::create();
action_group->add(Gtk::Action::create("FileNew", "New File"));
action_group->add(Gtk::Action::create("FileMenu", "File"));
action_group->add(Gtk::Action::create("EditMenu", "Edit"));
action_group->add(Gtk::Action::create("WindowMenu", "_Window"));
action_group->add(Gtk::Action::create("WindowSplitWindow", "Split window"), Gtk::AccelKey(key_map["split_window"]), [this]() {
@ -25,10 +25,6 @@ Gtk::Widget& Menu::get_widget() {
return *ui_manager->get_widget("/MenuBar");
}
Gtk::Menu& Menu::get_source_menu() {
return *(Gtk::Menu*)ui_manager->get_widget("/MenuBar/SourceMenu");
}
void Menu::build() {
try {
ui_manager->add_ui_from_string(ui);

1
src/menu.h

@ -9,7 +9,6 @@ class Menu {
public:
Menu();
Gtk::Widget& get_widget();
Gtk::Menu& get_source_menu();
void build();
Gtk::Box box;

146
src/notebook.cc

@ -1,8 +1,7 @@
#include <fstream>
#include "notebook.h"
#include "logging.h"
#include "sourcefile.h"
#include "singletons.h"
#include <iostream> //TODO: remove
using namespace std; //TODO: remove
namespace sigc {
@ -10,92 +9,68 @@ namespace sigc {
}
Notebook::Notebook() : Gtk::Notebook() {
INFO("Create notebook");
Gsv::init();
}
auto menu=Singleton::menu();
INFO("Notebook create signal handlers");
menu->action_group->add(Gtk::Action::create("FileMenu", "File"));
menu->action_group->add(Gtk::Action::create("WindowCloseTab", "Close tab"), Gtk::AccelKey(menu->key_map["close_tab"]), [this]() {
close_current_page();
});
menu->action_group->add(Gtk::Action::create("EditUndo", "Undo"), Gtk::AccelKey(menu->key_map["edit_undo"]), [this]() {
INFO("On undo");
Glib::RefPtr<Gsv::UndoManager> undo_manager = CurrentSourceView()->get_source_buffer()->get_undo_manager();
if (Pages() != 0 && undo_manager->can_undo()) {
undo_manager->undo();
}
INFO("Done undo");
});
menu->action_group->add(Gtk::Action::create("EditRedo", "Redo"), Gtk::AccelKey(menu->key_map["edit_redo"]), [this]() {
INFO("On Redo");
Glib::RefPtr<Gsv::UndoManager> undo_manager =
CurrentSourceView()->get_source_buffer()->get_undo_manager();
if (Pages() != 0 && undo_manager->can_redo()) {
undo_manager->redo();
}
INFO("Done Redo");
});
int Notebook::size() {
return get_n_pages();
}
menu->action_group->add(Gtk::Action::create("SourceGotoDeclaration", "Go to declaration"), Gtk::AccelKey(menu->key_map["source_goto_declaration"]), [this]() {
if(CurrentPage()!=-1) {
if(CurrentSourceView()->get_declaration_location) {
auto location=CurrentSourceView()->get_declaration_location();
if(location.first.size()>0) {
open_file(location.first);
CurrentSourceView()->get_buffer()->place_cursor(CurrentSourceView()->get_buffer()->get_iter_at_offset(location.second));
while(gtk_events_pending())
gtk_main_iteration();
CurrentSourceView()->scroll_to(CurrentSourceView()->get_buffer()->get_insert(), 0.0, 1.0, 0.5);
}
}
}
});
Source::View* Notebook::get_view(int page) {
if(page>=size())
return nullptr;
return source_views.at(page).get();
}
menu->action_group->add(Gtk::Action::create("SourceGotoMethod", "Go to method"), Gtk::AccelKey(menu->key_map["source_goto_method"]), [this]() {
if(CurrentPage()!=-1) {
if(CurrentSourceView()->goto_method) {
CurrentSourceView()->goto_method();
}
}
});
Source::View* Notebook::get_current_view() {
INFO("Getting sourceview");
if(get_current_page()==-1)
return nullptr;
return get_view(get_current_page());
}
void Notebook::open_file(std::string path) {
void Notebook::open(std::string path) {
INFO("Notebook open file");
INFO("Notebook create page");
for(int c=0;c<Pages();c++) {
if(path==source_views.at(c)->view->file_path) {
for(int c=0;c<size();c++) {
if(path==get_view(c)->file_path) {
set_current_page(c);
return;
}
}
source_views.emplace_back(new Source(path, project_path));
auto tmp_project_path=project_path;
if(tmp_project_path=="") {
tmp_project_path=boost::filesystem::path(path).parent_path().string();
}
auto language=Source::guess_language(path);
if(language && (language->get_id()=="chdr" || language->get_id()=="c" || language->get_id()=="cpp" || language->get_id()=="objc"))
source_views.emplace_back(new Source::ClangView(path, tmp_project_path));
else
source_views.emplace_back(new Source::GenericView(path, tmp_project_path, language));
scrolled_windows.emplace_back(new Gtk::ScrolledWindow());
hboxes.emplace_back(new Gtk::HBox());
scrolled_windows.back()->add(*source_views.back()->view);
scrolled_windows.back()->add(*source_views.back());
hboxes.back()->pack_start(*scrolled_windows.back(), true, true);
boost::filesystem::path file_path(source_views.back()->view->file_path);
boost::filesystem::path file_path(source_views.back()->file_path);
std::string title=file_path.filename().string();
append_page(*hboxes.back(), title);
show_all_children();
set_current_page(Pages()-1);
set_focus_child(*source_views.back()->view);
CurrentSourceView()->get_buffer()->set_modified(false);
set_current_page(size()-1);
set_focus_child(*source_views.back());
get_current_view()->get_buffer()->set_modified(false);
//Add star on tab label when the page is not saved:
auto source_view=CurrentSourceView();
CurrentSourceView()->get_buffer()->signal_modified_changed().connect([this, source_view]() {
auto source_view=get_current_view();
get_current_view()->get_buffer()->signal_modified_changed().connect([this, source_view]() {
boost::filesystem::path file_path(source_view->file_path);
std::string title=file_path.filename().string();
if(source_view->get_buffer()->get_modified())
title+="*";
int page=-1;
for(int c=0;c<Pages();c++) {
if(source_views.at(c)->view.get()==source_view) {
for(int c=0;c<size();c++) {
if(get_view(c)==source_view) {
page=c;
break;
}
@ -105,14 +80,34 @@ void Notebook::open_file(std::string path) {
});
}
bool Notebook::save(int page) {
if(page>=size())
return false;
auto view=get_view(page);
if (view->file_path != "" && view->get_buffer()->get_modified()) {
juci::filesystem::save(view->file_path, view->get_buffer()->get_text());
view->get_buffer()->set_modified(false);
Singleton::terminal()->print("File saved to: " +view->file_path+"\n");
return true;
}
return false;
}
bool Notebook::save_current() {
INFO("Notebook save current file");
if(get_current_page()==-1)
return false;
return save(get_current_page());
}
bool Notebook::close_current_page() {
INFO("Notebook close page");
if (Pages() != 0) {
if(CurrentSourceView()->get_buffer()->get_modified()){
if (size() != 0) {
if(get_current_view()->get_buffer()->get_modified()){
if(!save_modified_dialog())
return false;
}
int page = CurrentPage();
int page = get_current_page();
remove_page(page);
source_views.erase(source_views.begin()+ page);
scrolled_windows.erase(scrolled_windows.begin()+page);
@ -121,26 +116,13 @@ bool Notebook::close_current_page() {
return true;
}
Source::View* Notebook::CurrentSourceView() {
INFO("Getting sourceview");
return source_views.at(CurrentPage())->view.get();
}
int Notebook::CurrentPage() {
return get_current_page();
}
int Notebook::Pages() {
return get_n_pages();
}
bool Notebook::save_modified_dialog() {
INFO("Notebook::save_dialog");
INFO("Notebook::save_modified_dialog");
Gtk::MessageDialog dialog((Gtk::Window&)(*get_toplevel()), "Save file!", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO);
dialog.set_secondary_text("Do you want to save: " + CurrentSourceView()->file_path+" ?");
dialog.set_secondary_text("Do you want to save: " + get_current_view()->file_path+" ?");
int result = dialog.run();
if(result==Gtk::RESPONSE_YES) {
CurrentSourceView()->save();
save_current();
return true;
}
else if(result==Gtk::RESPONSE_NO) {

16
src/notebook.h

@ -3,29 +3,27 @@
#include <iostream>
#include "gtkmm.h"
#include "entrybox.h"
#include "source.h"
#include "directories.h"
#include <boost/algorithm/string/case_conv.hpp>
#include <type_traits>
#include <map>
#include <sigc++/sigc++.h>
#include "clangmm.h"
class Notebook : public Gtk::Notebook {
public:
Notebook();
Source::View* CurrentSourceView();
int CurrentPage();
Source::View* get_view(int page);
int size();
Source::View* get_current_view();
bool close_current_page();
void open_file(std::string filename);
int Pages();
void open(std::string filename);
bool save(int page);
bool save_current();
std::string project_path;
std::vector<std::unique_ptr<Source> > source_views;
private:
bool save_modified_dialog();
std::vector<std::unique_ptr<Source::View> > source_views;
std::vector<std::unique_ptr<Gtk::ScrolledWindow> > scrolled_windows;
std::vector<std::unique_ptr<Gtk::HBox> > hboxes;
};

73
src/source.cc

@ -1,7 +1,6 @@
#include "source.h"
#include "sourcefile.h"
#include <boost/property_tree/json_parser.hpp>
#include <fstream>
#include <boost/timer/timer.hpp>
#include "logging.h"
#include <algorithm>
@ -16,14 +15,22 @@ namespace sigc {
SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
}
bool Source::Config::legal_extension(std::string e) const {
std::transform(e.begin(), e.end(),e.begin(), ::tolower);
if (find(extensions.begin(), extensions.end(), e) != extensions.end()) {
DEBUG("Legal extension");
return true;
Glib::RefPtr<Gsv::Language> Source::guess_language(const std::string &file_path) {
auto language_manager=Gsv::LanguageManager::get_default();
bool result_uncertain = false;
auto content_type = Gio::content_type_guess(file_path, NULL, 0, result_uncertain);
if(result_uncertain) {
content_type.clear();
}
auto language=language_manager->guess_language(file_path, content_type);
if(!language) {
auto path=boost::filesystem::path(file_path);
auto filename=path.filename().string();
auto extension=path.extension();
if(filename=="CMakeLists.txt")
language=language_manager->get_language("cmake");
}
DEBUG("Ilegal extension");
return false;
return language;
}
//////////////
@ -34,13 +41,10 @@ file_path(file_path), project_path(project_path) {
set_smart_home_end(Gsv::SMART_HOME_END_BEFORE);
set_show_line_numbers(Singleton::Config::source()->show_line_numbers);
set_highlight_current_line(Singleton::Config::source()->highlight_current_line);
sourcefile s(file_path);
get_source_buffer()->get_undo_manager()->begin_not_undoable_action();
get_source_buffer()->set_text(s.get_content());
get_source_buffer()->set_text(juci::filesystem::open(file_path));
get_source_buffer()->get_undo_manager()->end_not_undoable_action();
get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(0));
search_settings = gtk_source_search_settings_new();
gtk_source_search_settings_set_wrap_around(search_settings, true);
search_context = gtk_source_search_context_new(get_source_buffer()->gobj(), search_settings);
@ -56,20 +60,6 @@ file_path(file_path), project_path(project_path) {
g_signal_connect(search_context, "notify::occurrences-count", G_CALLBACK(search_occurrences_updated), this);
}
bool Source::View::save() {
INFO("Source save file");
if (file_path != "" && get_buffer()->get_modified()) {
std::ofstream file;
file.open (file_path);
file << get_buffer()->get_text();
file.close();
get_buffer()->set_modified(false);
Singleton::terminal()->print("File saved to: " +file_path+"\n");
return true;
}
return false;
}
void Source::View::search_occurrences_updated(GtkWidget* widget, GParamSpec* property, gpointer data) {
auto view=(Source::View*)data;
if(view->update_search_occurrences)
@ -241,7 +231,7 @@ bool Source::View::on_key_press_event(GdkEventKey* key) {
/////////////////////
//// GenericView ////
/////////////////////
Source::GenericView::GenericView(const std::string& file_path, const std::string& project_path) : View(file_path, project_path) {
Source::GenericView::GenericView(const std::string& file_path, const std::string& project_path, Glib::RefPtr<Gsv::Language> language) : View(file_path, project_path) {
auto style_scheme_manager=Gsv::StyleSchemeManager::get_default();
//TODO: add?: style_scheme_manager->prepend_search_path("~/.juci/");
auto scheme=style_scheme_manager->get_scheme("classic");
@ -252,20 +242,6 @@ Source::GenericView::GenericView(const std::string& file_path, const std::string
cout << "TODO, in progress: def:comment in scheme " << scheme->get_name() << " has color " << style->property_foreground() << endl;
}
auto language_manager=Gsv::LanguageManager::get_default();
bool result_uncertain = false;
auto content_type = Gio::content_type_guess(file_path, get_buffer()->get_text(), result_uncertain);
if(result_uncertain) {
content_type.clear();
}
auto language=language_manager->guess_language(file_path, content_type);
if(!language) {
auto path=boost::filesystem::path(file_path);
auto filename=path.filename().string();
auto extension=path.extension();
if(filename=="CMakeLists.txt")
language=language_manager->get_language("cmake");
}
if(language) {
get_source_buffer()->set_language(language);
Singleton::terminal()->print("Language for file "+file_path+" set to "+language->get_name()+".\n");
@ -1038,18 +1014,3 @@ Source::ClangViewAutocomplete(file_path, project_path) {
}
};
}
////////////////
//// Source ////
////////////////
Source::Source(const std::string& file_path, std::string project_path) {
if(project_path=="") {
project_path=boost::filesystem::path(file_path).parent_path().string();
}
if (Singleton::Config::source()->legal_extension(file_path.substr(file_path.find_last_of(".") + 1)))
view=std::unique_ptr<View>(new ClangView(file_path, project_path));
else
view=std::unique_ptr<View>(new GenericView(file_path, project_path));
INFO("Source Controller with childs constructed");
}

15
src/source.h

@ -15,16 +15,15 @@
#include "selectiondialog.h"
#include <set>
class Source {
public:
namespace Source {
Glib::RefPtr<Gsv::Language> guess_language(const std::string &file_path);
class Config {
public:
bool legal_extension(std::string e) const ;
unsigned tab_size;
bool show_line_numbers, highlight_current_line;
std::string tab, background, background_selected, background_tooltips, font;
char tab_char=' ';
std::vector<std::string> extensions;
std::unordered_map<std::string, std::string> tags, types;
}; // class Config
@ -50,8 +49,6 @@ public:
View(const std::string& file_path, const std::string& project_path);
~View();
bool save();
void search_highlight(const std::string &text, bool case_sensitive, bool regex);
std::function<void(int number)> update_search_occurrences;
void search_forward();
@ -82,7 +79,7 @@ public:
class GenericView : public View {
public:
GenericView(const std::string& file_path, const std::string& project_path);
GenericView(const std::string& file_path, const std::string& project_path, Glib::RefPtr<Gsv::Language> language);
};
class ClangViewParse : public View {
@ -167,9 +164,5 @@ public:
ClangView(const std::string& file_path, const std::string& project_path):
ClangViewRefactor(file_path, project_path) {}
};
Source(const std::string& file_path, std::string project_path);
std::unique_ptr<Source::View> view;
}; // class Source
#endif // JUCI_SOURCE_H_

106
src/sourcefile.cc

@ -1,92 +1,32 @@
#include "sourcefile.h"
#include <giomm.h>
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
sourcefile::sourcefile(const string &input_filename)
: lines(), filename(input_filename) {
open(input_filename);
}
/**
*
*/
void sourcefile::open(const string &filename) {
Gio::init();
// Creates/Opens a file specified by the input string.
Glib::RefPtr<Gio::File> file = Gio::File::create_for_path(filename);
if (!file) // Gio::File has overloaded operator
cerr << "Was not able to open file: " << filename << endl;
// Creates pointer for filestream
if (!file->query_exists()) {
file->create_file()->close();
std::string juci::filesystem::open(std::string path) {
std::string res;
for (auto &line : lines(path)) {
res += line;
}
Glib::RefPtr<Gio::FileInputStream> stream = file->read();
if (!stream) // error message on stream failure
cerr << filename << " returned an empty stream" << endl;
Glib::RefPtr<Gio::DataInputStream>
datainput = Gio::DataInputStream::create(stream);
string line;
while (datainput->read_line(line)) {
lines.push_back(line);
}
datainput->close();
stream->close();
}
vector<string> sourcefile::get_lines() {
return lines;
}
string sourcefile::get_line(int line_number) {
return lines[line_number];
}
int sourcefile::save(const string &text) {
Gio::init();
// Creates/Opens a file specified by the input string.
Glib::RefPtr<Gio::File> file = Gio::File::create_for_path(filename);
if (!file) // Gio::File has overloaded operator
cerr << "Was not able to open file: " << filename << endl;
// Creates
Glib::RefPtr<Gio::FileOutputStream> stream =
file->query_exists() ? file->replace() : file->create_file();
if (!stream) // error message on stream failure
cerr << filename << " returned an empty stream" << endl;
Glib::RefPtr<Gio::DataOutputStream>
output = Gio::DataOutputStream::create(stream);
output->put_string(text);
output->close();
stream->close();
return 0;
return res;
}
string sourcefile::get_content() {
string res;
for (auto line : lines) {
res.append(line).append("\n");
std::vector<std::string> juci::filesystem::lines(std::string path) {
std::vector<std::string> res;
std::ifstream input(path);
if (input.is_open()) {
do { res.emplace_back(); } while(getline(input, res.back()));
}
input.close();
return res;
}
int juci::filesystem::save(std::string path, std::string new_content) {
std::ofstream output(path);
if(output.is_open()) {
output << new_content;
} else {
output.close();
return 1;
}
output.close();
return 0;
}

31
src/sourcefile.h

@ -1,21 +1,20 @@
#ifndef JUCI_SOURCEFILE_H_
#define JUCI_SOURCEFILE_H_
#include <string>
#include <vector>
#include <string>
#include <boost/filesystem.hpp>
class sourcefile {
public:
explicit sourcefile(const std::string &filename);
std::vector<std::string> get_lines();
std::string get_content();
std::string get_line(int line_number);
int save(const std::string &text);
private:
void open(const std::string &filename);
std::vector<std::string> lines;
std::string filename;
};
namespace juci {
class filesystem {
public:
static std::string open(std::string);
static std::string open(boost::filesystem::path path) { return open(path.string()); }
static std::vector<std::string> lines(std::string);
static std::vector<std::string> lines(boost::filesystem::path path) { return lines(path.string()); };
static int save(std::string, std::string);
static int save(boost::filesystem::path path, std::string new_content) { return save(path.string(), new_content); }
static int save(std::string path) { return save(path, ""); };
static int save(boost::filesystem::path path) { return save(path, ""); };
};
} // namepace juci
#endif // JUCI_SOURCEFILE_H_

528
src/window.cc

@ -1,203 +1,217 @@
#include "window.h"
#include "logging.h"
#include "singletons.h"
#include "sourcefile.h"
#include "config.h"
#include "api.h"
namespace sigc {
SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
}
Window::Window() : notebook(), plugin_api(&notebook), box(Gtk::ORIENTATION_VERTICAL) {
Window::Window() : box(Gtk::ORIENTATION_VERTICAL) {
INFO("Create Window");
set_title("juCi++");
set_default_size(600, 400);
set_events(Gdk::POINTER_MOTION_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::SCROLL_MASK);
add(box);
//TODO: see TODO Window::on_directory_navigation
directories.m_TreeView.signal_row_activated().connect(sigc::mem_fun(*this, &Window::on_directory_navigation));
MainConfig(); //Read the configs here
PluginApi(&this->notebook); //Initialise plugins
add_menu();
box.pack_start(entry_box, Gtk::PACK_SHRINK);
directory_and_notebook_panes.pack1(directories, true, true); //TODO: should be pack1(directories, ...) Clean up directories.*
directory_and_notebook_panes.pack2(notebook);
directory_and_notebook_panes.set_position(120);
vpaned.set_position(300);
vpaned.pack1(directory_and_notebook_panes, true, false);
vpaned.pack2(Singleton::terminal()->view, true, true);
box.pack_end(vpaned);
show_all_children();
directories.on_row_activated=[this](const std::string &file) {
notebook.open(file);
};
entry_box.signal_show().connect([this](){
std::vector<Gtk::Widget*> focus_chain;
focus_chain.emplace_back(&entry_box);
box.set_focus_chain(focus_chain);
});
entry_box.signal_hide().connect([this](){
box.unset_focus_chain();
});
entry_box.signal_hide().connect([this]() {
if(notebook.get_current_page()!=-1) {
notebook.get_current_view()->grab_focus();
}
});
notebook.signal_switch_page().connect([this](Gtk::Widget* page, guint page_num) {
if(search_entry_shown && entry_box.labels.size()>0 && notebook.get_current_page()!=-1) {
notebook.get_current_view()->update_search_occurrences=[this](int number){
entry_box.labels.begin()->update(0, std::to_string(number));
};
notebook.get_current_view()->search_highlight(last_search, case_sensitive_search, regex_search);
}
if(notebook.get_current_page()!=-1) {
if(auto menu_item=dynamic_cast<Gtk::MenuItem*>(Singleton::menu()->ui_manager->get_widget("/MenuBar/SourceMenu/SourceGotoDeclaration")))
menu_item->set_sensitive((bool)notebook.get_current_view()->get_declaration_location);
if(auto menu_item=dynamic_cast<Gtk::MenuItem*>(Singleton::menu()->ui_manager->get_widget("/MenuBar/SourceMenu/SourceGotoMethod")))
menu_item->set_sensitive((bool)notebook.get_current_view()->goto_method);
if(auto menu_item=dynamic_cast<Gtk::MenuItem*>(Singleton::menu()->ui_manager->get_widget("/MenuBar/SourceMenu/SourceRename")))
menu_item->set_sensitive((bool)notebook.get_current_view()->rename_similar_tokens);
}
});
INFO("Window created");
} // Window constructor
void Window::add_menu() {
auto menu=Singleton::menu();
INFO("Adding actions to menu");
menu->action_group->add(Gtk::Action::create("FileQuit", "Quit juCi++"), Gtk::AccelKey(menu->key_map["quit"]), [this]() {
hide();
});
hide();
});
menu->action_group->add(Gtk::Action::create("FileNewFile", "New file"), Gtk::AccelKey(menu->key_map["new_file"]), [this]() {
new_file_entry();
});
new_file_entry();
});
menu->action_group->add(Gtk::Action::create("FileOpenFile", "Open file"), Gtk::AccelKey(menu->key_map["open_file"]), [this]() {
open_file_dialog();
});
open_file_dialog();
});
menu->action_group->add(Gtk::Action::create("FileOpenFolder", "Open folder"), Gtk::AccelKey(menu->key_map["open_folder"]), [this]() {
open_folder_dialog();
});
open_folder_dialog();
});
menu->action_group->add(Gtk::Action::create("FileSaveAs", "Save as"), Gtk::AccelKey(menu->key_map["save_as"]), [this]() {
save_file_dialog();
});
save_file_dialog();
});
menu->action_group->add(Gtk::Action::create("FileSave", "Save"), Gtk::AccelKey(menu->key_map["save"]), [this]() {
notebook.CurrentSourceView()->save();
});
notebook.save_current();
});
menu->action_group->add(Gtk::Action::create("EditCopy", "Copy"), Gtk::AccelKey(menu->key_map["edit_copy"]), [this]() {
auto widget=get_focus();
if(auto entry=dynamic_cast<Gtk::Entry*>(widget))
entry->copy_clipboard();
else if(auto text_view=dynamic_cast<Gtk::TextView*>(widget))
auto widget=get_focus();
if(auto entry=dynamic_cast<Gtk::Entry*>(widget))
entry->copy_clipboard();
else if(auto text_view=dynamic_cast<Gtk::TextView*>(widget))
text_view->get_buffer()->copy_clipboard(Gtk::Clipboard::get());
});
});
menu->action_group->add(Gtk::Action::create("EditCut", "Cut"), Gtk::AccelKey(menu->key_map["edit_cut"]), [this]() {
auto widget=get_focus();
if(auto entry=dynamic_cast<Gtk::Entry*>(widget))
entry->cut_clipboard();
else {
if (notebook.Pages() != 0)
notebook.CurrentSourceView()->get_buffer()->cut_clipboard(Gtk::Clipboard::get());
}
});
auto widget=get_focus();
if(auto entry=dynamic_cast<Gtk::Entry*>(widget))
entry->cut_clipboard();
else if(notebook.get_current_page()!=-1)
notebook.get_current_view()->get_buffer()->cut_clipboard(Gtk::Clipboard::get());
});
menu->action_group->add(Gtk::Action::create("EditPaste", "Paste"), Gtk::AccelKey(menu->key_map["edit_paste"]), [this]() {
auto widget=get_focus();
if(auto entry=dynamic_cast<Gtk::Entry*>(widget))
entry->paste_clipboard();
else {
if (notebook.Pages() != 0)
notebook.CurrentSourceView()->get_buffer()->paste_clipboard(Gtk::Clipboard::get());
}
});
auto widget=get_focus();
if(auto entry=dynamic_cast<Gtk::Entry*>(widget))
entry->paste_clipboard();
else if(notebook.get_current_page()!=-1)
notebook.get_current_view()->get_buffer()->paste_clipboard(Gtk::Clipboard::get());
});
menu->action_group->add(Gtk::Action::create("EditFind", "Find"), Gtk::AccelKey(menu->key_map["edit_find"]), [this]() {
search_and_replace_entry();
});
menu->action_group->add(Gtk::Action::create("SourceRename", "Rename function/variable"), Gtk::AccelKey(menu->key_map["source_rename"]), [this]() {
entry_box.clear();
if(notebook.CurrentPage()!=-1) {
if(notebook.CurrentSourceView()->get_token && notebook.CurrentSourceView()->get_token_name) {
auto token=std::make_shared<std::string>(notebook.CurrentSourceView()->get_token());
if(token->size()>0 && notebook.CurrentSourceView()->get_token_name) {
auto token_name=std::make_shared<std::string>(notebook.CurrentSourceView()->get_token_name());
for(int c=0;c<notebook.Pages();c++) {
if(notebook.source_views.at(c)->view->tag_similar_tokens) {
notebook.source_views.at(c)->view->tag_similar_tokens(*token);
}
search_and_replace_entry();
});
menu->action_group->add(Gtk::Action::create("EditUndo", "Undo"), Gtk::AccelKey(menu->key_map["edit_undo"]), [this]() {
INFO("On undo");
if(notebook.get_current_page()!=-1) {
auto undo_manager = notebook.get_current_view()->get_source_buffer()->get_undo_manager();
if (undo_manager->can_undo()) {
undo_manager->undo();
}
}
INFO("Done undo");
});
menu->action_group->add(Gtk::Action::create("EditRedo", "Redo"), Gtk::AccelKey(menu->key_map["edit_redo"]), [this]() {
INFO("On Redo");
if(notebook.get_current_page()!=-1) {
auto undo_manager = notebook.get_current_view()->get_source_buffer()->get_undo_manager();
if(undo_manager->can_redo()) {
undo_manager->redo();
}
}
INFO("Done Redo");
});
menu->action_group->add(Gtk::Action::create("SourceGotoDeclaration", "Go to declaration"), Gtk::AccelKey(menu->key_map["source_goto_declaration"]), [this]() {
if(notebook.get_current_page()!=-1) {
if(notebook.get_current_view()->get_declaration_location) {
auto location=notebook.get_current_view()->get_declaration_location();
if(location.first.size()>0) {
notebook.open(location.first);
notebook.get_current_view()->get_buffer()->place_cursor(notebook.get_current_view()->get_buffer()->get_iter_at_offset(location.second));
while(gtk_events_pending())
gtk_main_iteration();
notebook.get_current_view()->scroll_to(notebook.get_current_view()->get_buffer()->get_insert(), 0.0, 1.0, 0.5);
}
entry_box.labels.emplace_back();
auto label_it=entry_box.labels.begin();
label_it->update=[label_it](int state, const std::string& message){
label_it->set_text("Warning: only opened and parsed tabs will have its content renamed, and modified files will be saved.");
};
label_it->update(0, "");
entry_box.entries.emplace_back(*token_name, [this, token_name, token](const std::string& content){
if(notebook.CurrentPage()!=-1 && content!=*token_name) {
for(int c=0;c<notebook.Pages();c++) {
if(notebook.source_views.at(c)->view->rename_similar_tokens) {
auto number=notebook.source_views.at(c)->view->rename_similar_tokens(*token, content);
if(number>0) {
Singleton::terminal()->print("Replaced "+std::to_string(number)+" occurrences in file "+notebook.source_views.at(c)->view->file_path+"\n");
notebook.source_views.at(c)->view->save();
}
}
}
entry_box.hide();
}
});
auto entry_it=entry_box.entries.begin();
entry_box.buttons.emplace_back("Rename", [this, entry_it](){
entry_it->activate();
});
entry_box.show();
}
}
}
});
});
menu->action_group->add(Gtk::Action::create("SourceGotoMethod", "Go to method"), Gtk::AccelKey(menu->key_map["source_goto_method"]), [this]() {
if(notebook.get_current_page()!=-1) {
if(notebook.get_current_view()->goto_method) {
notebook.get_current_view()->goto_method();
}
}
});
menu->action_group->add(Gtk::Action::create("SourceRename", "Rename"), Gtk::AccelKey(menu->key_map["source_rename"]), [this]() {
rename_token_entry();
});
menu->action_group->add(Gtk::Action::create("ProjectCompileAndRun", "Compile And Run"), Gtk::AccelKey(menu->key_map["compile_and_run"]), [this]() {
if(notebook.CurrentPage()==-1)
return;
notebook.CurrentSourceView()->save();
if (running.try_lock()) {
std::thread execute([this]() {
std::string path = notebook.CurrentSourceView()->file_path;
size_t pos = path.find_last_of("/\\");
if(pos != std::string::npos) {
path.erase(path.begin()+pos,path.end());
Singleton::terminal()->SetFolderCommand(path);
}
Singleton::terminal()->Compile();
std::string executable = directories.GetCmakeVarValue(path,"add_executable");
Singleton::terminal()->Run(executable);
running.unlock();
});
execute.detach();
}
});
if(notebook.get_current_page()==-1)
return;
notebook.save_current();
if (running.try_lock()) {
std::thread execute([this]() {
std::string path = notebook.get_current_view()->file_path;
size_t pos = path.find_last_of("/\\");
if(pos != std::string::npos) {
path.erase(path.begin()+pos,path.end());
Singleton::terminal()->SetFolderCommand(path);
}
Singleton::terminal()->Compile();
std::string executable = directories.get_cmakelists_variable(path,"add_executable");
Singleton::terminal()->Run(executable);
running.unlock();
});
execute.detach();
}
});
menu->action_group->add(Gtk::Action::create("ProjectCompile", "Compile"), Gtk::AccelKey(menu->key_map["compile"]), [this]() {
if(notebook.CurrentPage()==-1)
return;
notebook.CurrentSourceView()->save();
if (running.try_lock()) {
std::thread execute([this]() {
std::string path = notebook.CurrentSourceView()->file_path;
size_t pos = path.find_last_of("/\\");
if(pos != std::string::npos){
path.erase(path.begin()+pos,path.end());
Singleton::terminal()->SetFolderCommand(path);
}
Singleton::terminal()->Compile();
running.unlock();
});
execute.detach();
}
});
INFO("Done adding actions to menu, building menu:")
if(notebook.get_current_page()==-1)
return;
notebook.save_current();
if (running.try_lock()) {
std::thread execute([this]() {
std::string path = notebook.get_current_view()->file_path;
size_t pos = path.find_last_of("/\\");
if(pos != std::string::npos){
path.erase(path.begin()+pos,path.end());
Singleton::terminal()->SetFolderCommand(path);
}
Singleton::terminal()->Compile();
running.unlock();
});
execute.detach();
}
});
menu->action_group->add(Gtk::Action::create("WindowCloseTab", "Close tab"), Gtk::AccelKey(menu->key_map["close_tab"]), [this]() {
notebook.close_current_page();
});
add_accel_group(menu->ui_manager->get_accel_group());
menu->build();
INFO("Menu build")
box.pack_start(menu->get_widget(), Gtk::PACK_SHRINK);
box.pack_start(entry_box, Gtk::PACK_SHRINK);
directory_and_notebook_panes.pack1(directories.widget(), true, true); //TODO: should be pack1(directories, ...) Clean up directories.*
directory_and_notebook_panes.pack2(notebook);
directory_and_notebook_panes.set_position(120);
vpaned.set_position(300);
vpaned.pack1(directory_and_notebook_panes, true, false);
vpaned.pack2(Singleton::terminal()->view, true, true);
box.pack_end(vpaned);
show_all_children();
entry_box.signal_show().connect([this](){
std::vector<Gtk::Widget*> focus_chain;
focus_chain.emplace_back(&entry_box);
box.set_focus_chain(focus_chain);
});
entry_box.signal_hide().connect([this](){
box.unset_focus_chain();
});
entry_box.signal_hide().connect([this]() {
if(notebook.CurrentPage()!=-1) {
notebook.CurrentSourceView()->grab_focus();
}
});
notebook.signal_switch_page().connect([this](Gtk::Widget* page, guint page_num) {
if(search_entry_shown && entry_box.labels.size()>0 && notebook.CurrentPage()!=-1) {
notebook.CurrentSourceView()->update_search_occurrences=[this](int number){
entry_box.labels.begin()->update(0, std::to_string(number));
};
notebook.CurrentSourceView()->search_highlight(last_search, case_sensitive_search, regex_search);
}
if(notebook.CurrentPage()!=-1) {
if(auto menu_item=dynamic_cast<Gtk::MenuItem*>(Singleton::menu()->ui_manager->get_widget("/MenuBar/SourceMenu/SourceGotoDeclaration")))
menu_item->set_sensitive((bool)notebook.CurrentSourceView()->get_declaration_location);
if(auto menu_item=dynamic_cast<Gtk::MenuItem*>(Singleton::menu()->ui_manager->get_widget("/MenuBar/SourceMenu/SourceGotoMethod")))
menu_item->set_sensitive((bool)notebook.CurrentSourceView()->goto_method);
if(auto menu_item=dynamic_cast<Gtk::MenuItem*>(Singleton::menu()->ui_manager->get_widget("/MenuBar/SourceMenu/SourceRename")))
menu_item->set_sensitive((bool)notebook.CurrentSourceView()->rename_similar_tokens);
}
});
INFO("Window created");
} // Window constructor
box.pack_start(menu->get_widget(), Gtk::PACK_SHRINK);
}
bool Window::on_key_press_event(GdkEventKey *event) {
if(event->keyval==GDK_KEY_Escape)
@ -246,8 +260,8 @@ bool Window::on_delete_event (GdkEventAny *event) {
}
void Window::hide() {
auto size=notebook.source_views.size();
for(size_t c=0;c<size;c++) {
auto size=notebook.size();
for(int c=0;c<size;c++) {
if(!notebook.close_current_page())
return;
}
@ -266,17 +280,11 @@ void Window::new_file_entry() {
Singleton::terminal()->print("Error: "+p.string()+" already exists.\n");
}
else {
std::ofstream f(p.string().c_str());
if(f) {
notebook.open_file(boost::filesystem::canonical(p).string());
Singleton::terminal()->print("New file "+p.string()+" created.\n");
if(notebook.project_path!="")
directories.open_folder(notebook.project_path); //TODO: Do refresh instead
}
else {
Singleton::terminal()->print("Error: could not create new file "+p.string()+".\n");
}
f.close();
juci::filesystem::save(p);
notebook.open(boost::filesystem::canonical(p).string());
Singleton::terminal()->print("New file "+p.string()+" created.\n");
if(notebook.project_path!="")
directories.open_folder(notebook.project_path); //TODO: Do refresh instead
}
}
entry_box.hide();
@ -310,7 +318,6 @@ void Window::open_file_dialog() {
Gtk::FileChooserDialog dialog("Please choose a file", Gtk::FILE_CHOOSER_ACTION_OPEN);
if(notebook.project_path.size()>0)
gtk_file_chooser_set_current_folder((GtkFileChooser*)dialog.gobj(), notebook.project_path.c_str());
std::cout << notebook.project_path << std::endl;
dialog.set_transient_for(*this);
dialog.set_position(Gtk::WindowPosition::WIN_POS_CENTER_ALWAYS);
@ -340,14 +347,16 @@ void Window::open_file_dialog() {
if(result==Gtk::RESPONSE_OK) {
std::string path = dialog.get_filename();
notebook.open_file(path);
notebook.open(path);
}
}
void Window::save_file_dialog() {
if(notebook.get_current_page()==-1)
return;
INFO("Save file dialog");
Gtk::FileChooserDialog dialog(*this, "Please choose a file", Gtk::FILE_CHOOSER_ACTION_SAVE);
gtk_file_chooser_set_filename((GtkFileChooser*)dialog.gobj(), notebook.CurrentSourceView()->file_path.c_str());
gtk_file_chooser_set_filename((GtkFileChooser*)dialog.gobj(), notebook.get_current_view()->file_path.c_str());
dialog.set_position(Gtk::WindowPosition::WIN_POS_CENTER_ALWAYS);
dialog.add_button("_Cancel", Gtk::RESPONSE_CANCEL);
dialog.add_button("_Save", Gtk::RESPONSE_OK);
@ -358,10 +367,10 @@ void Window::save_file_dialog() {
if(path.size()>0) {
std::ofstream file(path);
if(file) {
file << notebook.CurrentSourceView()->get_buffer()->get_text();
file << notebook.get_current_view()->get_buffer()->get_text();
file.close();
notebook.open_file(path);
Singleton::terminal()->print("File saved to: " + notebook.CurrentSourceView()->file_path+"\n");
notebook.open(path);
Singleton::terminal()->print("File saved to: " + notebook.get_current_view()->file_path+"\n");
if(notebook.project_path!="")
directories.open_folder(notebook.project_path); //TODO: Do refresh instead
}
@ -371,27 +380,6 @@ void Window::save_file_dialog() {
}
}
//TODO: move most of it to Directories
void Window::on_directory_navigation(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column) {
INFO("Directory navigation");
Gtk::TreeModel::iterator iter = directories.m_refTreeModel->get_iter(path);
if (iter) {
Gtk::TreeModel::Row row = *iter;
std::string upath = Glib::ustring(row[directories.view().m_col_path]);
boost::filesystem::path fs_path(upath);
if (boost::filesystem::is_directory(fs_path)) {
directories.m_TreeView.row_expanded(path) ?
directories.m_TreeView.collapse_row(path) :
directories.m_TreeView.expand_row(path, false);
} else {
std::stringstream sstm;
sstm << row[directories.view().m_col_path];
std::string file = sstm.str();
notebook.open_file(file);
}
}
}
void Window::search_and_replace_entry() {
entry_box.clear();
entry_box.labels.emplace_back();
@ -408,81 +396,123 @@ void Window::search_and_replace_entry() {
}
};
entry_box.entries.emplace_back(last_search, [this](const std::string& content){
if(notebook.CurrentPage()!=-1)
notebook.CurrentSourceView()->search_forward();
});
if(notebook.get_current_page()!=-1)
notebook.get_current_view()->search_forward();
});
auto search_entry_it=entry_box.entries.begin();
search_entry_it->set_placeholder_text("Find");
if(notebook.CurrentPage()!=-1) {
notebook.CurrentSourceView()->update_search_occurrences=[label_it](int number){
if(notebook.get_current_page()!=-1) {
notebook.get_current_view()->update_search_occurrences=[label_it](int number){
label_it->update(0, std::to_string(number));
};
notebook.CurrentSourceView()->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search);
notebook.get_current_view()->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search);
}
search_entry_it->signal_key_press_event().connect([this](GdkEventKey* event){
if(event->keyval==GDK_KEY_Return && event->state==GDK_SHIFT_MASK) {
if(notebook.CurrentPage()!=-1)
notebook.CurrentSourceView()->search_backward();
}
return false;
});
if(event->keyval==GDK_KEY_Return && event->state==GDK_SHIFT_MASK) {
if(notebook.get_current_page()!=-1)
notebook.get_current_view()->search_backward();
}
return false;
});
search_entry_it->signal_changed().connect([this, search_entry_it](){
last_search=search_entry_it->get_text();
if(notebook.CurrentPage()!=-1)
notebook.CurrentSourceView()->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search);
});
last_search=search_entry_it->get_text();
if(notebook.get_current_page()!=-1)
notebook.get_current_view()->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search);
});
entry_box.entries.emplace_back(last_replace, [this](const std::string &content){
if(notebook.CurrentPage()!=-1)
notebook.CurrentSourceView()->replace_forward(content);
});
if(notebook.get_current_page()!=-1)
notebook.get_current_view()->replace_forward(content);
});
auto replace_entry_it=entry_box.entries.begin();
replace_entry_it++;
replace_entry_it->set_placeholder_text("Replace");
replace_entry_it->signal_key_press_event().connect([this, replace_entry_it](GdkEventKey* event){
if(event->keyval==GDK_KEY_Return && event->state==GDK_SHIFT_MASK) {
if(notebook.CurrentPage()!=-1)
notebook.CurrentSourceView()->replace_backward(replace_entry_it->get_text());
}
return false;
});
if(event->keyval==GDK_KEY_Return && event->state==GDK_SHIFT_MASK) {
if(notebook.get_current_page()!=-1)
notebook.get_current_view()->replace_backward(replace_entry_it->get_text());
}
return false;
});
replace_entry_it->signal_changed().connect([this, replace_entry_it](){
last_replace=replace_entry_it->get_text();
});
last_replace=replace_entry_it->get_text();
});
entry_box.buttons.emplace_back("Find", [this](){
if(notebook.CurrentPage()!=-1)
notebook.CurrentSourceView()->search_forward();
});
if(notebook.get_current_page()!=-1)
notebook.get_current_view()->search_forward();
});
entry_box.buttons.emplace_back("Replace", [this, replace_entry_it](){
if(notebook.CurrentPage()!=-1)
notebook.CurrentSourceView()->replace_forward(replace_entry_it->get_text());
});
if(notebook.get_current_page()!=-1)
notebook.get_current_view()->replace_forward(replace_entry_it->get_text());
});
entry_box.buttons.emplace_back("Replace all", [this, replace_entry_it](){
if(notebook.CurrentPage()!=-1)
notebook.CurrentSourceView()->replace_all(replace_entry_it->get_text());
});
if(notebook.get_current_page()!=-1)
notebook.get_current_view()->replace_all(replace_entry_it->get_text());
});
entry_box.toggle_buttons.emplace_back("Match case");
entry_box.toggle_buttons.back().set_active(case_sensitive_search);
entry_box.toggle_buttons.back().on_activate=[this, search_entry_it](){
case_sensitive_search=!case_sensitive_search;
if(notebook.CurrentPage()!=-1)
notebook.CurrentSourceView()->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search);
if(notebook.get_current_page()!=-1)
notebook.get_current_view()->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search);
};
entry_box.toggle_buttons.emplace_back("Use regex");
entry_box.toggle_buttons.back().set_active(regex_search);
entry_box.toggle_buttons.back().on_activate=[this, search_entry_it](){
regex_search=!regex_search;
if(notebook.CurrentPage()!=-1)
notebook.CurrentSourceView()->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search);
if(notebook.get_current_page()!=-1)
notebook.get_current_view()->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search);
};
entry_box.signal_hide().connect([this]() {
for(int c=0;c<notebook.Pages();c++) {
notebook.source_views.at(c)->view->update_search_occurrences=nullptr;
notebook.source_views.at(c)->view->search_highlight("", case_sensitive_search, regex_search);
}
search_entry_shown=false;
});
for(int c=0;c<notebook.size();c++) {
notebook.get_view(c)->update_search_occurrences=nullptr;
notebook.get_view(c)->search_highlight("", case_sensitive_search, regex_search);
}
search_entry_shown=false;
});
search_entry_shown=true;
entry_box.show();
}
void Window::rename_token_entry() {
entry_box.clear();
if(notebook.get_current_page()!=-1) {
if(notebook.get_current_view()->get_token && notebook.get_current_view()->get_token_name) {
auto token=std::make_shared<std::string>(notebook.get_current_view()->get_token());
if(token->size()>0 && notebook.get_current_view()->get_token_name) {
auto token_name=std::make_shared<std::string>(notebook.get_current_view()->get_token_name());
for(int c=0;c<notebook.size();c++) {
if(notebook.get_view(c)->tag_similar_tokens) {
notebook.get_view(c)->tag_similar_tokens(*token);
}
}
entry_box.labels.emplace_back();
auto label_it=entry_box.labels.begin();
label_it->update=[label_it](int state, const std::string& message){
label_it->set_text("Warning: only opened and parsed tabs will have its content renamed, and modified files will be saved.");
};
label_it->update(0, "");
entry_box.entries.emplace_back(*token_name, [this, token_name, token](const std::string& content){
if(notebook.get_current_page()!=-1 && content!=*token_name) {
for(int c=0;c<notebook.size();c++) {
if(notebook.get_view(c)->rename_similar_tokens) {
auto number=notebook.get_view(c)->rename_similar_tokens(*token, content);
if(number>0) {
Singleton::terminal()->print("Replaced "+std::to_string(number)+" occurrences in file "+notebook.get_view(c)->file_path+"\n");
notebook.save(c);
}
}
}
entry_box.hide();
}
});
auto entry_it=entry_box.entries.begin();
entry_box.buttons.emplace_back("Rename", [this, entry_it](){
entry_it->activate();
});
entry_box.show();
}
}
}
}

11
src/window.h

@ -1,15 +1,16 @@
#ifndef JUCI_WINDOW_H_
#define JUCI_WINDOW_H_
#include "api.h"
#include <cstddef>
#include "directories.h"
#include "entrybox.h"
#include "notebook.h"
class Window : public Gtk::Window {
public:
Window();
Notebook notebook;
Directories::Controller directories;
Directories directories;
protected:
bool on_key_press_event(GdkEventKey *event);
bool on_delete_event (GdkEventAny *event);
@ -18,17 +19,17 @@ private:
Gtk::VPaned vpaned;
Gtk::Paned directory_and_notebook_panes;
EntryBox entry_box;
PluginApi plugin_api;
std::mutex running;
void add_menu();
void hide();
void new_file_entry();
void open_folder_dialog();
void open_file_dialog();
void save_file_dialog();
void on_directory_navigation(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column);
void search_and_replace_entry();
void rename_token_entry();
std::string last_search;
std::string last_replace;
bool case_sensitive_search=true;

Loading…
Cancel
Save