/* KLayout Layout Viewer Copyright (C) 2006-2017 Matthias Koefferlein This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "layPropertiesDialog.h" #include "tlLog.h" #include "layEditable.h" #include "layProperties.h" #include "tlExceptions.h" #include namespace lay { PropertiesDialog::PropertiesDialog (QWidget * /*parent*/, db::Manager *manager, lay::Editables *editables) : QDialog (0 /*parent*/), mp_manager (manager), mp_editables (editables), m_index (-1) { mp_editables->enable_edits (false); setObjectName (QString::fromUtf8 ("properties_dialog")); Ui::PropertiesDialog::setupUi (this); mp_stack = new QStackedLayout; for (lay::Editables::iterator e = mp_editables->begin (); e != mp_editables->end (); ++e) { mp_properties_pages.push_back (e->properties_page (content_frame)); if (mp_properties_pages.back ()) { mp_stack->addWidget (mp_properties_pages.back ()); } } // Necessary to maintain the page order for UI regression testing of 0.18 vs. 0.19 (because tl::Collection has changed to order) .. std::reverse (mp_properties_pages.begin (), mp_properties_pages.end ()); // Add a label as a dummy QLabel *dummy = new QLabel (QObject::tr ("No object with properties to display"), content_frame); dummy->setAlignment (Qt::AlignHCenter | Qt::AlignVCenter); mp_stack->addWidget (dummy); content_frame->setLayout (mp_stack); // disable the apply button for first .. apply_button->setEnabled (false); apply_to_all_button->setEnabled (false); ok_button->setEnabled (false); // as a proposal, the start button can be enabled in most cases prev_button->setEnabled (true); // count the total number of objects m_objects = mp_editables->selection_size (); m_current_object = 0; update_title (); // look for next usable editable while (m_index < int (mp_properties_pages.size ()) && (m_index < 0 || mp_properties_pages [m_index] == 0 || mp_properties_pages [m_index]->at_end ())) { ++m_index; } prev_button->setEnabled (false); // if at end disable the "Next" button and return (this may only happen at the first call) if (m_index >= int (mp_properties_pages.size ())) { next_button->setEnabled (false); mp_stack->setCurrentWidget (dummy); apply_button->setEnabled (false); apply_to_all_button->setEnabled (false); ok_button->setEnabled (false); } else { next_button->setEnabled (any_next ()); mp_properties_pages [m_index]->update (); mp_stack->setCurrentWidget (mp_properties_pages [m_index]); apply_button->setEnabled (! mp_properties_pages [m_index]->readonly ()); apply_to_all_button->setEnabled (! mp_properties_pages [m_index]->readonly () && mp_properties_pages [m_index]->can_apply_to_all ()); ok_button->setEnabled (! mp_properties_pages [m_index]->readonly ()); } connect (apply_button, SIGNAL (clicked ()), this, SLOT (apply_pressed ())); connect (apply_to_all_button, SIGNAL (clicked ()), this, SLOT (apply_to_all_pressed ())); connect (ok_button, SIGNAL (clicked ()), this, SLOT (ok_pressed ())); connect (cancel_button, SIGNAL (clicked ()), this, SLOT (cancel_pressed ())); connect (prev_button, SIGNAL (clicked ()), this, SLOT (prev_pressed ())); connect (next_button, SIGNAL (clicked ()), this, SLOT (next_pressed ())); } PropertiesDialog::~PropertiesDialog () { disconnect (); } void PropertiesDialog::disconnect () { mp_editables->enable_edits (true); for (std::vector ::iterator p = mp_properties_pages.begin (); p != mp_properties_pages.end (); ++p) { delete *p; } mp_properties_pages.clear (); } void PropertiesDialog::next_pressed () { BEGIN_PROTECTED if (! mp_properties_pages [m_index]->readonly ()) { db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes"))); mp_properties_pages [m_index]->apply (); } // advance the current entry ++(*mp_properties_pages [m_index]); // look for next usable editable if at end if (mp_properties_pages [m_index]->at_end ()) { mp_properties_pages [m_index]->leave (); ++m_index; while (m_index < int (mp_properties_pages.size ()) && (mp_properties_pages [m_index] == 0 || ! mp_properties_pages [m_index]->front_checked ())) { ++m_index; } // because we checked that there are any further elements, this should not happen: if (m_index >= int (mp_properties_pages.size ())) { return; } mp_stack->setCurrentWidget (mp_properties_pages [m_index]); } ++m_current_object; update_title (); prev_button->setEnabled (true); next_button->setEnabled (any_next ()); apply_button->setEnabled (! mp_properties_pages [m_index]->readonly ()); apply_to_all_button->setEnabled (! mp_properties_pages [m_index]->readonly () && mp_properties_pages [m_index]->can_apply_to_all ()); ok_button->setEnabled (! mp_properties_pages [m_index]->readonly ()); mp_properties_pages [m_index]->update (); END_PROTECTED } void PropertiesDialog::prev_pressed () { BEGIN_PROTECTED if (! mp_properties_pages [m_index]->readonly ()) { db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes"))); mp_properties_pages [m_index]->apply (); } if (mp_properties_pages [m_index]->at_begin ()) { // look for last usable editable if at end mp_properties_pages [m_index]->leave (); --m_index; while (m_index >= 0 && (mp_properties_pages [m_index] == 0 || ! mp_properties_pages [m_index]->back_checked ())) { --m_index; } // because we checked that there are any further elements, this should not happen: if (m_index < 0) { return; } mp_stack->setCurrentWidget (mp_properties_pages [m_index]); } // decrement the current entry --(*mp_properties_pages [m_index]); --m_current_object; update_title (); next_button->setEnabled (true); prev_button->setEnabled (any_prev ()); apply_button->setEnabled (! mp_properties_pages [m_index]->readonly ()); apply_to_all_button->setEnabled (! mp_properties_pages [m_index]->readonly () && mp_properties_pages [m_index]->can_apply_to_all ()); ok_button->setEnabled (! mp_properties_pages [m_index]->readonly ()); mp_properties_pages [m_index]->update (); END_PROTECTED } void PropertiesDialog::update_title () { setWindowTitle (tl::to_qstring (tl::to_string (QObject::tr ("Object Properties - ")) + tl::to_string (m_current_object + 1) + tl::to_string (QObject::tr (" of ")) + tl::to_string (m_objects))); } bool PropertiesDialog::any_next () const { // test-advance int index = m_index; ++(*mp_properties_pages [index]); if (mp_properties_pages [index]->at_end ()) { ++index; while (index < int (mp_properties_pages.size ()) && (mp_properties_pages [index] == 0 || ! mp_properties_pages [index]->front_checked ())) { ++index; } } // return true, if not at end bool ret = (index < int (mp_properties_pages.size ())); --(*mp_properties_pages [m_index]); return ret; } bool PropertiesDialog::any_prev () const { // test-decrement int index = m_index; if (mp_properties_pages [index]->at_begin ()) { --index; while (index >= 0 && (mp_properties_pages [index] == 0 || ! mp_properties_pages [index]->back_checked ())) { --index; } } // return true, if not at the beginning return (index >= 0); } void PropertiesDialog::apply_to_all_pressed () { BEGIN_PROTECTED db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes to all"))); mp_properties_pages [m_index]->apply_to_all (); mp_properties_pages [m_index]->update (); END_PROTECTED } void PropertiesDialog::apply_pressed () { BEGIN_PROTECTED db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes"))); mp_properties_pages [m_index]->apply (); mp_properties_pages [m_index]->update (); END_PROTECTED } void PropertiesDialog::cancel_pressed () { // make sure that the property pages are no longer used .. disconnect (); // close the dialog done (0); } void PropertiesDialog::ok_pressed () { BEGIN_PROTECTED if (! mp_properties_pages [m_index]->readonly ()) { db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes"))); mp_properties_pages [m_index]->apply (); mp_properties_pages [m_index]->update (); } // make sure that the property pages are no longer used .. disconnect (); QDialog::accept (); END_PROTECTED } void PropertiesDialog::reject () { // make sure that the property pages are no longer used .. disconnect (); QDialog::reject (); } }