Rationalize gtk box packing.
[ardour.git] / gtk2_ardour / session_dialog.cc
index fe8a1bdd4c4bfe204e48cd0db389b76eb81a0050..8bad1d5ab23a1bb066bf8054f777c045734aa4a5 100644 (file)
@@ -30,6 +30,7 @@
 #include <glibmm/datetime.h>
 
 #include <gtkmm/filechooser.h>
+#include <gtkmm/stock.h>
 
 #include "pbd/basename.h"
 #include "pbd/failed_constructor.h"
 #include "pbd/openuri.h"
 
 #include "gtkmm2ext/utils.h"
+#include "gtkmm2ext/keyboard.h"
+
+#include "widgets/tooltips.h"
 
 #include "ardour/audioengine.h"
 #include "ardour/filesystem_paths.h"
+#include "ardour/luascripting.h"
 #include "ardour/recent_sessions.h"
 #include "ardour/session.h"
 #include "ardour/session_state_utils.h"
@@ -54,8 +59,7 @@
 #include "session_dialog.h"
 #include "opts.h"
 #include "engine_dialog.h"
-#include "i18n.h"
-#include "tooltips.h"
+#include "pbd/i18n.h"
 #include "ui_config.h"
 #include "utils.h"
 
@@ -65,6 +69,7 @@ using namespace Gdk;
 using namespace Glib;
 using namespace PBD;
 using namespace ARDOUR;
+using namespace ArdourWidgets;
 using namespace ARDOUR_UI_UTILS;
 
 SessionDialog::SessionDialog (bool require_new, const std::string& session_name, const std::string& session_path, const std::string& template_name, bool cancel_not_quit)
