Reworked implementation to include user feedback

This commit is contained in:
Matthias Koefferlein 2025-12-04 22:39:46 +01:00
parent 7c81a8e954
commit 652b596164
7 changed files with 164 additions and 62 deletions

View File

@ -375,9 +375,10 @@ PropertiesPage::count () const
void
PropertiesPage::select_entries (const std::vector<size_t> &entries)
{
tl_assert (entries.size () == 1);
if (! entries.empty ()) {
m_index = entries.front ();
}
}
std::string
PropertiesPage::description (size_t entry) const

View File

@ -283,7 +283,7 @@ ShapePropertiesPage::do_apply (bool current_only, bool relative, bool commit)
}
}
int new_layer = layer_selector ()->current_layer ();
int new_layer = layer_selector ()->current_layer_ensure ();
if (new_layer >= 0 && int (pos->layer ()) != new_layer) {
unsigned int gs_layer = cv->layout ().guiding_shape_layer ();
ChangeLayerApplicator *cla = new ChangeLayerApplicator (cv_index, (unsigned int) new_layer);

View File

@ -181,10 +181,11 @@ PropertiesPage::count () const
void
PropertiesPage::select_entries (const std::vector<size_t> &entries)
{
tl_assert (entries.size () == 1);
if (! entries.empty ()) {
m_index = entries.front ();
invalidate ();
}
}
std::string
PropertiesPage::description (size_t entry) const

View File

@ -235,10 +235,11 @@ PropertiesDialog::PropertiesDialog (QWidget * /*parent*/, db::Manager *manager,
m_current_object = 0;
// look for next usable editable
m_object_indexes.resize (mp_properties_pages.size ());
if (m_index >= int (mp_properties_pages.size ())) {
m_index = -1;
} else {
m_object_indexes.push_back (0);
m_object_indexes [m_index].push_back (0);
}
update_title ();
@ -383,6 +384,7 @@ BEGIN_PROTECTED
delete *p;
} else {
mp_properties_pages.push_back (*p);
(*p)->set_page_set (this);
}
}
}
@ -398,10 +400,11 @@ BEGIN_PROTECTED
// look for next usable editable
m_index = 0;
m_object_indexes.clear ();
m_object_indexes.resize (mp_properties_pages.size ());
if (m_index >= int (mp_properties_pages.size ())) {
m_index = -1;
} else {
m_object_indexes.push_back (0);
m_object_indexes [m_index].push_back (0);
}
mp_tree_model->end_reset_model ();
@ -436,6 +439,7 @@ PropertiesDialog::current_index_changed (const QModelIndex &index, const QModelI
}
m_object_indexes.clear ();
m_object_indexes.resize (mp_properties_pages.size ());
if (! index.isValid ()) {
@ -462,56 +466,66 @@ PropertiesDialog::current_index_changed (const QModelIndex &index, const QModelI
}
if (mp_tree_model->parent (index).isValid ()) {
m_index = mp_tree_model->page_index (index);
if (mp_properties_pages [m_index]->can_apply_to_all ()) {
m_object_indexes.push_back (size_t (mp_tree_model->object_index (index)));
m_index = -1;
auto selection = mp_ui->tree->selectionModel ()->selectedIndexes ();
// establish a single-selection on the current item
if (mp_tree_model->parent (index).isValid ()) {
int oi = mp_tree_model->object_index (index);
int pi = mp_tree_model->page_index (index);
m_index = pi;
m_object_indexes [pi].push_back (size_t (oi));
}
// establish individual selections for the other items
// as far as allowed by "can_apply_to_all"
for (auto i = selection.begin (); i != selection.end (); ++i) {
if (mp_tree_model->parent (*i).isValid () && mp_tree_model->page_index (*i) == m_index) {
if (*i != index && mp_tree_model->parent (*i).isValid ()) {
int oi = mp_tree_model->object_index (*i);
if (oi != int (m_object_indexes.front ())) {
m_object_indexes.push_back (size_t (oi));
int pi = mp_tree_model->page_index (*i);
if (mp_properties_pages [pi]->can_apply_to_all ()) {
m_object_indexes [pi].push_back (size_t (oi));
}
}
}
} else {
m_object_indexes.push_back (size_t (mp_tree_model->object_index (index)));
// establish group node selection as current item -> translate into "all" for "can_apply_to_all" pages
// or first item unless an item is explicitly selected.
if (! mp_tree_model->parent (index).isValid ()) {
int pi = index.row ();
m_index = pi;
m_object_indexes [pi].clear ();
if (mp_properties_pages [pi]->can_apply_to_all ()) {
for (size_t oi = 0; oi < mp_properties_pages [pi]->count (); ++oi) {
m_object_indexes [pi].push_back (oi);
}
} else if (mp_properties_pages [pi]->count () > 0 && m_object_indexes [pi].empty ()) {
m_object_indexes [pi].push_back (0);
}
}
} else {
m_index = index.row ();
if (mp_properties_pages [m_index]->can_apply_to_all ()) {
for (size_t oi = 0; oi < mp_properties_pages [m_index]->count (); ++oi) {
m_object_indexes.push_back (oi);
// establish group node selection for other items -> translate into "all" for "can_apply_to_all" pages
for (auto i = selection.begin (); i != selection.end (); ++i) {
if (*i != index && ! mp_tree_model->parent (*i).isValid ()) {
int pi = i->row ();
m_object_indexes [pi].clear ();
if (mp_properties_pages [pi]->can_apply_to_all ()) {
for (size_t oi = 0; oi < mp_properties_pages [pi]->count (); ++oi) {
m_object_indexes[pi].push_back (oi);
}
}
}
} else if (mp_properties_pages [m_index]->count () > 0) {
m_object_indexes.push_back (0);
}
}
}
if (! m_object_indexes.empty ()) {
if (m_index >= 0 && ! m_object_indexes [m_index].empty ()) {
m_current_object = 0;
for (int i = 0; i < m_index; ++i) {
m_current_object += mp_properties_pages [i]->count ();
}
m_current_object += int (m_object_indexes.front ());
m_current_object += int (m_object_indexes [m_index].front ());
} else {
m_current_object = -1;
}
@ -552,7 +566,10 @@ PropertiesDialog::update_controls ()
mp_ui->ok_button->setEnabled (! mp_properties_pages [m_index]->readonly ());
mp_ui->tree->setEnabled (true);
mp_properties_pages [m_index]->select_entries (m_object_indexes);
for (int i = 0; i < int (mp_properties_pages.size ()); ++i) {
mp_properties_pages [i]->select_entries (m_object_indexes [i]);
}
mp_properties_pages [m_index]->update ();
}
@ -563,7 +580,7 @@ PropertiesDialog::next_pressed ()
{
BEGIN_PROTECTED
if (m_object_indexes.empty ()) {
if (m_index < 0 || m_object_indexes [m_index].empty ()) {
return;
}
@ -576,7 +593,7 @@ BEGIN_PROTECTED
}
// advance the current entry
int object_index = int (m_object_indexes.front ());
int object_index = int (m_object_indexes [m_index].front ());
++object_index;
// look for next usable editable if at end
@ -593,7 +610,8 @@ BEGIN_PROTECTED
}
m_object_indexes.clear ();
m_object_indexes.push_back (object_index);
m_object_indexes.resize (mp_properties_pages.size ());
m_object_indexes [m_index].push_back (object_index);
++m_current_object;
update_title ();
@ -611,7 +629,7 @@ PropertiesDialog::prev_pressed ()
{
BEGIN_PROTECTED
if (m_object_indexes.empty ()) {
if (m_index < 0 || m_object_indexes [m_index].empty ()) {
return;
}
@ -624,7 +642,7 @@ BEGIN_PROTECTED
}
// advance the current entry
int object_index = int (m_object_indexes.front ());
int object_index = int (m_object_indexes [m_index].front ());
if (object_index == 0) {
// look for last usable editable if at end
@ -643,7 +661,8 @@ BEGIN_PROTECTED
--object_index;
m_object_indexes.clear ();
m_object_indexes.push_back (object_index);
m_object_indexes.resize (mp_properties_pages.size ());
m_object_indexes [m_index].push_back (object_index);
--m_current_object;
update_title ();
@ -669,12 +688,12 @@ PropertiesDialog::update_title ()
bool
PropertiesDialog::any_next () const
{
if (m_object_indexes.empty ()) {
if (m_index < 0 || m_object_indexes [m_index].empty ()) {
return false;
}
int index = m_index;
if (m_object_indexes.front () + 1 >= mp_properties_pages [index]->count ()) {
if (m_object_indexes [m_index].front () + 1 >= mp_properties_pages [index]->count ()) {
++index;
}
@ -685,12 +704,12 @@ PropertiesDialog::any_next () const
bool
PropertiesDialog::any_prev () const
{
if (m_object_indexes.empty ()) {
if (m_index < 0 || m_object_indexes [m_index].empty ()) {
return false;
}
int index = m_index;
if (m_object_indexes.front () == 0) {
if (m_object_indexes [m_index].front () == 0) {
--index;
}

View File

@ -95,7 +95,7 @@ private:
db::Manager *mp_manager;
lay::Editables *mp_editables;
int m_index, m_prev_index;
std::vector<size_t> m_object_indexes;
std::vector<std::vector<size_t> > m_object_indexes;
QStackedLayout *mp_stack;
QLabel *mp_none;
lay::MainWindow *mp_mw;

View File

@ -514,7 +514,7 @@ struct LayerSelectionComboBoxPrivateData
};
LayerSelectionComboBox::LayerSelectionComboBox (QWidget *parent)
: QComboBox (parent), dm_update_layer_list (this, &LayerSelectionComboBox::do_update_layer_list)
: QComboBox (parent), dm_update_layer_list (this, &LayerSelectionComboBox::do_update_layer_list), m_ignore_layer_list_changed (false)
{
mp_private = new LayerSelectionComboBoxPrivateData ();
mp_private->no_layer_available = false;
@ -651,8 +651,10 @@ LayerSelectionComboBox::set_view (lay::LayoutViewBase *view, int cv_index, bool
void
LayerSelectionComboBox::on_layer_list_changed (int)
{
if (! m_ignore_layer_list_changed) {
update_layer_list ();
}
}
void
LayerSelectionComboBox::set_layout (const db::Layout *layout)
@ -795,8 +797,8 @@ LayerSelectionComboBox::set_current_layer (const db::LayerProperties &props)
setCurrentIndex (-1);
}
void
LayerSelectionComboBox::set_current_layer (int l)
const db::Layout *
LayerSelectionComboBox::layout () const
{
const db::Layout *layout = mp_private->layout;
if (! layout && mp_private->view) {
@ -805,9 +807,22 @@ LayerSelectionComboBox::set_current_layer (int l)
layout = & cv->layout ();
}
}
return layout;
}
if (l >= 0 && layout && layout->is_valid_layer ((unsigned int) l)) {
mp_private->last_props = layout->get_properties ((unsigned int) l);
db::Layout *
LayerSelectionComboBox::layout ()
{
return const_cast<db::Layout *> (((const LayerSelectionComboBox *) this)->layout ());
}
void
LayerSelectionComboBox::set_current_layer (int l)
{
const db::Layout *ly = layout ();
if (l >= 0 && ly && ly->is_valid_layer ((unsigned int) l)) {
mp_private->last_props = ly->get_properties ((unsigned int) l);
}
if (l < 0) {
@ -821,6 +836,12 @@ LayerSelectionComboBox::set_current_layer (int l)
}
}
bool
LayerSelectionComboBox::is_no_layer_selected () const
{
return currentIndex () < 0;
}
int
LayerSelectionComboBox::current_layer () const
{
@ -832,6 +853,39 @@ LayerSelectionComboBox::current_layer () const
}
}
int
LayerSelectionComboBox::current_layer_ensure ()
{
int i = currentIndex ();
if (i < 0 || i > int (mp_private->layers.size ())) {
return -1;
} else if (mp_private->layers [i].second < 0) {
db::Layout *ly = layout ();
if (! ly) {
return -1;
}
m_ignore_layer_list_changed = true;
try {
unsigned int l = ly->insert_layer (mp_private->layers [i].first);
mp_private->layers [i].second = l;
m_ignore_layer_list_changed = false;
return l;
} catch (...) {
m_ignore_layer_list_changed = false;
throw;
}
} else {
return mp_private->layers [i].second;
}
}
db::LayerProperties
LayerSelectionComboBox::current_layer_props () const
{

View File

@ -300,13 +300,37 @@ public:
*/
void set_current_layer (int l);
/**
* @brief Gets a valid indicating whether a layer is selected
*
* This method returns true if "no layer" is selected
*/
bool is_no_layer_selected () const;
/**
* @brief Get the current layer (index)
*
* NOTE: this method returns -1 if no layer is selected or
* the current layer does not exist. Use "is_no_layer_selected"
* for a value telling whether no layer is selected (true)
* or a not-yet-existing layer is selected (false).
*/
int current_layer () const;
/**
* @brief Get the current layer (index) and makes sure it exists
*
* This method ensures that the layer is created if it does not
* exist yet. It returns -1 on "no layer" (if enabled).
*/
int current_layer_ensure ();
/**
* @brief Get the current layer properties
*
* If "no layer" is selected, this method returns the last properties set
* with "set_current_layer". Use "is_no_layer_selected" to get
* a value indicating whether the "no layer" entry is selected.
*/
db::LayerProperties current_layer_props () const;
@ -323,10 +347,13 @@ protected slots:
private:
LayerSelectionComboBoxPrivateData *mp_private;
tl::DeferredMethod<LayerSelectionComboBox> dm_update_layer_list;
bool m_ignore_layer_list_changed;
void on_layer_list_changed (int);
void update_layer_list ();
void do_update_layer_list ();
db::Layout *layout ();
const db::Layout *layout () const;
};
/**