@@ -63,8 +63,10 @@ bool Directories::TreeStore::drag_data_received_vfunc(const TreeModel::Path &pat
6363 auto it=directories.get_selection ()->get_selected ();
6464 if (it) {
6565 auto source_path=it->get_value (directories.column_record .path );
66- auto target_path=get_target_folder (path);
66+ if (source_path.empty ())
67+ return false ;
6768
69+ auto target_path=get_target_folder (path);
6870 target_path/=source_path.filename ();
6971
7072 if (source_path==target_path)
@@ -109,6 +111,7 @@ bool Directories::TreeStore::drag_data_received_vfunc(const TreeModel::Path &pat
109111 directories.select (target_path);
110112 }
111113
114+ EntryBox::get ().hide ();
112115 return false ;
113116}
114117
@@ -205,6 +208,94 @@ Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) {
205208 enable_model_drag_source ();
206209 enable_model_drag_dest ();
207210
211+ auto new_file_label = " New File" ;
212+ auto new_file_function = [this ] {
213+ if (menu_popup_row_path.empty ())
214+ return ;
215+ EntryBox::get ().clear ();
216+ auto source_path=std::make_shared<boost::filesystem::path>(menu_popup_row_path);
217+ EntryBox::get ().entries .emplace_back (" " , [this , source_path](const std::string &content) {
218+ bool is_directory=boost::filesystem::is_directory (*source_path);
219+ auto target_path = (is_directory ? *source_path : source_path->parent_path ())/content;
220+ if (!boost::filesystem::exists (target_path)) {
221+ if (filesystem::write (target_path, " " )) {
222+ update ();
223+ Notebook::get ().open (target_path);
224+ }
225+ else {
226+ Terminal::get ().print (" Error: could not create " +target_path.string ()+' \n ' , true );
227+ return ;
228+ }
229+ }
230+ else {
231+ Terminal::get ().print (" Error: could not create " +target_path.string ()+" : already exists\n " , true );
232+ return ;
233+ }
234+
235+ EntryBox::get ().hide ();
236+ });
237+ auto entry_it=EntryBox::get ().entries .begin ();
238+ entry_it->set_placeholder_text (" Filename" );
239+ EntryBox::get ().buttons .emplace_back (" Create New File" , [this , entry_it](){
240+ entry_it->activate ();
241+ });
242+ EntryBox::get ().show ();
243+ };
244+
245+ menu_item_new_file.set_label (new_file_label);
246+ menu_item_new_file.signal_activate ().connect (new_file_function);
247+ menu.append (menu_item_new_file);
248+
249+ menu_root_item_new_file.set_label (new_file_label);
250+ menu_root_item_new_file.signal_activate ().connect (new_file_function);
251+ menu_root.append (menu_root_item_new_file);
252+
253+ auto new_folder_label = " New Folder" ;
254+ auto new_folder_function = [this ] {
255+ if (menu_popup_row_path.empty ())
256+ return ;
257+ EntryBox::get ().clear ();
258+ auto source_path=std::make_shared<boost::filesystem::path>(menu_popup_row_path);
259+ EntryBox::get ().entries .emplace_back (" " , [this , source_path](const std::string &content) {
260+ bool is_directory=boost::filesystem::is_directory (*source_path);
261+ auto target_path = (is_directory ? *source_path : source_path->parent_path ())/content;
262+ if (!boost::filesystem::exists (target_path)) {
263+ boost::system::error_code ec;
264+ boost::filesystem::create_directory (target_path, ec);
265+ if (!ec) {
266+ update ();
267+ select (target_path);
268+ }
269+ else {
270+ Terminal::get ().print (" Error: could not create " +target_path.string ()+" : " +ec.message (), true );
271+ return ;
272+ }
273+ }
274+ else {
275+ Terminal::get ().print (" Error: could not create " +target_path.string ()+" : already exists\n " , true );
276+ return ;
277+ }
278+
279+ EntryBox::get ().hide ();
280+ });
281+ auto entry_it=EntryBox::get ().entries .begin ();
282+ entry_it->set_placeholder_text (" Folder name" );
283+ EntryBox::get ().buttons .emplace_back (" Create New Folder" , [this , entry_it](){
284+ entry_it->activate ();
285+ });
286+ EntryBox::get ().show ();
287+ };
288+
289+ menu_item_new_folder.set_label (new_folder_label);
290+ menu_item_new_folder.signal_activate ().connect (new_folder_function);
291+ menu.append (menu_item_new_folder);
292+
293+ menu_root_item_new_folder.set_label (new_folder_label);
294+ menu_root_item_new_folder.signal_activate ().connect (new_folder_function);
295+ menu_root.append (menu_root_item_new_folder);
296+
297+ menu.append (menu_item_separator);
298+
208299 menu_item_rename.set_label (" Rename" );
209300 menu_item_rename.signal_activate ().connect ([this ] {
210301 if (menu_popup_row_path.empty ())
@@ -214,46 +305,53 @@ Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) {
214305 EntryBox::get ().entries .emplace_back (menu_popup_row_path.filename ().string (), [this , source_path](const std::string &content){
215306 bool is_directory=boost::filesystem::is_directory (*source_path);
216307
217- boost::system::error_code ec;
218308 auto target_path=source_path->parent_path ()/content;
309+
310+ if (boost::filesystem::exists (target_path)) {
311+ Terminal::get ().print (" Error: could not rename to " +target_path.string ()+" : already exists\n " , true );
312+ return ;
313+ }
314+
315+ boost::system::error_code ec;
219316 boost::filesystem::rename (*source_path, target_path, ec);
220- if (ec)
221- Terminal::get ().print (" Error: could not rename " +source_path->string ()+" : " +ec.message ()+' \n ' );
222- else {
223- update ();
224- select (target_path);
225-
226- for (int c=0 ;c<Notebook::get ().size ();c++) {
227- auto view=Notebook::get ().get_view (c);
228- if (is_directory) {
229- if (filesystem::file_in_path (view->file_path , *source_path)) {
230- auto file_it=view->file_path .begin ();
231- for (auto source_it=source_path->begin ();source_it!=source_path->end ();source_it++)
232- file_it++;
233- auto new_file_path=target_path;
234- for (;file_it!=view->file_path .end ();file_it++)
235- new_file_path/=*file_it;
236- view->file_path =new_file_path;
237- }
238- }
239- else if (view->file_path ==*source_path) {
240- view->file_path =target_path;
317+ if (ec) {
318+ Terminal::get ().print (" Error: could not rename " +source_path->string ()+" : " +ec.message ()+' \n ' , true );
319+ return ;
320+ }
321+ update ();
322+ select (target_path);
323+
324+ for (int c=0 ;c<Notebook::get ().size ();c++) {
325+ auto view=Notebook::get ().get_view (c);
326+ if (is_directory) {
327+ if (filesystem::file_in_path (view->file_path , *source_path)) {
328+ auto file_it=view->file_path .begin ();
329+ for (auto source_it=source_path->begin ();source_it!=source_path->end ();source_it++)
330+ file_it++;
331+ auto new_file_path=target_path;
332+ for (;file_it!=view->file_path .end ();file_it++)
333+ new_file_path/=*file_it;
334+ view->file_path =new_file_path;
241335 g_signal_emit_by_name (view->get_buffer ()->gobj (), " modified_changed" );
242-
243- std::string old_language_id;
244- if (view->language )
245- old_language_id=view->language ->get_id ();
246- view->language =Source::guess_language (target_path);
247- std::string new_language_id;
248- if (view->language )
249- new_language_id=view->language ->get_id ();
250- if (new_language_id!=old_language_id)
251- Terminal::get ().print (" Warning: language for " +target_path.string ()+" has changed. Please reopen the file\n " );
252336 }
253337 }
254-
255- EntryBox::get ().hide ();
338+ else if (view->file_path ==*source_path) {
339+ view->file_path =target_path;
340+ g_signal_emit_by_name (view->get_buffer ()->gobj (), " modified_changed" );
341+
342+ std::string old_language_id;
343+ if (view->language )
344+ old_language_id=view->language ->get_id ();
345+ view->language =Source::guess_language (target_path);
346+ std::string new_language_id;
347+ if (view->language )
348+ new_language_id=view->language ->get_id ();
349+ if (new_language_id!=old_language_id)
350+ Terminal::get ().print (" Warning: language for " +target_path.string ()+" has changed. Please reopen the file\n " );
351+ }
256352 }
353+
354+ EntryBox::get ().hide ();
257355 });
258356 auto entry_it=EntryBox::get ().entries .begin ();
259357 entry_it->set_placeholder_text (" Filename" );
@@ -299,6 +397,22 @@ Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) {
299397
300398 menu.show_all ();
301399 menu.accelerate (*this );
400+
401+ menu_root.show_all ();
402+ menu_root.accelerate (*this );
403+
404+ set_headers_clickable ();
405+ forall ([this ](Gtk::Widget &widget) {
406+ if (widget.get_name ()==" GtkButton" ) {
407+ widget.signal_button_press_event ().connect ([this ](GdkEventButton *event) {
408+ if (event->type ==GDK_BUTTON_PRESS && event->button ==GDK_BUTTON_SECONDARY && !path.empty ()) {
409+ menu_popup_row_path=this ->path ;
410+ menu_root.popup (event->button , event->time );
411+ }
412+ return true ;
413+ });
414+ }
415+ });
302416}
303417
304418Directories::~Directories () {
@@ -394,12 +508,28 @@ void Directories::select(const boost::filesystem::path &select_path) {
394508
395509bool Directories::on_button_press_event (GdkEventButton* event) {
396510 if (event->type ==GDK_BUTTON_PRESS && event->button ==GDK_BUTTON_SECONDARY) {
511+ EntryBox::get ().hide ();
397512 Gtk::TreeModel::Path path;
398513 if (get_path_at_pos (static_cast <int >(event->x ), static_cast <int >(event->y ), path)) {
399514 menu_popup_row_path=get_model ()->get_iter (path)->get_value (column_record.path );
515+ if (menu_popup_row_path.empty ()) {
516+ auto parent=get_model ()->get_iter (path)->parent ();
517+ if (parent)
518+ menu_popup_row_path=parent->get_value (column_record.path );
519+ else {
520+ menu_popup_row_path=this ->path ;
521+ menu_root.popup (event->button , event->time );
522+ return true ;
523+ }
524+ }
400525 menu.popup (event->button , event->time );
401526 return true ;
402527 }
528+ else if (!this ->path .empty ()) {
529+ menu_popup_row_path=this ->path ;
530+ menu_root.popup (event->button , event->time );
531+ return true ;
532+ }
403533 }
404534
405535 return Gtk::TreeView::on_button_press_event (event);
0 commit comments