@@ -87,6 +92,7 @@ SessionDialog::SessionDialog (bool require_new, const std::string& session_name,
        open_button = add_button (Stock::OPEN, RESPONSE_ACCEPT);
 
        back_button->signal_button_press_event().connect (sigc::mem_fun (*this, &SessionDialog::back_button_pressed), false);
+       open_button->signal_button_press_event().connect (sigc::mem_fun (*this, &SessionDialog::open_button_pressed), false);
 
        open_button->set_sensitive (false);
        back_button->set_sensitive (false);
@@ -110,7 +116,6 @@ SessionDialog::SessionDialog (bool require_new, const std::string& session_name,
        }
 
        if (!template_name.empty()) {
-               use_template_button.set_active (false);
                load_template_override = template_name;
        }
 
@@ -120,14 +125,6 @@ SessionDialog::SessionDialog (bool require_new, const std::string& session_name,
 
        populate_session_templates ();
 
-       if (!template_model->children().empty()) {
-               use_template_button.show();
-               template_chooser.show ();
-       } else {
-               use_template_button.hide();
-               template_chooser.hide ();
-       }
-
        if (recent_session_model) {
                int cnt = redisplay_recent_sessions ();
                if (cnt > 0) {
@@ -212,7 +209,7 @@ SessionDialog::use_session_template ()
                return true;
        }
 
-       if (use_template_button.get_active()) {
+       if (template_chooser.get_selection()->count_selected_rows() > 0) {
                return true;
        }
 
@@ -227,11 +224,13 @@ SessionDialog::session_template_name ()
                return Glib::build_filename (the_path, load_template_override + ARDOUR::template_suffix);
        }
 
-       if (use_template_button.get_active()) {
-               TreeModel::iterator iter = template_chooser.get_active ();
-               TreeModel::Row row = (*iter);
-               string s = row[session_template_columns.path];
-               return s;
+       if (template_chooser.get_selection()->count_selected_rows() > 0) {
+               TreeIter iter = template_chooser.get_selection()->get_selected();
+
+               if (iter) {
+                       string s = (*iter)[session_template_columns.path];
+                       return s;
+               }
        }
 
        return string();
@@ -322,6 +321,7 @@ SessionDialog::setup_recent_sessions ()
 
        recent_session_display.show();
        recent_session_display.signal_row_activated().connect (sigc::mem_fun (*this, &SessionDialog::recent_row_activated));
+       recent_session_display.signal_button_press_event().connect (sigc::mem_fun (*this, &SessionDialog::recent_button_press), false);
 }
 
 void
@@ -409,6 +409,12 @@ SessionDialog::setup_initial_choice_box ()
        session_filter.add_pattern (string_compose(X_("*%1"), ARDOUR::statefile_suffix));
        session_filter.set_name (string_compose (_("%1 sessions"), PROGRAM_NAME));
        existing_session_chooser.add_filter (session_filter);
+
+       FileFilter archive_filter;
+       archive_filter.add_pattern (X_("*.tar.xz"));
+       archive_filter.set_name (_("Session Archives"));
+       existing_session_chooser.add_filter (archive_filter);
+
        existing_session_chooser.set_filter (session_filter);
 
        Gtkmm2ext::add_volume_shortcuts (existing_session_chooser);
@@ -478,15 +484,38 @@ SessionDialog::back_button_pressed (GdkEventButton*)
        return true;
 }
 
+bool
+SessionDialog::open_button_pressed (GdkEventButton* ev)
+{
+       if (Gtkmm2ext::Keyboard::modifier_state_equals (ev->state, Gtkmm2ext::Keyboard::PrimaryModifier)) {
+               _disable_plugins.set_active();
+       }
+       response (RESPONSE_ACCEPT);
+       return true;
+}
+
 void
 SessionDialog::populate_session_templates ()
 {
        vector<TemplateInfo> templates;
 
-       find_session_templates (templates);
+       find_session_templates (templates, true);
 
        template_model->clear ();
 
+    //Add any Lua scripts (factory templates) found in the scripts folder
+       LuaScriptList& ms (LuaScripting::instance ().scripts (LuaScriptInfo::SessionSetup));
+       for (LuaScriptList::const_iterator s = ms.begin(); s != ms.end(); ++s) {
+               TreeModel::Row row;
+               row = *(template_model->append ());
+               row[session_template_columns.name] = "Meta: " + (*s)->name;
+               row[session_template_columns.path] = "urn:ardour:" + (*s)->path;
+               row[session_template_columns.description] = (*s)->description;
+        row[session_template_columns.created_with] = _("{Factory Template}");
+       }
+
+
+    //Add any "template sessions" found in the user's preferences folder
        for (vector<TemplateInfo>::iterator x = templates.begin(); x != templates.end(); ++x) {
                TreeModel::Row row;
 
@@ -494,31 +523,38 @@ SessionDialog::populate_session_templates ()
 
                row[session_template_columns.name] = (*x).name;
                row[session_template_columns.path] = (*x).path;
+        row[session_template_columns.description] = (*x).description;
+        row[session_template_columns.created_with] = (*x).created_with;
        }
-
-       if (!templates.empty()) {
-               /* select first row */
-               template_chooser.set_active (0);
-       }
+    
+    //Add an explicit 'Empty Template' item
+       TreeModel::Row row = *template_model->prepend ();
+       row[session_template_columns.name] = (_("Empty Template"));
+       row[session_template_columns.path] = string();
+    row[session_template_columns.description] = _("An empty session with factory default settings.");
+    row[session_template_columns.created_with] = _("{Factory Template}");
+
+    //auto-select the first item in the list
+    Gtk::TreeModel::Row first = template_model->children()[0];
+    if(first) {
+        template_chooser.get_selection()->select(first);
+    }
 }
 
 void
 SessionDialog::setup_new_session_page ()
 {
-       session_new_vbox.set_border_width (12);
-       session_new_vbox.set_spacing (18);
-
-       VBox *vbox1 = manage (new VBox);
-       HBox* hbox1 = manage (new HBox);
-       Label* label1 = manage (new Label);
+       session_new_vbox.set_border_width (8);
+       session_new_vbox.set_spacing (8);
 
-       vbox1->set_spacing (6);
+    Label* name_label = manage (new Label);
+       name_label->set_text (_("Session name:"));
 
-       hbox1->set_spacing (6);
-       hbox1->pack_start (*label1, false, false);
-       hbox1->pack_start (new_name_entry, true, true);
+       HBox* name_hbox = manage (new HBox);
+    name_hbox->set_spacing (6);
 
-       label1->set_text (_("Session name:"));
+       name_hbox->pack_start (*name_label, false, false);
+       name_hbox->pack_start (new_name_entry, true, true);
 
        if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
                new_name_entry.set_text  (Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name));
@@ -529,16 +565,14 @@ SessionDialog::setup_new_session_page ()
        new_name_entry.signal_changed().connect (sigc::mem_fun (*this, &SessionDialog::new_name_changed));
        new_name_entry.signal_activate().connect (sigc::mem_fun (*this, &SessionDialog::new_name_activated));
 
-       vbox1->pack_start (*hbox1, true, true);
-
        /* --- */
 
-       HBox* hbox2 = manage (new HBox);
+       HBox* folder_box = manage (new HBox);
        Label* label2 = manage (new Label);
 
-       hbox2->set_spacing (6);
-       hbox2->pack_start (*label2, false, false);
-       hbox2->pack_start (new_folder_chooser, true, true);
+       folder_box->set_spacing (6);
+       folder_box->pack_start (*label2, false, false);
+       folder_box->pack_start (new_folder_chooser, true, true);
 
        label2->set_text (_("Create session folder in:"));
 
@@ -565,67 +599,45 @@ SessionDialog::setup_new_session_page ()
 
        Gtkmm2ext::add_volume_shortcuts (new_folder_chooser);
 
-       vbox1->pack_start (*hbox2, false, false);
-
-       session_new_vbox.pack_start (*vbox1, false, false);
-
        /* --- */
 
-       VBox *vbox2 = manage (new VBox);
-       HBox* hbox3 = manage (new HBox);
-       template_model = ListStore::create (session_template_columns);
-
-       vbox2->set_spacing (6);
+       template_model = TreeStore::create (session_template_columns);
 
-       VBox *vbox3 = manage (new VBox);
+       HBox* template_hbox = manage (new HBox);
 
-       vbox3->set_spacing (6);
-
-       /* we may want to hide this and show it at various
-          times depending on the existence of templates.
-       */
-       template_chooser.set_no_show_all (true);
-       use_template_button.set_no_show_all (true);
-
-       HBox* hbox4a = manage (new HBox);
-       use_template_button.set_label (_("Use this template"));
-
-       TreeModel::Row row = *template_model->prepend ();
-       row[session_template_columns.name] = (_("no template"));
-       row[session_template_columns.path] = string();
-
-       hbox4a->set_spacing (6);
-       hbox4a->pack_start (use_template_button, false, false);
-       hbox4a->pack_start (template_chooser, true, true);
+    //if the "template override" is provided, don't give the user any template selections   (?)
+       if ( load_template_override.empty() ) {
+        template_hbox->set_spacing (6);
+        template_hbox->pack_start (template_chooser, false, false);
+        template_hbox->pack_start (template_desc, true, true);
+    }
+    
+       template_desc.set_editable (false);
+       template_desc.set_wrap_mode (Gtk::WRAP_WORD);
+       template_desc.set_size_request(300,400);
+       template_desc.set_left_margin(6);
+       template_desc.set_right_margin(6);
 
        template_chooser.set_model (template_model);
-
-       Gtk::CellRendererText* text_renderer = Gtk::manage (new Gtk::CellRendererText);
-       text_renderer->property_editable() = false;
-
-       template_chooser.pack_start (*text_renderer);
-       template_chooser.add_attribute (text_renderer->property_text(), session_template_columns.name);
-       template_chooser.set_active (0);
-
-       vbox3->pack_start (*hbox4a, false, false);
+       template_chooser.set_size_request(300,400);
+       template_chooser.append_column (_("Template"), session_template_columns.name);
+       template_chooser.append_column (_("Created With"), session_template_columns.created_with);
+       template_chooser.set_headers_visible (true);
+       template_chooser.get_selection()->set_mode (SELECTION_SINGLE);
+       template_chooser.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &SessionDialog::template_row_selected));
+       template_chooser.set_sensitive (true);
 
        /* --- */
 
