File indexing completed on 2024-04-28 03:51:14
0001 /* 0002 SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "clipboard.h" 0008 0009 #include <QApplication> 0010 #include <QBuffer> 0011 #include <QClipboard> 0012 #include <QDebug> 0013 #include <QMimeData> 0014 0015 #include <stepcore/factory.h> 0016 #include <stepcore/world.h> 0017 #include <stepcore/xmlfile.h> 0018 0019 namespace 0020 { 0021 class CopyHelper 0022 { 0023 public: 0024 void addItem(const StepCore::Item* item); 0025 StepCore::World* createWorld(); 0026 0027 private: 0028 void fillMap(const StepCore::Object* item, StepCore::Object* copy); 0029 void fixItemLinks(StepCore::Item* item); 0030 0031 QHash<const StepCore::Object*, StepCore::Object*> _copyMap; 0032 QList<StepCore::Item*> _items; 0033 }; 0034 0035 void CopyHelper::addItem(const StepCore::Item* item) 0036 { 0037 StepCore::Object *copy = item->metaObject()->cloneObject(*item); 0038 0039 _items << static_cast<StepCore::Item*>(copy); 0040 fillMap(item, copy); 0041 } 0042 0043 StepCore::World* CopyHelper::createWorld() 0044 { 0045 StepCore::World *world = new StepCore::World; 0046 0047 foreach (StepCore::Item* item, _items) { 0048 world->addItem(item); 0049 } 0050 0051 StepCore::ItemList items; 0052 world->allItems(&items); 0053 foreach (StepCore::Item* item, items) { 0054 fixItemLinks(item); 0055 } 0056 0057 _items.clear(); 0058 _copyMap.clear(); 0059 0060 return world; 0061 } 0062 0063 void CopyHelper::fillMap(const StepCore::Object* item, StepCore::Object* copy) 0064 { 0065 _copyMap.insert(item, copy); 0066 0067 if (item->metaObject()->inherits<StepCore::ItemGroup>()) { 0068 const StepCore::ItemGroup* group = 0069 static_cast<const StepCore::ItemGroup*>(item); 0070 StepCore::ItemGroup* copiedGroup = 0071 static_cast<StepCore::ItemGroup*>(copy); 0072 0073 StepCore::ItemList items; 0074 group->allItems(&items); 0075 StepCore::ItemList copiedItems; 0076 copiedGroup->allItems(&copiedItems); 0077 0078 for (StepCore::ItemList::size_type n = 0; n < items.size(); ++n) { 0079 _copyMap.insert(items[n], copiedItems[n]); 0080 } 0081 } 0082 } 0083 0084 void CopyHelper::fixItemLinks(StepCore::Item* item) 0085 { 0086 const StepCore::MetaObject* mobj = item->metaObject(); 0087 0088 for (int i = 0; i < mobj->propertyCount(); ++i) { 0089 const StepCore::MetaProperty* pr = mobj->property(i); 0090 0091 if (pr->userTypeId() == qMetaTypeId<StepCore::Object*>()) { 0092 QVariant v = pr->readVariant(item); 0093 StepCore::Object *obj = v.value<StepCore::Object*>(); 0094 StepCore::Object *copy = _copyMap.value(obj, nullptr); 0095 pr->writeVariant(item, QVariant::fromValue(copy)); 0096 } 0097 } 0098 } 0099 } 0100 0101 Clipboard::Clipboard(QObject* parent) : QObject(parent), _canPaste(hasData()) 0102 { 0103 connect(QApplication::clipboard(), &QClipboard::dataChanged, 0104 this, &Clipboard::dataChanged); 0105 } 0106 0107 0108 void Clipboard::copy(const QList<StepCore::Item*>& items) 0109 { 0110 CopyHelper helper; 0111 0112 foreach (const StepCore::Item* item, items) { 0113 helper.addItem(item); 0114 } 0115 0116 QScopedPointer<StepCore::World> world(helper.createWorld()); 0117 0118 QBuffer buffer; 0119 buffer.open(QBuffer::WriteOnly); 0120 StepCore::XmlFile xmlfile(&buffer); 0121 if (!xmlfile.save(world.data())) { 0122 // Serialization of items failed 0123 qWarning() << xmlfile.errorString(); 0124 return; 0125 } 0126 0127 QMimeData *mimedata = new QMimeData; 0128 mimedata->setData(QStringLiteral("application/x-step"), buffer.data()); 0129 0130 QClipboard *clipboard = QApplication::clipboard(); 0131 clipboard->setMimeData(mimedata); 0132 } 0133 0134 QList<StepCore::Item*> Clipboard::paste(const StepCore::Factory* factory) 0135 { 0136 QClipboard *clipboard = QApplication::clipboard(); 0137 const QMimeData *mimedata = clipboard->mimeData(); 0138 0139 if (!mimedata->hasFormat(QStringLiteral("application/x-step"))) { 0140 // No Step data available 0141 qWarning() << "No Step data on the clipboard"; 0142 return QList<StepCore::Item*>(); 0143 } 0144 0145 QByteArray data(mimedata->data(QStringLiteral("application/x-step"))); 0146 QBuffer buffer(&data); 0147 buffer.open(QBuffer::ReadOnly); 0148 StepCore::XmlFile xmlfile(&buffer); 0149 0150 StepCore::World world; 0151 if (!xmlfile.load(&world, factory)) { 0152 // Deserialization of items failed 0153 qCritical() << xmlfile.errorString(); 0154 return QList<StepCore::Item*>(); 0155 } 0156 0157 QList<StepCore::Item*> qitems; 0158 foreach (StepCore::Item* item, world.items()) { 0159 world.removeItem(item); 0160 qitems << item; 0161 } 0162 0163 return qitems; 0164 } 0165 0166 void Clipboard::dataChanged() 0167 { 0168 bool canPaste = hasData(); 0169 0170 if (canPaste != _canPaste) { 0171 _canPaste = canPaste; 0172 emit canPasteChanged(canPaste); 0173 } 0174 } 0175 0176 bool Clipboard::hasData() const 0177 { 0178 QClipboard *clipboard = QApplication::clipboard(); 0179 const QMimeData *mimedata = clipboard->mimeData(); 0180 0181 return mimedata->hasFormat(QStringLiteral("application/x-step")); 0182 } 0183 0184 #include "moc_clipboard.cpp"