From 13f4efbc9c6131f792493b7f422aaaccb6c05644 Mon Sep 17 00:00:00 2001 From: Lukas K Date: Wed, 7 Apr 2021 17:00:08 +0200 Subject: [PATCH] pool manager: add 'move to other pool' --- Makefile | 1 + imp.gresource.xml | 1 + src/pool-prj-mgr/pool-mgr/move_window.cpp | 168 +++++++++++++++++ src/pool-prj-mgr/pool-mgr/move_window.hpp | 34 ++++ src/pool-prj-mgr/pool-mgr/move_window.ui | 191 ++++++++++++++++++++ src/pool-prj-mgr/pool-mgr/pool_notebook.cpp | 16 ++ src/widgets/location_entry.cpp | 4 + src/widgets/location_entry.hpp | 3 +- 8 files changed, 417 insertions(+), 1 deletion(-) create mode 100644 src/pool-prj-mgr/pool-mgr/move_window.cpp create mode 100644 src/pool-prj-mgr/pool-mgr/move_window.hpp create mode 100644 src/pool-prj-mgr/pool-mgr/move_window.ui diff --git a/Makefile b/Makefile index 0fc27f207..9a99d014c 100644 --- a/Makefile +++ b/Makefile @@ -722,6 +722,7 @@ SRC_POOL_PRJ_MGR = \ src/pool-prj-mgr/pools_window/pool_status_provider.cpp\ src/pool-prj-mgr/pools_window/pool_merge_box.cpp\ src/pool-prj-mgr/pools_window/pool_download_window.cpp\ + src/pool-prj-mgr/pool-mgr/move_window.cpp\ SRC_PGM_TEST = \ src/pgm-test/pgm-test.cpp diff --git a/imp.gresource.xml b/imp.gresource.xml index 6f3a97d6f..8de06ad5e 100644 --- a/imp.gresource.xml +++ b/imp.gresource.xml @@ -22,6 +22,7 @@ pool-prj-mgr/pool-mgr/github_login_window.ui pool-prj-mgr/pool-mgr/import_kicad_package_window.ui pool-prj-mgr/pool-mgr/pool_cache_box.ui + pool-prj-mgr/pool-mgr/move_window.ui pool-prj-mgr/prj-mgr/part_browser/part_browser.ui pool-prj-mgr/welcome.ui pool-prj-mgr/output_window.ui diff --git a/src/pool-prj-mgr/pool-mgr/move_window.cpp b/src/pool-prj-mgr/pool-mgr/move_window.cpp new file mode 100644 index 000000000..702f1d33a --- /dev/null +++ b/src/pool-prj-mgr/pool-mgr/move_window.cpp @@ -0,0 +1,168 @@ +#include "move_window.hpp" +#include "pool/pool.hpp" +#include "util/gtk_util.hpp" +#include "common/object_descr.hpp" +#include "widgets/location_entry.hpp" +#include "pool/pool_manager.hpp" + +namespace horizon { +MoveWindow *MoveWindow::create(Pool &pool, ObjectType type, const UUID &uu) +{ + MoveWindow *w; + Glib::RefPtr x = Gtk::Builder::create(); + x->add_from_resource("/org/horizon-eda/horizon/pool-prj-mgr/pool-mgr/move_window.ui"); + x->get_widget_derived("window", w, pool, type, uu); + + return w; +} + +class MoveItemRow : public Gtk::Box { +public: + MoveItemRow(MoveWindow &p, SQLite::Query &q) + : Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 10), parent(p), filename(q.get(0)) + { + property_margin() = 5; + set_margin_end(10); + const auto type = q.get(1); + const auto name = q.get(2); + cb_item = Gtk::manage(new Gtk::CheckButton()); + { + auto box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 5)); + { + auto la = Gtk::manage(new Gtk::Label(object_descriptions.at(type).name)); + la->set_xalign(0); + parent.sg_type->add_widget(*la); + box->pack_start(*la, false, false, 0); + } + { + auto la = Gtk::manage(new Gtk::Label(name)); + la->set_xalign(0); + box->pack_start(*la, false, false, 0); + } + cb_item->add(*box); + } + cb_item->show_all(); + cb_item->set_active(true); + parent.sg_item->add_widget(*cb_item); + pack_start(*cb_item, false, false, 0); + + + { + auto la = Gtk::manage(new Gtk::Label(filename)); + la->set_xalign(0); + la->show(); + parent.sg_src->add_widget(*la); + pack_start(*la, false, false, 0); + } + + entry = Gtk::manage(new LocationEntry); + entry->show(); + entry->set_rel_filename(filename); + parent.sg_dest->add_widget(*entry); + pack_start(*entry, true, true, 0); + } + + MoveWindow &parent; + Gtk::CheckButton *cb_item; + LocationEntry *entry; + const std::string filename; +}; + + +MoveWindow::MoveWindow(BaseObjectType *cobject, const Glib::RefPtr &x, Pool &apool, ObjectType type, + const UUID &uu) + : Gtk::Window(cobject), pool(apool), window_state_store(this, "move-pool-item") +{ + GET_OBJECT(sg_item); + GET_OBJECT(sg_src); + GET_OBJECT(sg_dest); + sg_type = Gtk::SizeGroup::create(Gtk::SIZE_GROUP_HORIZONTAL); + + SQLite::Query q(pool.get_db(), + "WITH RECURSIVE " + "deps(typex, uuidx) AS " + "( SELECT $type, $uuid UNION " + "SELECT dep_type, dep_uuid FROM dependencies, deps " + "WHERE dependencies.type = deps.typex AND dependencies.uuid = deps.uuidx) " + ", deps_sym(typey, uuidy) AS (SELECT * FROM deps UNION SELECT 'symbol', symbols.uuid FROM " + "symbols INNER JOIN deps ON (symbols.unit = uuidx AND typex = 'unit')) " + ", where_used(typex, uuidx) AS ( SELECT $type, $uuid UNION " + "SELECT type, uuid FROM dependencies, where_used " + "WHERE dependencies.dep_type = where_used.typex " + "AND dependencies.dep_uuid = where_used.uuidx) " + + "SELECT filename, type, name FROM deps_sym LEFT JOIN all_items_view " + "ON(all_items_view.type =deps_sym.typey AND all_items_view.uuid = deps_sym.uuidy) " + "WHERE all_items_view.pool_uuid = $pool " + + "UNION SELECT model_filename, 'model_3d', '' FROM models INNER JOIN deps " + "ON (deps.typex = 'package' AND deps.uuidx = models.package_uuid) " + "LEFT JOIN packages ON (models.package_uuid = packages.uuid) " + "WHERE packages.pool_uuid = $pool " + + "UNION SELECT filename, type, name FROM where_used " + "LEFT JOIN all_items_view " + "ON (where_used.typex = all_items_view.type " + "AND where_used.uuidx = all_items_view.uuid) " + "WHERE all_items_view.pool_uuid = $pool"); + q.bind("$type", type); + q.bind("$uuid", uu); + q.bind("$pool", pool.get_pool_info().uuid); + GET_WIDGET(listbox); + + while (q.step()) { + auto w = Gtk::manage(new MoveItemRow(*this, q)); + w->show(); + listbox->append(*w); + } + + GET_WIDGET(pool_combo); + for (const auto &[path, it] : PoolManager::get().get_pools()) { + if (path != pool.get_base_path()) { + pool_combo->append(path, it.name + " (" + path + ")"); + } + } + pool_combo->signal_changed().connect([this] { + const std::string path = pool_combo->get_active_id(); + for (auto ch : listbox->get_children()) { + if (auto row = dynamic_cast(ch)) { + if (auto w = dynamic_cast(row->get_child())) { + w->entry->set_relative_to(path); + } + } + } + }); + pool_combo->set_active(0); + + { + Gtk::Button *button_move; + GET_WIDGET(button_move); + button_move->signal_clicked().connect(sigc::mem_fun(*this, &MoveWindow::do_move)); + } +} + +void MoveWindow::do_move() +{ + for (auto ch : listbox->get_children()) { + if (auto row = dynamic_cast(ch)) { + if (auto w = dynamic_cast(row->get_child())) { + if (w->cb_item->get_active()) { + auto src = Gio::File::create_for_path(Glib::build_filename(pool.get_base_path(), w->filename)); + auto dest = Gio::File::create_for_path(w->entry->get_filename()); + try { + dest->get_parent()->make_directory_with_parents(); + } + catch (Gio::Error &e) { + if (e.code() != Gio::Error::EXISTS) + throw; + } + src->move(dest); + } + } + } + } + moved = true; + hide(); +} + +} // namespace horizon diff --git a/src/pool-prj-mgr/pool-mgr/move_window.hpp b/src/pool-prj-mgr/pool-mgr/move_window.hpp new file mode 100644 index 000000000..d05481477 --- /dev/null +++ b/src/pool-prj-mgr/pool-mgr/move_window.hpp @@ -0,0 +1,34 @@ +#pragma once +#include +#include "util/window_state_store.hpp" +#include "common/common.hpp" +#include "util/uuid.hpp" + +namespace horizon { +class MoveWindow : public Gtk::Window { +public: + friend class MoveItemRow; + MoveWindow(BaseObjectType *cobject, const Glib::RefPtr &x, class Pool &pool, ObjectType type, + const UUID &uu); + static MoveWindow *create(class Pool &pool, ObjectType type, const UUID &uu); + bool get_moved() const + { + return moved; + } + +private: + void do_move(); + class Pool &pool; + Gtk::ComboBoxText *pool_combo = nullptr; + Gtk::ListBox *listbox = nullptr; + bool moved = false; + + + Glib::RefPtr sg_item; + Glib::RefPtr sg_type; + Glib::RefPtr sg_src; + Glib::RefPtr sg_dest; + + WindowStateStore window_state_store; +}; +} // namespace horizon diff --git a/src/pool-prj-mgr/pool-mgr/move_window.ui b/src/pool-prj-mgr/pool-mgr/move_window.ui new file mode 100644 index 000000000..174163511 --- /dev/null +++ b/src/pool-prj-mgr/pool-mgr/move_window.ui @@ -0,0 +1,191 @@ + + + + + + False + True + dialog + + + True + False + vertical + + + True + False + 10 + 10 + 10 + 10 + 10 + + + True + False + Destination Pool + + + + False + True + 0 + + + + + True + False + + + True + True + 1 + + + + + False + True + 0 + + + + + True + False + 1 + 1 + 10 + + + True + False + Item + 0 + + + + + + + False + True + 0 + + + + + True + False + Source filename + 0 + + + + + + + False + True + 1 + + + + + True + False + Destination filename + 0 + + + + + + + False + True + 2 + + + + + + False + True + 1 + + + + + True + True + external + + + True + False + none + + + True + False + none + False + + + + + + + True + True + 2 + + + + + + + True + False + Move Items + True + + + Move + True + True + True + + + + + + + + + + + + + + + + + + + + + diff --git a/src/pool-prj-mgr/pool-mgr/pool_notebook.cpp b/src/pool-prj-mgr/pool-mgr/pool_notebook.cpp index 5c87f5c23..9964b7d0b 100644 --- a/src/pool-prj-mgr/pool-mgr/pool_notebook.cpp +++ b/src/pool-prj-mgr/pool-mgr/pool_notebook.cpp @@ -24,6 +24,7 @@ #include "util/fs_util.hpp" #include "duplicate/duplicate_unit.hpp" #include "editors/editor_window.hpp" +#include "move_window.hpp" namespace horizon { @@ -429,6 +430,21 @@ void PoolNotebook::add_context_menu(PoolBrowser *br) auto x = get_pool_uuids(ty, uu); return x.last || x.pool != pool.get_pool_info().uuid; }); + br->add_context_menu_item( + "Move to other pool", + [this](const UUID &uu) { + auto win = MoveWindow::create(pool, ObjectType::PART, uu); + auto top = dynamic_cast(get_ancestor(GTK_TYPE_WINDOW)); + win->set_transient_for(*top); + win->present(); + win->signal_hide().connect([this, win] { + if (win->get_moved()) { + this->pool_update(); + } + delete win; + }); + }, + this_pool_lambda); } PoolNotebook::ItemPoolInfo PoolNotebook::get_pool_uuids(ObjectType ty, const UUID &uu) diff --git a/src/widgets/location_entry.cpp b/src/widgets/location_entry.cpp index 372aeb0a9..62905da6b 100644 --- a/src/widgets/location_entry.cpp +++ b/src/widgets/location_entry.cpp @@ -8,6 +8,10 @@ std::string LocationEntry::get_rel_filename(const std::string &s) const return Gio::File::create_for_path(relative_to)->get_relative_path(Gio::File::create_for_path(s)); } +void LocationEntry::set_relative_to(const std::string &s) +{ + relative_to = s; +} void LocationEntry::set_filename(const std::string &s) { diff --git a/src/widgets/location_entry.hpp b/src/widgets/location_entry.hpp index 912b4c7c7..9c98297dc 100644 --- a/src/widgets/location_entry.hpp +++ b/src/widgets/location_entry.hpp @@ -8,6 +8,7 @@ class LocationEntry : public Gtk::Box { LocationEntry(const std::string &rel = ""); void set_filename(const std::string &s); void set_rel_filename(const std::string &s); + void set_relative_to(const std::string &s); std::string get_filename(); void set_warning(const std::string &t); @@ -20,7 +21,7 @@ class LocationEntry : public Gtk::Box { bool check_ends_json(bool *v = nullptr); private: - const std::string relative_to; + std::string relative_to; std::string get_rel_filename(const std::string &s) const; Gtk::Entry *entry = nullptr; void handle_button();