-       HBox* hbox5 = manage (new HBox);
-
-       hbox5->set_spacing (6);
-       hbox5->pack_start (more_new_session_options_button, false, false);
-
        setup_more_options_box ();
        more_new_session_options_button.add (more_options_vbox);
 
-       vbox3->pack_start (*hbox5, false, false);
-       hbox3->pack_start (*vbox3, true, true, 8);
-       vbox2->pack_start (*hbox3, false, false);
-
        /* --- */
 
-       session_new_vbox.pack_start (*vbox2, false, false);
+       session_new_vbox.pack_start (*name_hbox, true, true);
+       session_new_vbox.pack_start (*folder_box, true, true);
+       session_new_vbox.pack_start (*template_hbox, false, false);
+       session_new_vbox.pack_start (more_new_session_options_button, false, false);
        session_new_vbox.show_all ();
 }
 
@@ -715,6 +727,7 @@ SessionDialog::redisplay_recent_sessions ()
 
                float sr;
                SampleFormat sf;
+               std::string program_version;
 
                std::string state_file_basename;
 
@@ -736,10 +749,9 @@ SessionDialog::redisplay_recent_sessions ()
                g_stat (s.c_str(), &gsb);
 
                row[recent_session_columns.fullpath] = s;
-               row[recent_session_columns.tip] = Gtkmm2ext::markup_escape_text (dirname);
                row[recent_session_columns.time_modified] = gsb.st_mtime;
 
