24 #include <KGenericFactory>
39 ki18nc(
"@title Displayed plugin name",
"Rocs Graph File Backend"),
41 ki18n(
"Read and write Rocs Graph Files"),
42 KAboutData::License_GPL_V2);
44 class RocsGraphFileFormatPluginPrivate
47 RocsGraphFileFormatPluginPrivate() :
58 d =
new RocsGraphFileFormatPluginPrivate;
70 << i18n(
"*.graph|Rocs Graph File Format") +
'\n';
82 QFile fileHandle(
file().toLocalFile());
84 if (!fileHandle.open(QIODevice::ReadOnly | QIODevice::Text)) {
91 QMap<int, DataPtr> dataMap;
93 QTextStream in(&fileHandle);
97 QString str = in.readLine().simplified();
99 if (str.startsWith(
'#')) {
101 }
else if (str.startsWith(QLatin1String(
"[Document Properties]"))) {
103 QString dataLine = in.readLine().simplified();
104 while (!in.atEnd() && !dataLine.isEmpty()) {
105 if (dataLine.startsWith(QLatin1String(
"DataStructurePlugin :"))) {
107 QString pluginIdentifier = dataLine.section(
' ', 2);
109 }
else if (!dataLine.isEmpty()) {
112 dataLine = in.readLine().simplified();
115 }
else if (str.startsWith(QLatin1String(
"[DataStructure"))) {
116 QString gName = str.section(
' ', 1, 1);
119 tmpObject = tmpDataStructure.get();
123 else if (str.startsWith(QLatin1String(
"X-plugin-")) && tmpObject &&
dynamic_cast<DataStructure*
>(tmpObject)) {
124 QString identifier = str.section(
':', 0, 0).trimmed().remove(
"X-plugin-");
125 QString
property = str.section(
':', 1, 1).trimmed();
129 else if (str.startsWith(QLatin1String(
"[DataType"))) {
130 QString identifier = str.section(
' ', 1);
131 identifier.remove(
']');
132 int tmpDataTypeId = identifier.toInt();
133 if (tmpDataTypeId != 0) {
135 if (tmpDataTypeId != identifier.toInt()) {
136 kWarning() <<
"Could not register already used data type << " << identifier.toInt()
137 <<
": use identifier " << tmpDataTypeId <<
" instead.";
142 QString dataLine = in.readLine().simplified();
143 while (!in.atEnd() && !dataLine.isEmpty()) {
144 if (dataLine.startsWith(QLatin1String(
"Name :"))) tmpDataType->setName(dataLine.section(
' ', 2));
145 else if (dataLine.startsWith(QLatin1String(
"IconName :"))) {
146 QString iconString = dataLine.section(
' ', 2);
148 tmpDataType->setIcon(iconString.remove(
"rocs_"));
149 }
else if (dataLine.startsWith(QLatin1String(
"Properties :"))) {
150 QStringList properties = dataLine.section(
' ', 2).split(
',');
151 foreach(
const QString& property, properties) {
152 if (!property.isEmpty()) {
153 tmpDataType->addProperty(property.section(
'=',0,0),
property.section(
'=',1));
156 }
else if (dataLine.startsWith(QLatin1String(
"Color :"))) tmpDataType->setDefaultColor(QColor(dataLine.section(
' ', 2)));
157 else if (!dataLine.isEmpty())
break;
158 dataLine = in.readLine().simplified();
162 else if (str.startsWith(QLatin1String(
"[PointerType"))) {
163 QString identifier = str.section(
' ', 1);
164 identifier.remove(
']');
165 int tmpPointerTypeId = identifier.toInt();
166 if (tmpPointerTypeId != 0) {
168 if (tmpPointerTypeId != identifier.toInt()) {
169 kWarning() <<
"Could not register already used pointer type << " << identifier.toInt()
170 <<
": use identifier " << tmpPointerTypeId <<
" instead.";
175 QString dataLine = in.readLine().simplified();
176 while (!in.atEnd() && !dataLine.isEmpty()) {
177 if (dataLine.startsWith(QLatin1String(
"Name :"))) {
178 tmpPointerType->setName(dataLine.section(
' ', 2));
179 }
else if (dataLine.startsWith(QLatin1String(
"Color :"))) {
180 tmpPointerType->setDefaultColor(QColor(dataLine.section(
' ', 2)));
181 }
else if (dataLine.startsWith(QLatin1String(
"Direction :"))) {
182 if (dataLine.section(
' ', 2) ==
"bidirectional") {
184 }
else if (dataLine.section(
' ', 2) ==
"unidirectional") {
188 kWarning() <<
"Direction unset, use default direction of this data type backend.";
190 }
else if (dataLine.startsWith(QLatin1String(
"LineStyle :"))) {
191 tmpPointerType->setLineStyle(Qt::PenStyle(dataLine.section(
' ', 2).toInt()));
192 }
else if (dataLine.startsWith(QLatin1String(
"Properties :"))) {
193 QStringList properties = dataLine.section(
' ', 2).split(
',');
194 foreach(
const QString& property, properties) {
195 if (!property.isEmpty()) {
196 tmpPointerType->addProperty(property.section(
'=',0,0),
property.section(
'=',1));
199 }
else if (!dataLine.isEmpty()) {
202 dataLine = in.readLine().simplified();
206 else if (str.startsWith(QLatin1String(
"[Data "))) {
209 QString dataLine = in.readLine().simplified();
216 while (!in.atEnd() && !dataLine.isEmpty()) {
217 if (dataLine.startsWith(QLatin1String(
"x :"))) posX = dataLine.section(
' ', 2).toFloat();
218 else if (dataLine.startsWith(QLatin1String(
"y :"))) posY = dataLine.section(
' ', 2).toFloat();
219 else if (dataLine.startsWith(QLatin1String(
"type :"))) type = dataLine.section(
' ', 2).toInt();
220 else if (dataLine.startsWith(QLatin1String(
"value :"))) value = dataLine.section(
' ', 2);
221 else if (dataLine.startsWith(QLatin1String(
"color :"))) color = dataLine.section(
' ', 2);
222 else if (dataLine.startsWith(QLatin1String(
"name :"))) name = dataLine.section(
' ', 2);
223 else if (!dataLine.isEmpty())
break;
224 dataLine = in.readLine().simplified();
227 tmpData = tmpDataStructure->createData(name, type);
229 kDebug() <<
"Create data element of type 0, since type " << type <<
" was not registered.";
230 tmpData = tmpDataStructure->createData(name, 0);
233 tmpData->setColor(color);
234 tmpData->setPos(posX, posY);
237 QString identifier = str.section(
' ', 1);
238 identifier.remove(
']');
239 dataMap.insert(identifier.toInt(), tmpData);
240 tmpObject = tmpData.get();
244 else if (str.startsWith(QLatin1String(
"[Pointer "))) {
246 QString eName = str.section(
' ', 1, 1);
249 QString nameFrom = eName.section(
"->", 0, 0);
250 QString nameTo = eName.section(
"->", 1, 1);
252 QString dataLine = in.readLine().simplified();
257 while (!in.atEnd() && !dataLine.isEmpty()) {
258 if (dataLine.startsWith(QLatin1String(
"width :"))) width = dataLine.section(
' ', 2).toInt();
259 else if (dataLine.startsWith(QLatin1String(
"value :"))) value = dataLine.section(
' ', 2);
260 else if (dataLine.startsWith(QLatin1String(
"type :"))) type = dataLine.section(
' ', 2).toInt();
261 else if (dataLine.startsWith(QLatin1String(
"color :"))) color = dataLine.section(
' ', 2);
262 else if (!dataLine.isEmpty())
break;
263 dataLine = in.readLine().simplified();
266 tmpPointer = tmpDataStructure->createPointer(dataMap[nameFrom.toInt()],dataMap[nameTo.toInt()], type);
268 kDebug() <<
"Create pointer of type 0, since type " << type <<
" was not registered.";
269 tmpPointer = tmpDataStructure->createPointer(dataMap[nameFrom.toInt()],dataMap[nameTo.toInt()], 0);
272 tmpPointer->setWidth(width);
273 tmpPointer->setColor(color);
274 tmpObject = tmpPointer.get();
278 else if (str.startsWith(QLatin1String(
"[Group"))) {
284 else if (str.contains(
':')) {
285 QString propertyName = str.section(
':', 0, 0).trimmed();
286 QString propertyValue = str.section(
':', 1, 1).trimmed();
287 if (!propertyName.isEmpty()) {
288 tmpObject->setProperty(propertyName.toUtf8() , propertyValue);
298 KSaveFile saveFile(!
file().toLocalFile().endsWith(
".graph") ? QString(
"%1.graph").arg(
file().toLocalFile()) :
file().toLocalFile());
300 if (!saveFile.open()) {
305 QTextStream stream(&saveFile);
306 stream.setCodec(
"UTF-8");
309 stream << d->_buffer;
311 if (!saveFile.finalize()) {
324 d->_buffer = QString(
"[Document Properties] \n")
328 foreach(
int dataTypeIdentifier, document.
dataTypeList()) {
329 QStringList properties;
330 foreach (
const QString& property, document.
dataType(dataTypeIdentifier)->properties()) {
331 properties.append(property + QString(
'=') + document.
dataType(dataTypeIdentifier)->propertyDefaultValue(property).toString());
334 d->_buffer += QString(
"[DataType %1]").arg(QString::number(dataTypeIdentifier)) % QChar(
'\n')
335 % QString(
"Name : ") % document.
dataType(dataTypeIdentifier)->name() % QChar(
'\n')
336 % QString(
"IconName : ") % document.
dataType(dataTypeIdentifier)->iconName() % QChar(
'\n')
337 % QString(
"Color : ") % document.
dataType(dataTypeIdentifier)->defaultColor().name() % QChar(
'\n')
338 % QString(
"Properties : ") % properties.join(QChar(
','))
340 d->_buffer += QChar(
'\n');
344 QStringList properties;
345 foreach (
const QString& property, document.
pointerType(pointerTypeIdentifier)->properties()) {
346 properties.append(property + QString(
'=') + document.
pointerType(pointerTypeIdentifier)->propertyDefaultValue(property).toString());
354 d->_buffer += QString(
"[PointerType %1]").arg(QString::number(pointerTypeIdentifier)) % QChar(
'\n')
355 % QString(
"Name : ") % document.
pointerType(pointerTypeIdentifier)->name() % QChar(
'\n')
356 % QString(
"Color : ") % document.
pointerType(pointerTypeIdentifier)->defaultColor().name() % QChar(
'\n')
357 % QString(
"LineStyle : ") % QString::number(document.
pointerType(pointerTypeIdentifier)->lineStyle()) % QChar(
'\n')
358 % QString(
"Direction : ") % direction % QChar(
'\n')
359 % QString(
"Properties : ") % properties.join(QChar(
','))
361 d->_buffer += QChar(
'\n');
365 QList<DataStructurePtr>::const_iterator dataStructure = document.
dataStructures().constBegin();
368 d->_buffer += QString(
"[DataStructure %1] \n").arg(identifier++).toUtf8();
369 QMap<QString, QString> properties = (*dataStructure)->pluginProperties();
370 QMap<QString, QString>::const_iterator propertyIter = properties.constBegin();
371 while (propertyIter != properties.constEnd()) {
372 d->_buffer += QString(
"X-plugin-%1 : %2").arg(propertyIter.key()).arg(propertyIter.value()) % QChar(
'\n');
376 serializeProperties(dataStructure->get());
379 foreach(
DataPtr n, (*dataStructure)->dataList(type)) {
380 d->_buffer += QString(
"[Data %1]\n").arg(QString::number(n->identifier()));
381 d->_buffer += QString(
"type : ") % QString::number(n->dataType()) % QChar(
'\n');
382 serializeProperties(n.get());
387 foreach(
PointerPtr e, (*dataStructure)->pointers(type)) {
388 d->_buffer += QString(
"[Pointer %1->%2]\n").
389 arg(QString::number(e->from()->identifier())).
390 arg(QString::number(e->to()->identifier())).toUtf8();
391 d->_buffer += QString(
"type : ") % QString::number(e->pointerType()) % QChar(
'\n');
392 serializeProperties(e.get());
397 kDebug() <<
"------- /// BEGIN internal file format /// -------";
398 kDebug() << d->_buffer;
399 kDebug() <<
"------- /// internal file format END /// -------";
405 void RocsGraphFileFormatPlugin::serializeProperties(
QObject *o)
407 const QMetaObject *metaObject = o->metaObject();
408 int propertyCount = metaObject->propertyCount();
410 for (
int i = 0; i < propertyCount; ++i) {
411 QMetaProperty metaProperty = metaObject->property(i);
412 const char *name = metaProperty.name();
413 QVariant value = o->property(name);
415 if (QString(
"objectName").compare(metaProperty.name()) == 0) {
417 }
else if (QString(
"name").compare(metaProperty.name()) == 0) {
418 QString namevalue = QString(
"%1 : %2 \n").arg(name).arg(value.toString());
421 d->_buffer += QString(
"%1 : %2 \n").arg(name, value.toString());
424 QList<QByteArray> propertyNames = o->dynamicPropertyNames();
425 foreach(
const QByteArray & name, propertyNames) {
426 QVariant value = o->property(name);
427 d->_buffer += QString(
"%1 : %2 \n").arg(name, value.toString()).toUtf8();
virtual void setPluginProperty(const QString &, const QString &)
Set plugin specific properties of data structure.
int registerDataType(const QString &name, int identifier=0)
Register new type for data elements.
DataStructureBackendInterface * activeBackend() const
Returns the currently active data structure backend.
boost::shared_ptr< PointerType > PointerTypePtr
boost::shared_ptr< DataStructure > DataStructurePtr
static DataStructureBackendManager & self()
Returns self reference to backend manager.
boost::shared_ptr< Pointer > PointerPtr
void setBackend(const QString &pluginIdentifier)
Set data structure plugin for this document.
void setError(Error error, QString message=QString())
DataStructurePtr addDataStructure(const QString &name=QString())
Add data structure to graph document with name name.
int registerPointerType(const QString &name, int identifier=0)
Register new type for pointers.
PointerTypePtr pointerType(int pointerType) const
void remove(DataStructurePtr dataStructure)
QList< DataStructurePtr > & dataStructures() const
boost::shared_ptr< Data > DataPtr
QList< int > pointerTypeList() const
Getter for all registered pointer types.
DataTypePtr dataType(int dataType) const
boost::shared_ptr< DataType > DataTypePtr
QString internalName()
return the internal name from plugin.
QList< int > dataTypeList() const
Getter for all registered data types.
void setGraphDocument(Document *document)
const KUrl & file() const
This class provides an interface for graph file format plugins.
void setFileUrl(const KUrl &fileUrl)
Set file path used for saving.