/*! Constructor * \param[in] el the configuration element to display * \param[in] differ shall the changes be applied later using apply_changes()? */ ConfigElement::ConfigElement(crn::ConfigElement &el, bool differ): value(el.GetValue()), tmpvalue(el.GetValue()) { if (!value) throw crn::ExceptionUninitialized(_("The element was not initialized.")); if (differ) tmpvalue = crn::Clone(*value); if (std::dynamic_pointer_cast<crn::Int>(tmpvalue)) typ = U"Int"; else if (std::dynamic_pointer_cast<crn::Real>(tmpvalue)) typ = U"Real"; else if (std::dynamic_pointer_cast<crn::Prop3>(tmpvalue)) typ = U"Prop3"; else if (std::dynamic_pointer_cast<crn::String>(tmpvalue)) typ = U"String"; else if (std::dynamic_pointer_cast<crn::StringUTF8>(tmpvalue)) typ = U"StringUTF8"; else if (std::dynamic_pointer_cast<crn::Path>(tmpvalue)) typ = U"Path"; Gtk::Label *lab = Gtk::manage(new Gtk::Label(el.GetName().CStr())); lab->show(); pack_start(*lab, false, true, 2); if (typ == U"Prop3") { Prop3 *p = Gtk::manage(new Prop3(Gtk::ICON_SIZE_BUTTON, el.GetValue<crn::Prop3>())); p->signal_value_changed().connect(sigc::mem_fun(this, &ConfigElement::on_p3_changed)); p->show(); pack_start(*p, true, true, 2); } else if (!el.GetAllowedValues().IsEmpty()) { // any Int, Real, String, StringUTF8 or Path Gtk::ComboBoxText *cb = Gtk::manage(new Gtk::ComboBoxText); const std::vector<crn::StringUTF8> values(el.GetAllowedValues<crn::StringUTF8>()); for (const crn::StringUTF8 &val : values) #ifdef CRN_USING_GTKMM3 cb->append(val.CStr()); #else /* CRN_USING_GTKMM3 */ cb->append_text(val.CStr()); #endif /* CRN_USING_GTKMM3 */ cb->set_active_text(el.GetValue<crn::StringUTF8>().CStr()); cb->signal_changed().connect(sigc::bind(sigc::mem_fun(this, &ConfigElement::on_combo_changed), cb)); cb->show(); pack_start(*cb, true, true, 2); } else if (typ == U"Int") { if (el.HasMinValue() && el.HasMaxValue()) { // has finite range, use a slider #ifdef CRN_USING_GTKMM3 auto *s = Gtk::manage(new Gtk::Scale(Gtk::ORIENTATION_HORIZONTAL)); s->set_range(el.GetMinValue<int>(), el.GetMaxValue<int>() + 1); s->set_increments(1, 1); #else Gtk::HScale *s = Gtk::manage(new Gtk::HScale(el.GetMinValue<int>(), el.GetMaxValue<int>() + 1, 1)); #endif s->set_value(el.GetValue<int>()); s->signal_value_changed().connect(sigc::bind(sigc::mem_fun(this, &ConfigElement::on_range_changed), s)); s->show(); pack_start(*s, true, true, 2); } else { // has at least one infinite (maxed) bound, use a spin button Gtk::SpinButton *s = Gtk::manage(new Gtk::SpinButton); int m = std::numeric_limits<int>::min(), M = std::numeric_limits<int>::max(); if (el.HasMinValue()) m = el.GetMinValue<int>(); if (el.HasMaxValue()) M = el.GetMaxValue<int>(); s->set_range(m, M); s->set_increments(1, 10); s->set_value(el.GetValue<int>()); s->signal_value_changed().connect(sigc::bind(sigc::mem_fun(this, &ConfigElement::on_spin_changed), s)); s->show(); pack_start(*s, true, true, 2); } } else if (typ == U"Real") { if (el.HasMinValue() && el.HasMaxValue()) { // has finite range, use a slider #ifdef CRN_USING_GTKMM3 auto *s = Gtk::manage(new Gtk::Scale(Gtk::ORIENTATION_HORIZONTAL)); s->set_range(el.GetMinValue<double>(), el.GetMaxValue<double>() + 0.01); s->set_increments(0.01, 0.01); #else Gtk::HScale *s = Gtk::manage(new Gtk::HScale(el.GetMinValue<double>(), el.GetMaxValue<double>() + 0.01, 0.01)); #endif s->set_digits(2); s->set_value(el.GetValue<double>()); s->signal_value_changed().connect(sigc::bind(sigc::mem_fun(this, &ConfigElement::on_range_changed), s)); s->show(); pack_start(*s, true, true, 2); } else { // has at least one infinite (maxed) bound, use a spin button Gtk::SpinButton *s = Gtk::manage(new Gtk::SpinButton(0, 2)); double m = -std::numeric_limits<double>::max(), M = std::numeric_limits<double>::max(); if (el.HasMinValue()) m = el.GetMinValue<double>(); if (el.HasMaxValue()) M = el.GetMaxValue<double>(); s->set_range(m, M); s->set_increments(0.01, 1); s->set_value(el.GetValue<double>()); s->signal_value_changed().connect(sigc::bind(sigc::mem_fun(this, &ConfigElement::on_spin_changed), s)); s->show(); pack_start(*s, true, true, 2); } } else // string types { Gtk::Entry *e = Gtk::manage(new Gtk::Entry); e->set_text(el.GetValue<crn::StringUTF8>().CStr()); e->signal_changed().connect(sigc::bind(sigc::mem_fun(this, &ConfigElement::on_entry_changed), e)); e->show(); pack_start(*e, true, true, 2); } lab = Gtk::manage(new Gtk::Label("?")); lab->show(); lab->set_tooltip_text(el.GetDescription().CStr()); pack_start(*lab, false, true, 2); }
void DocumentProperties::setupFields (Glib::ustring const &docType) { Gtk::VBox *metadataBox; xml_->get_widget ("MetadataBox", metadataBox); if (metadataBox->children().size()) { metadataBox->children().erase(metadataBox->children().begin()); } DocumentType type = typeManager_.getType (docType); int const nRows = type.requiredFields_.size() + type.optionalFields_.size(); Gtk::Table *metadataTable = new Gtk::Table (nRows, 4, false); metadataTable->set_col_spacings (6); metadataTable->set_row_spacings (6); fieldEntries_.clear (); Gtk::Label *typeLabel = Gtk::manage (new Gtk::Label (_("_Type:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, true)); if (typecombochanged_) typecombochanged_.disconnect(); typeCombo_ = Gtk::manage (new Gtk::ComboBox); typeCombo_->set_model(typecombostore_); typeCombo_->pack_start(typelabelcol_, true); typeCombo_->pack_start(typebibtexnamecol_, false); typeLabel->set_mnemonic_widget (*typeCombo_); metadataTable->attach (*typeLabel, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK | Gtk::FILL, 0, 0); metadataTable->attach (*typeCombo_, 1, 4, 0, 1, Gtk::FILL, Gtk::SHRINK | Gtk::FILL, 0, 0); typecombostore_->clear(); for (DocumentTypeManager::TypesMap::iterator it = typeManager_.getTypes().begin(); it != typeManager_.getTypes().end(); ++it) { Gtk::TreeModel::Row row = *(typecombostore_->append()); row[typelabelcol_] = (*it).second.displayName_; row[typebibtexnamecol_] = (*it).second.bibtexName_; } typecombochanged_ = typeCombo_->signal_changed().connect ( sigc::mem_fun (*this, &DocumentProperties::onTypeChanged)); int row = 1; for ( std::vector<DocumentField>::iterator it = type.requiredFields_.begin(); it != type.requiredFields_.end(); ++it) { if (it->shortField_) continue; Gtk::Label *label = Gtk::manage (new Gtk::Label (it->displayName_ + ":", Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false)); Gtk::Entry *entry = Gtk::manage (new Gtk::Entry ()); /* [bert] Minor change to actually implement and register * a callback for changes to the DOI field. This is a bit * ugly here since it assumes we know whether DOI is * required or not. */ if (it->internalName_ == "doi") { entry->signal_changed().connect(sigc::mem_fun(*this, &DocumentProperties::onDoiEntryChanged)); } fieldEntries_[it->internalName_] = entry; metadataTable->attach (*label, 0, 1, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK | Gtk::FILL, 0, 0); metadataTable->attach (*entry, 1, 4, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK | Gtk::FILL, 0, 0); ++row; } for ( std::vector<DocumentField>::iterator it = type.optionalFields_.begin(); it != type.optionalFields_.end(); ++it) { if (it->shortField_) continue; Gtk::Label *label = Gtk::manage (new Gtk::Label (it->displayName_ + ":", Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false)); Gtk::Entry *entry = Gtk::manage (new Gtk::Entry ()); fieldEntries_[it->internalName_] = entry; metadataTable->attach (*label, 0, 1, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK | Gtk::FILL, 0, 0); metadataTable->attach (*entry, 1, 4, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK | Gtk::FILL, 0, 0); ++row; } int col = 0; for ( std::vector<DocumentField>::iterator it = type.requiredFields_.begin(); it != type.requiredFields_.end(); ++it) { if (!it->shortField_) continue; Gtk::Label *label = Gtk::manage (new Gtk::Label (it->displayName_ + ":", Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false)); Gtk::Entry *entry = Gtk::manage (new Gtk::Entry ()); fieldEntries_[it->internalName_] = entry; metadataTable->attach (*label, 0 + col * 2, 1 + col * 2, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK | Gtk::FILL, 0, 0); metadataTable->attach (*entry, 1 + col * 2, 2 + col * 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK | Gtk::FILL, 0, 0); ++col; if (col > 1) { ++row; col = 0; } } for ( std::vector<DocumentField>::iterator it = type.optionalFields_.begin(); it != type.optionalFields_.end(); ++it) { if (!it->shortField_) continue; Gtk::Label *label = Gtk::manage (new Gtk::Label (it->displayName_ + ":", Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, false)); Gtk::Entry *entry = Gtk::manage (new Gtk::Entry ()); fieldEntries_[it->internalName_] = entry; metadataTable->attach (*label, 0 + col * 2, 1 + col * 2, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::SHRINK | Gtk::FILL, 0, 0); metadataTable->attach (*entry, 1 + col * 2, 2 + col * 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK | Gtk::FILL, 0, 0); ++col; if (col > 1) { ++row; col = 0; } } metadataBox->pack_start (*metadataTable); metadataBox->show_all (); }