-               if (Session::get_info_from_path (s, sr, sf) == 0) {
+               if (Session::get_info_from_path (s, sr, sf, program_version) == 0) {
                        row[recent_session_columns.sample_rate] = rate_as_string (sr);
                        switch (sf) {
                        case FormatFloat:
@@ -757,6 +769,12 @@ SessionDialog::redisplay_recent_sessions ()
                        row[recent_session_columns.disk_format] = "--";
                }
 
+               if (program_version.empty()) {
+                       row[recent_session_columns.tip] = Gtkmm2ext::markup_escape_text (dirname);
+               } else {
+                       row[recent_session_columns.tip] = Gtkmm2ext::markup_escape_text (dirname + "\n" + string_compose (_("Last modified with: %1"), program_version));
+               }
+
                ++session_snapshot_count;
 
                if (state_file_names.size() > 1) {
@@ -768,6 +786,7 @@ SessionDialog::redisplay_recent_sessions ()
                        int64_t most_recent = 0;
 
                        // add the children
+                       int kidcount = 0;
                        for (std::vector<std::string>::iterator i2 = state_file_names.begin(); i2 != state_file_names.end(); ++i2) {
 
                                s = Glib::build_filename (dirname, *i2 + statefile_suffix);
@@ -786,22 +805,36 @@ SessionDialog::redisplay_recent_sessions ()
                                        most_recent = gsb.st_mtime;
                                }
 
-                               if (Session::get_info_from_path (s, sr, sf) == 0) {
-                                       child_row[recent_session_columns.sample_rate] = rate_as_string (sr);
-                                       switch (sf) {
-                                       case FormatFloat:
-                                               child_row[recent_session_columns.disk_format] = _("32-bit float");
-                                               break;
-                                       case FormatInt24:
-                                               child_row[recent_session_columns.disk_format] = _("24-bit");
-                                               break;
-                                       case FormatInt16:
-                                               child_row[recent_session_columns.disk_format] = _("16-bit");
-                                               break;
+                               if (++kidcount < 5) {
+                                       // parse "modified with" for the first 5 snapshots
+                                       if (Session::get_info_from_path (s, sr, sf, program_version) == 0) {
+#if 0
+                                               child_row[recent_session_columns.sample_rate] = rate_as_string (sr);
+                                               switch (sf) {
+                                                       case FormatFloat:
+                                                               child_row[recent_session_columns.disk_format] = _("32-bit float");
+                                                               break;
+                                                       case FormatInt24:
+                                                               child_row[recent_session_columns.disk_format] = _("24-bit");
+                                                               break;
+                                                       case FormatInt16:
+                                                               child_row[recent_session_columns.disk_format] = _("16-bit");
+                                                               break;
+                                               }
+#else
+                                               child_row[recent_session_columns.sample_rate] = "";
+                                               child_row[recent_session_columns.disk_format] = "";
+#endif
+                                       } else {
+                                               child_row[recent_session_columns.sample_rate] = "??";
+                                               child_row[recent_session_columns.disk_format] = "--";
+                                       }
+                                       if (!program_version.empty()) {
+                                               child_row[recent_session_columns.tip] = Gtkmm2ext::markup_escape_text (string_compose (_("Last modified with: %1"), program_version));
                                        }
                                } else {
-                                       child_row[recent_session_columns.sample_rate] = "??";
-                                       child_row[recent_session_columns.disk_format] = "--";
+                                       child_row[recent_session_columns.sample_rate] = "";
+                                       child_row[recent_session_columns.disk_format] = "";
                                }
 
                                ++session_snapshot_count;
@@ -865,6 +898,19 @@ SessionDialog::recent_session_row_selected ()
        }
 }
 
+void
+SessionDialog::template_row_selected ()
+{
+       if (template_chooser.get_selection()->count_selected_rows() > 0) {
+               TreeIter iter = template_chooser.get_selection()->get_selected();
+
+               if (iter) {
+                       string s = (*iter)[session_template_columns.description];
+                       template_desc.get_buffer()->set_text (s);
+               }
+       }
+}
+
 void
 SessionDialog::setup_more_options_box ()
 {
@@ -1166,6 +1212,70 @@ SessionDialog::recent_row_activated (const Gtk::TreePath&, Gtk::TreeViewColumn*)
        response (RESPONSE_ACCEPT);
 }
 
+bool
+SessionDialog::recent_button_press (GdkEventButton* ev)
+{
+       if ((ev->type == GDK_BUTTON_PRESS) && (ev->button == 3) ) {
+
+               TreeModel::Path path;
+               TreeViewColumn* column;
+               int cellx, celly;
+               if (recent_session_display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) {
+                       Glib::RefPtr<Gtk::TreeView::Selection> selection = recent_session_display.get_selection();
+                       if (selection) {
+                               selection->unselect_all();
+                               selection->select(path);
+                       }
+               }
+
+               if (recent_session_display.get_selection()->count_selected_rows() > 0) {
+                       recent_context_mennu (ev);
+               }
+       }
+       return false;
+}
+
+void
+SessionDialog::recent_context_mennu (GdkEventButton *ev)
+{
+       using namespace Gtk::Menu_Helpers;
+
+       TreeIter iter = recent_session_display.get_selection()->get_selected();
+       assert (iter);
+       string s = (*iter)[recent_session_columns.fullpath];
+       if (Glib::file_test (s, Glib::FILE_TEST_IS_REGULAR)) {
+               s = Glib::path_get_dirname (s);
+       }
+       if (!Glib::file_test (s, Glib::FILE_TEST_IS_DIR)) {
+               return;
+       }
+
+       Gtk::TreeModel::Path tpath = recent_session_model->get_path(iter);
+       const bool is_child = tpath.up () && tpath.up ();
+
+       Gtk::Menu* m = manage (new Menu);
+       MenuList& items = m->items ();
+       items.push_back (MenuElem (s, sigc::bind (sigc::hide_return (sigc::ptr_fun (&PBD::open_folder)), s)));
+       if (!is_child) {
+               items.push_back (SeparatorElem());
+               items.push_back (MenuElem (_("Remove session from recent list"), sigc::mem_fun (*this, &SessionDialog::recent_remove_selected)));
+       }
+       m->popup (ev->button, ev->time);
+}
+
+void
+SessionDialog::recent_remove_selected ()
+{
+       TreeIter iter = recent_session_display.get_selection()->get_selected();
+       assert (iter);
+       string s = (*iter)[recent_session_columns.fullpath];
+       if (Glib::file_test (s, Glib::FILE_TEST_IS_REGULAR)) {
+               s = Glib::path_get_dirname (s);
+       }
+       ARDOUR::remove_recent_sessions (s);
+       redisplay_recent_sessions ();
+}
+
 void
 SessionDialog::disable_plugins_clicked ()
 {