Add buttons for reordering favorites
This commit is contained in:
parent
fde15eaebb
commit
4fe39a82a5
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "guiutils.h"
|
#include "guiutils.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
#include "rtimage.h"
|
||||||
#include "toollocationpref.h"
|
#include "toollocationpref.h"
|
||||||
#include "toolpanelcoord.h"
|
#include "toolpanelcoord.h"
|
||||||
|
|
||||||
@ -291,7 +292,28 @@ Glib::ustring getToolTitleKey(Tool tool)
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
class ListEditButtons : public Gtk::Box
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Gtk::TreeView &list;
|
||||||
|
Glib::RefPtr<Gtk::ListStore> listStore;
|
||||||
|
Gtk::Button buttonUp;
|
||||||
|
Gtk::Button buttonDown;
|
||||||
|
Gtk::Button buttonRemove;
|
||||||
|
|
||||||
|
sigc::signal<void, const std::vector<Gtk::TreeModel::Path>> signalRowsPreErase;
|
||||||
|
|
||||||
|
void onButtonDownPressed();
|
||||||
|
void onButtonRemovePressed();
|
||||||
|
void onButtonUpPressed();
|
||||||
|
void onListSelectionChanged();
|
||||||
|
void updateButtonSensitivity();
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ListEditButtons(Gtk::TreeView &list, Glib::RefPtr<Gtk::ListStore> listStore);
|
||||||
|
|
||||||
|
sigc::signal<void, const std::vector<Gtk::TreeModel::Path>> getSignalRowsPreErase();
|
||||||
|
};
|
||||||
|
|
||||||
class FavoritesColumns : public Gtk::TreeModelColumnRecord
|
class FavoritesColumns : public Gtk::TreeModelColumnRecord
|
||||||
{
|
{
|
||||||
@ -323,6 +345,148 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ListEditButtons::ListEditButtons(Gtk::TreeView &list, Glib::RefPtr<Gtk::ListStore> listStore) :
|
||||||
|
Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL),
|
||||||
|
list(list),
|
||||||
|
listStore(listStore)
|
||||||
|
{
|
||||||
|
assert(list.get_model() == listStore);
|
||||||
|
|
||||||
|
// Set button images.
|
||||||
|
RTImage *image_button_up = Gtk::manage(new RTImage("arrow-up-small.png"));
|
||||||
|
RTImage *image_button_down = Gtk::manage(new RTImage("arrow-down-small.png"));
|
||||||
|
RTImage *image_button_remove = Gtk::manage(new RTImage("remove-small.png"));
|
||||||
|
buttonUp.set_image(*image_button_up);
|
||||||
|
buttonDown.set_image(*image_button_down);
|
||||||
|
buttonRemove.set_image(*image_button_remove);
|
||||||
|
|
||||||
|
// Connect signals for changing button sensitivity.
|
||||||
|
const auto on_list_sel_changed_fun = sigc::mem_fun(
|
||||||
|
*this, &ListEditButtons::onListSelectionChanged);
|
||||||
|
const auto on_row_deleted_fun = sigc::hide(on_list_sel_changed_fun);
|
||||||
|
const auto on_row_inserted_fun = sigc::hide(on_row_deleted_fun);
|
||||||
|
list.get_selection()->signal_changed().connect(on_list_sel_changed_fun);
|
||||||
|
listStore->signal_row_deleted().connect(on_row_deleted_fun);
|
||||||
|
listStore->signal_row_inserted().connect(on_row_inserted_fun);
|
||||||
|
|
||||||
|
// Connect signals for buttons.
|
||||||
|
buttonUp.signal_pressed().connect(sigc::mem_fun(
|
||||||
|
*this, &ListEditButtons::onButtonUpPressed));
|
||||||
|
buttonDown.signal_pressed().connect(sigc::mem_fun(
|
||||||
|
*this, &ListEditButtons::onButtonDownPressed));
|
||||||
|
buttonRemove.signal_pressed().connect(sigc::mem_fun(
|
||||||
|
*this, &ListEditButtons::onButtonRemovePressed));
|
||||||
|
|
||||||
|
updateButtonSensitivity();
|
||||||
|
|
||||||
|
add(buttonUp);
|
||||||
|
add(buttonDown);
|
||||||
|
add(buttonRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListEditButtons::onButtonDownPressed()
|
||||||
|
{
|
||||||
|
const auto list_children = listStore->children();
|
||||||
|
const std::vector<Gtk::TreeModel::Path> selected =
|
||||||
|
list.get_selection()->get_selected_rows();
|
||||||
|
|
||||||
|
if (selected.size() != 1) { // Only one can be selected.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto selected_row_iter = listStore->get_iter(selected[0]);
|
||||||
|
auto next_row_iter = selected_row_iter;
|
||||||
|
next_row_iter++;
|
||||||
|
|
||||||
|
if (next_row_iter == list_children.end()) { // Can't be last row.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
listStore->iter_swap(selected_row_iter, next_row_iter);
|
||||||
|
updateButtonSensitivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListEditButtons::onButtonRemovePressed()
|
||||||
|
{
|
||||||
|
const std::vector<Gtk::TreeModel::Path> selected_paths =
|
||||||
|
list.get_selection()->get_selected_rows();
|
||||||
|
std::vector<Gtk::TreeModel::RowReference> selected;
|
||||||
|
|
||||||
|
// Get row references, which are valid until the row is removed.
|
||||||
|
for (const auto & row_path : selected_paths) {
|
||||||
|
selected.push_back(Gtk::TreeModel::RowReference(listStore, row_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
signalRowsPreErase.emit(selected_paths);
|
||||||
|
|
||||||
|
for (const auto & row_ref : selected) {
|
||||||
|
const auto row_path = row_ref.get_path();
|
||||||
|
if (row_path) {
|
||||||
|
listStore->erase(listStore->get_iter(row_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateButtonSensitivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListEditButtons::onButtonUpPressed()
|
||||||
|
{
|
||||||
|
const auto list_children = listStore->children();
|
||||||
|
const std::vector<Gtk::TreeModel::Path> selected =
|
||||||
|
list.get_selection()->get_selected_rows();
|
||||||
|
|
||||||
|
if (selected.size() != 1) { // Only one can be selected.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto selected_row_iter = listStore->get_iter(selected[0]);
|
||||||
|
|
||||||
|
if (selected_row_iter == list_children.begin()) { // Can't be first row.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto prev_row_iter = selected_row_iter;
|
||||||
|
prev_row_iter--;
|
||||||
|
listStore->iter_swap(selected_row_iter, prev_row_iter);
|
||||||
|
updateButtonSensitivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListEditButtons::onListSelectionChanged()
|
||||||
|
{
|
||||||
|
updateButtonSensitivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListEditButtons::updateButtonSensitivity()
|
||||||
|
{
|
||||||
|
assert(list.get_model() == listStore);
|
||||||
|
|
||||||
|
const std::vector<Gtk::TreeModel::Path> selected =
|
||||||
|
list.get_selection()->get_selected_rows();
|
||||||
|
|
||||||
|
// Update sensitivity of the move up/down buttons.
|
||||||
|
if (selected.size() != 1) {
|
||||||
|
// Items can only be moved if one row is selected.
|
||||||
|
buttonDown.set_sensitive(false);
|
||||||
|
buttonUp.set_sensitive(false);
|
||||||
|
} else {
|
||||||
|
auto selected_row_iter = list.get_model()->get_iter(selected[0]);
|
||||||
|
const auto list_children = listStore->children();
|
||||||
|
buttonUp.set_sensitive(!selected_row_iter->equal(list_children.begin()));
|
||||||
|
buttonDown.set_sensitive(!(++selected_row_iter)->equal(list_children.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update sensitivity of the remove button.
|
||||||
|
buttonRemove.set_sensitive(selected.size() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sigc::signal<void, const std::vector<Gtk::TreeModel::Path>>
|
||||||
|
ListEditButtons::getSignalRowsPreErase()
|
||||||
|
{
|
||||||
|
return signalRowsPreErase;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
struct ToolLocationPreference::Impl {
|
struct ToolLocationPreference::Impl {
|
||||||
static std::unordered_map<std::string, Tool> toolNamesReverseMap;
|
static std::unordered_map<std::string, Tool> toolNamesReverseMap;
|
||||||
|
|
||||||
@ -336,6 +500,7 @@ struct ToolLocationPreference::Impl {
|
|||||||
Gtk::TreeViewColumn toolListViewColumnFavorite;
|
Gtk::TreeViewColumn toolListViewColumnFavorite;
|
||||||
Gtk::TreeViewColumn toolListViewColumnToolName;
|
Gtk::TreeViewColumn toolListViewColumnToolName;
|
||||||
Gtk::TreeView *toolListViewPtr;
|
Gtk::TreeView *toolListViewPtr;
|
||||||
|
std::unordered_map<Tool, Gtk::TreeModel::iterator> toolListToolToRowIterMap;
|
||||||
|
|
||||||
// Favorites list.
|
// Favorites list.
|
||||||
FavoritesColumns favoritesColumns;
|
FavoritesColumns favoritesColumns;
|
||||||
@ -343,6 +508,7 @@ struct ToolLocationPreference::Impl {
|
|||||||
Gtk::CellRendererText favoritesCellRendererToolName;
|
Gtk::CellRendererText favoritesCellRendererToolName;
|
||||||
Gtk::TreeViewColumn favoritesViewColumnToolName;
|
Gtk::TreeViewColumn favoritesViewColumnToolName;
|
||||||
Gtk::TreeView *favoritesViewPtr;
|
Gtk::TreeView *favoritesViewPtr;
|
||||||
|
ListEditButtons favoritesListEditButtons;
|
||||||
|
|
||||||
explicit Impl(Options &options);
|
explicit Impl(Options &options);
|
||||||
|
|
||||||
@ -354,6 +520,7 @@ struct ToolLocationPreference::Impl {
|
|||||||
Tool getToolFromName(const std::string &name) const;
|
Tool getToolFromName(const std::string &name) const;
|
||||||
void initFavoritesRows(const std::vector<Tool> &favorites);
|
void initFavoritesRows(const std::vector<Tool> &favorites);
|
||||||
void initToolListRows(const std::vector<Tool> &favorites);
|
void initToolListRows(const std::vector<Tool> &favorites);
|
||||||
|
void onFavoritesRowsPreRemove(const std::vector<Gtk::TreeModel::Path> paths);
|
||||||
std::vector<Tool> toolNamesToTools(
|
std::vector<Tool> toolNamesToTools(
|
||||||
const std::vector<Glib::ustring> &tool_names) const;
|
const std::vector<Glib::ustring> &tool_names) const;
|
||||||
void updateOptions();
|
void updateOptions();
|
||||||
@ -375,7 +542,8 @@ ToolLocationPreference::Impl::Impl(Options &options) :
|
|||||||
favoritesModelPtr(Gtk::ListStore::create(favoritesColumns)),
|
favoritesModelPtr(Gtk::ListStore::create(favoritesColumns)),
|
||||||
favoritesViewColumnToolName(
|
favoritesViewColumnToolName(
|
||||||
Gtk::TreeViewColumn(M("PREFERENCES_TOOLPANEL_TOOL"))),
|
Gtk::TreeViewColumn(M("PREFERENCES_TOOLPANEL_TOOL"))),
|
||||||
favoritesViewPtr(Gtk::manage(new Gtk::TreeView(favoritesModelPtr)))
|
favoritesViewPtr(Gtk::manage(new Gtk::TreeView(favoritesModelPtr))),
|
||||||
|
favoritesListEditButtons(*favoritesViewPtr, favoritesModelPtr)
|
||||||
{
|
{
|
||||||
const std::vector<Tool> favorites = toolNamesToTools(options.favorites);
|
const std::vector<Tool> favorites = toolNamesToTools(options.favorites);
|
||||||
|
|
||||||
@ -403,6 +571,10 @@ ToolLocationPreference::Impl::Impl(Options &options) :
|
|||||||
favoritesViewColumnToolName.pack_start(favoritesCellRendererToolName);
|
favoritesViewColumnToolName.pack_start(favoritesCellRendererToolName);
|
||||||
favoritesViewColumnToolName.set_renderer(
|
favoritesViewColumnToolName.set_renderer(
|
||||||
favoritesCellRendererToolName, favoritesColumns.toolName);
|
favoritesCellRendererToolName, favoritesColumns.toolName);
|
||||||
|
favoritesListEditButtons.getSignalRowsPreErase().connect(sigc::mem_fun(
|
||||||
|
*this, &ToolLocationPreference::Impl::onFavoritesRowsPreRemove));
|
||||||
|
favoritesViewPtr->get_selection()->set_mode(
|
||||||
|
Gtk::SelectionMode::SELECTION_MULTIPLE);
|
||||||
initFavoritesRows(favorites);
|
initFavoritesRows(favorites);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -497,6 +669,7 @@ void ToolLocationPreference::Impl::addToolListRowGroup(
|
|||||||
tool_row_iter->set_value(
|
tool_row_iter->set_value(
|
||||||
toolListColumns.isEditable,
|
toolListColumns.isEditable,
|
||||||
ToolPanelCoordinator::isFavoritable(tool.id));
|
ToolPanelCoordinator::isFavoritable(tool.id));
|
||||||
|
toolListToolToRowIterMap[tool.id] = tool_row_iter;
|
||||||
addToolListRowGroup(tool.children, tool_row_iter, favorites);
|
addToolListRowGroup(tool.children, tool_row_iter, favorites);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -527,6 +700,18 @@ void ToolLocationPreference::Impl::initToolListRows(const std::vector<Tool> &fav
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ToolLocationPreference::Impl::onFavoritesRowsPreRemove(
|
||||||
|
const std::vector<Gtk::TreeModel::Path> paths)
|
||||||
|
{
|
||||||
|
// Unset the favorite column in the tools list for tools about to be removed
|
||||||
|
// from the favorites list.
|
||||||
|
for (const auto &path : paths) {
|
||||||
|
const auto &row_iter = toolListToolToRowIterMap.at(
|
||||||
|
favoritesModelPtr->get_iter(path)->get_value(favoritesColumns.tool));
|
||||||
|
row_iter->set_value(toolListColumns.isFavorite, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Tool> ToolLocationPreference::Impl::toolNamesToTools(
|
std::vector<Tool> ToolLocationPreference::Impl::toolNamesToTools(
|
||||||
const std::vector<Glib::ustring> &tool_names) const
|
const std::vector<Glib::ustring> &tool_names) const
|
||||||
{
|
{
|
||||||
@ -579,11 +764,14 @@ ToolLocationPreference::ToolLocationPreference(Options &options) :
|
|||||||
// Favorites list.
|
// Favorites list.
|
||||||
Gtk::Frame *favorites_frame = Gtk::manage(new Gtk::Frame(
|
Gtk::Frame *favorites_frame = Gtk::manage(new Gtk::Frame(
|
||||||
M("PREFERENCES_TOOLPANEL_FAVORITESPANEL")));
|
M("PREFERENCES_TOOLPANEL_FAVORITESPANEL")));
|
||||||
|
Gtk::Box *favorites_box = Gtk::manage(new Gtk::Box());
|
||||||
Gtk::ScrolledWindow *favorites_list_scrolled_window =
|
Gtk::ScrolledWindow *favorites_list_scrolled_window =
|
||||||
Gtk::manage(new Gtk::ScrolledWindow());
|
Gtk::manage(new Gtk::ScrolledWindow());
|
||||||
favorites_list_scrolled_window->set_min_content_width(400);
|
favorites_list_scrolled_window->set_min_content_width(400);
|
||||||
layout_grid->attach_next_to(*favorites_frame, Gtk::PositionType::POS_RIGHT, 1, 1);
|
layout_grid->attach_next_to(*favorites_frame, Gtk::PositionType::POS_RIGHT, 1, 1);
|
||||||
favorites_frame->add(*favorites_list_scrolled_window);
|
favorites_box->pack_start(*favorites_list_scrolled_window, false, false);
|
||||||
|
favorites_box->pack_start(impl->favoritesListEditButtons, false, false);
|
||||||
|
favorites_frame->add(*favorites_box);
|
||||||
favorites_list_scrolled_window->add(*impl->favoritesViewPtr);
|
favorites_list_scrolled_window->add(*impl->favoritesViewPtr);
|
||||||
setExpandAlignProperties(
|
setExpandAlignProperties(
|
||||||
favorites_frame, false, true, Gtk::ALIGN_START, Gtk::ALIGN_FILL);
|
favorites_frame, false, true, Gtk::ALIGN_START, Gtk::ALIGN_FILL);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user