klayout/src/laybasic/layPropertiesDialog.cc

320 lines
9.1 KiB
C++

/*
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 <QStackedLayout>
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 <lay::PropertiesPage *>::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 ();
}
}