//static QDomElement RKComponentMap::findOrCreateElement (QDomElement& parent, const QString& tagname, const QString& name, const QString& label, int index) { RK_TRACE (PLUGIN); XMLHelper* xml = XMLHelper::getStaticHelper (); XMLChildList list = xml->getChildElements (parent, QString::null, DL_INFO); // we need to look at all children, so we get the order right QDomElement insert_after_element; for (XMLChildList::const_iterator it=list.begin (); it != list.end (); ++it) { if ((tagname == (*it).tagName ()) && (name == xml->getStringAttribute ((*it), "name", "", DL_ERROR))) { return (*it); } else { if (index >= 0) { if (index > xml->getIntAttribute ((*it), "index", -1, DL_INFO)) { insert_after_element = *it; } } } } // element not found. Create a new one instead QDomElement ret = xmlguiBuildDocument ().createElement (tagname); ret.setAttribute ("name", name); ret.setAttribute ("index", index); if (!label.isEmpty ()) { QDomElement text = xmlguiBuildDocument ().createElement ("text"); text.appendChild (xmlguiBuildDocument ().createTextNode (label)); ret.appendChild (text); } parent.insertAfter (ret, insert_after_element); // if index_after_element.isNull, this add the new element as the last child of parent! return ret; }
int RKComponentMap::addSubMenu (QDomElement& parent, const QDomElement& description, const QString& cnamespace) { RK_TRACE (PLUGIN); int counter = 0; XMLHelper* xml = XMLHelper::getStaticHelper (); // 1: check whether menu already exists, and create new menu otherwise QDomElement menu_element = findOrCreateElement (parent, "Menu", xml->getStringAttribute (description, "id", "none", DL_ERROR), xml->getStringAttribute (description, "label", i18n ("(no label)"), DL_WARNING), xml->getIntAttribute (description, "index", -1, DL_INFO)); // 2: recurse into submenus (of element to add!) XMLChildList list = xml->getChildElements (description, "menu", DL_INFO); for (XMLChildList::const_iterator it=list.begin (); it != list.end (); ++it) { counter += addSubMenu (menu_element, (*it), cnamespace); } // 3: add entries list = xml->getChildElements (description, "entry", DL_INFO); for (XMLChildList::const_iterator it=list.begin (); it != list.end (); ++it) { QString id = cnamespace + xml->getStringAttribute ((*it), "component", "#invalid#", DL_ERROR); RKComponentHandle* handle = components[id]; if ((!handle) || (!handle->isPlugin ())) { RK_DO (qDebug ("No such component found while creating menu-entries or component is not a standalone plugin: \"%s\". No entry created.", id.latin1 ()), PLUGIN, DL_ERROR); } else { findOrCreateElement (menu_element, "Action", id, QString::null, xml->getIntAttribute ((*it), "index", -1, DL_INFO)); counter++; } } return counter; }
RKValueSelector::RKValueSelector (const QDomElement &element, RKComponent *parent_component, QWidget *parent_widget) : RKComponent (parent_component, parent_widget) { RK_TRACE (PLUGIN); updating = false; XMLHelper *xml = parent_component->xmlHelper (); standalone = element.tagName () == "select"; addChild ("selected", selected = new RKComponentPropertyStringList (this, false)); connect (selected, SIGNAL (valueChanged(RKComponentPropertyBase*)), this, SLOT (selectionPropertyChanged())); selected->setInternal (!standalone); addChild ("available", available = new RKComponentPropertyStringList (this, false)); connect (available, SIGNAL (valueChanged(RKComponentPropertyBase*)), this, SLOT (availablePropertyChanged())); available->setInternal (true); addChild ("labels", labels = new RKComponentPropertyStringList (this, false)); connect (labels, SIGNAL (valueChanged(RKComponentPropertyBase*)), this, SLOT (labelsPropertyChanged())); labels->setInternal (true); QVBoxLayout *vbox = new QVBoxLayout (this); vbox->setContentsMargins (0, 0, 0, 0); label_string = xml->i18nStringAttribute (element, "label", QString (), DL_INFO); if (!label_string.isNull ()) { QLabel *label = new QLabel (label_string, this); vbox->addWidget (label); } list_view = new QTreeView (this); list_view->setHeaderHidden (true); list_view->setSelectionMode (QAbstractItemView::ExtendedSelection); list_view->setRootIsDecorated (false); model = new QStringListModel (this); list_view->setModel (model); connect (list_view->selectionModel (), SIGNAL (selectionChanged(QItemSelection,QItemSelection)), this, SLOT (listSelectionChanged())); vbox->addWidget (list_view); XMLChildList options = xml->getChildElements (element, "option", DL_INFO); if (!options.isEmpty ()) { QStringList values_list; QStringList labels_list; QStringList selected_list; for (int i = 0; i < options.size (); ++i) { const QDomElement &child = options[i]; QString v = xml->getStringAttribute (child, "value", QString (), DL_WARNING); QString l = xml->i18nStringAttribute (child, "label", v, DL_INFO); if (xml->getBoolAttribute (child, "checked", false, DL_INFO)) selected_list.append (v); labels_list.append (l); values_list.append (v); } available->setValueList (values_list); labels->setValueList (labels_list); selected->setValueList (selected_list); } }
int RKComponentMap::addPluginMap (const QString& plugin_map_file) { RK_TRACE (PLUGIN); XMLHelper* xml = XMLHelper::getStaticHelper (); QDomElement element; XMLChildList list; QDomElement document_element = xml->openXMLFile (plugin_map_file, DL_ERROR); if (xml->highestError () >= DL_ERROR) return (0); QString prefix = QFileInfo (plugin_map_file).dirPath (true) + "/" + xml->getStringAttribute (document_element, "base_prefix", QString::null, DL_INFO); QString cnamespace = xml->getStringAttribute (document_element, "namespace", "rkward", DL_INFO) + "::"; // step 1: create (list of) components element = xml->getChildElement (document_element, "components", DL_INFO); list = xml->getChildElements (element, "component", DL_INFO); for (XMLChildList::const_iterator it=list.begin (); it != list.end (); ++it) { QString filename = prefix + xml->getStringAttribute((*it), "file", QString::null, DL_WARNING); QString id = cnamespace + xml->getStringAttribute((*it), "id", QString::null, DL_WARNING); int type = xml->getMultiChoiceAttribute ((*it), "type", "standard", 0, DL_WARNING); QString label = xml->getStringAttribute ((*it), "label", i18n ("(no label)"), DL_WARNING); if (components.contains (id)) { RK_DO (qDebug ("RKComponentMap already contains a component with id \"%s\". Ignoring second entry.", id.latin1 ()), PLUGIN, DL_WARNING); } else if (!QFileInfo (filename).isReadable ()) { RK_DO (qDebug ("Specified file '%s' for component id \"%s\" does not exist or is not readable. Ignoring.", filename.latin1 (), id.latin1 ()), PLUGIN, DL_ERROR); } else { components.insert (id, RKComponentHandle::createComponentHandle (filename, (RKComponentType) type, id, label)); } } // step 2: create / insert into menus QDomElement xmlgui_menubar_elem = xml->getChildElement (xmlguiBuildDocument ().documentElement (), "MenuBar", DL_ERROR); element = xml->getChildElement (document_element, "hierarchy", DL_INFO); list = xml->getChildElements (element, "menu", DL_INFO); int counter = 0; for (XMLChildList::const_iterator it=list.begin (); it != list.end (); ++it) { counter += addSubMenu (xmlgui_menubar_elem, (*it), cnamespace); } // step 3: included files QStringList includelist; list = xml->getChildElements (document_element, "include", DL_INFO); for (XMLChildList::const_iterator it=list.constBegin (); it != list.constEnd (); ++it) { QString file = prefix + xml->getStringAttribute (*it, "file", QString::null, DL_ERROR); if (QFileInfo (file).isReadable ()) { includelist.append (file); } else { RK_DO (qDebug ("Specified include file '%s' does not exist or is not readable. Ignoring.", file.latin1 ()), PLUGIN, DL_ERROR); } } for (QStringList::const_iterator it = includelist.constBegin (); it != includelist.constEnd (); ++it) { counter += addPluginMap (*it); } return counter; }
RKOptionSet::RKOptionSet (const QDomElement &element, RKComponent *parent_component, QWidget *parent_widget) : RKComponent (parent_component, parent_widget) { RK_TRACE (PLUGIN); XMLHelper *xml = XMLHelper::getStaticHelper (); updating = false; last_known_status = Processing; n_invalid_rows = n_unfinished_rows = 0; min_rows = xml->getIntAttribute (element, "min_rows", 0, DL_INFO); min_rows_if_any = xml->getIntAttribute (element, "min_rows_if_any", 1, DL_INFO); max_rows = xml->getIntAttribute (element, "max_rows", INT_MAX, DL_INFO); // build UI framework QVBoxLayout *layout = new QVBoxLayout (this); switcher = new QStackedWidget (this); layout->addWidget (switcher); user_area = new KVBox (this); switcher->addWidget (user_area); updating_notice = new QLabel (i18n ("Updating status, please wait"), this); switcher->addWidget (updating_notice); update_timer.setInterval (0); update_timer.setSingleShot (true); connect (&update_timer, SIGNAL (timeout()), this, SLOT (slotUpdateUnfinishedRows())); // create some meta properties serialization_of_set = new RKComponentPropertyBase (this, false); addChild ("serialized", serialization_of_set); connect (serialization_of_set, SIGNAL (valueChanged(RKComponentPropertyBase*)), this, SLOT (serializationPropertyChanged(RKComponentPropertyBase*))); row_count = new RKComponentPropertyInt (this, false, 0); row_count->setInternal (true); addChild ("row_count", row_count); // NOTE: read-only return_to_row = active_row = -1; current_row = new RKComponentPropertyInt (this, false, active_row); current_row->setInternal (true); addChild ("current_row", current_row); // NOTE: read-write connect (current_row, SIGNAL (valueChanged(RKComponentPropertyBase*)), this, SLOT (currentRowPropertyChanged(RKComponentPropertyBase*))); // first build the contents, as we will need to refer to the elements inside, later model = 0; display = 0; // will be created from the builder, on demand -> createDisplay () contents_container = new RKComponent (this, user_area); QDomElement content_element = xml->getChildElement (element, "content", DL_ERROR); RKComponentBuilder *builder = new RKComponentBuilder (contents_container, content_element); builder->buildElement (content_element, user_area, false); // NOTE that parent widget != parent component, here, by intention. The point is that the display should not be disabled along with the contents builder->parseLogic (xml->getChildElement (element, "logic", DL_INFO), false); builder->makeConnections (); addChild ("contents", contents_container); connect (standardComponent (), SIGNAL (standardInitializationComplete()), this, SLOT (fetchDefaults())); // create columns XMLChildList options = xml->getChildElements (element, "optioncolumn", DL_WARNING); QStringList visible_column_labels ("#"); // Optionally hidden first row for index for (int i = 0; i < options.size (); ++i) { const QDomElement &e = options.at (i); QString id = xml->getStringAttribute (e, "id", QString (), DL_ERROR); QString label = xml->getStringAttribute (e, "label", QString (), DL_DEBUG); QString governor = xml->getStringAttribute (e, "connect", QString (), DL_INFO); bool external = xml->getBoolAttribute (e, "external", false, DL_INFO); while (child_map.contains (id)) { RK_DEBUG (PLUGIN, DL_ERROR, "optionset already contains a property named %s. Renaming to _%s", qPrintable (id), qPrintable (id)); id = "_" + id; } ColumnInfo col_inf; col_inf.column_name = id; col_inf.external = external; col_inf.governor = governor; if (external && e.hasAttribute ("default")) col_inf.default_value = xml->getStringAttribute (e, "default", QString (), DL_ERROR); RKComponentPropertyStringList *column_property = new RKComponentPropertyStringList (this, false); column_property->setInternal (external); // Yes, looks strange, indeed. External properties should simply not be serialized / restored... addChild (id, column_property); connect (column_property, SIGNAL (valueChanged(RKComponentPropertyBase *)), this, SLOT (columnPropertyChanged(RKComponentPropertyBase *))); if (!label.isEmpty ()) { col_inf.display_index = visible_column_labels.size (); col_inf.column_label = label; visible_column_labels.append (label); visible_columns.append (column_property); } else { col_inf.display_index = -1; } column_map.insert (column_property, col_inf); } keycolumn = 0; QString keycol = xml->getStringAttribute (element, "keycolumn", QString (), DL_DEBUG); if (!keycol.isEmpty ()) { keycolumn = static_cast<RKComponentPropertyStringList*> (child_map.value (keycol)); if (!column_map.contains (keycolumn)) { RK_DEBUG (PLUGIN, DL_ERROR, "optionset does not contain an optioncolumn named %s. Falling back to manual insertion mode", qPrintable (keycol)); keycolumn = 0; } else if (!column_map[keycolumn].external) { RK_DEBUG (PLUGIN, DL_ERROR, "keycolumn (%s) is not marked as external. Falling back to manual insertion mode", qPrintable (keycol)); keycolumn = 0; } else { updating = true; keycolumn->setValue (KEYCOLUMN_UNINITIALIZED_VALUE); updating = false; } } QMap<RKComponentPropertyStringList *, ColumnInfo>::iterator it = column_map.begin (); for (; it != column_map.end (); ++it) { ColumnInfo &ci = it.value (); if (!ci.governor.isEmpty ()) { // there *can* be columns without governor for driven or connected option sets // Establish connections between columns and their respective governors. Since the format differs, the connection is done indirectly, through this component. // So, here, we set up a map of properties to columns, and connect to the change signals. RKComponentBase *governor = contents_container->lookupComponent (ci.governor, &ci.governor_modifier); if (governor && governor->isProperty ()) { RKComponentPropertyBase *gov_prop = static_cast<RKComponentPropertyBase*> (governor); if (ci.external) { if (!ci.governor_modifier.isEmpty ()) { RK_DEBUG (PLUGIN, DL_ERROR, "Cannot connect external column '%s' in optionset to property with modifier (%s).", qPrintable (ci.column_name), qPrintable (ci.governor)); continue; } } columns_to_update.insertMulti (gov_prop, it.key ()); connect (gov_prop, SIGNAL (valueChanged(RKComponentPropertyBase *)), this, SLOT (governingPropertyChanged(RKComponentPropertyBase *))); } else {