From a2daa67af4d354a3986bf7f51238a8079095212b Mon Sep 17 00:00:00 2001 From: Ars Masiuk Date: Mon, 4 Feb 2019 23:57:02 +0100 Subject: [PATCH] qvge 0.5.3 --- CHANGES | 16 ++ src/3rdParty/qsint-widgets/qsplitbutton.cpp | 6 +- src/appbase/CMainWindow.cpp | 199 +++++++++++------ src/appbase/CMainWindow.h | 20 +- src/appbase/CPlatformServices.cpp | 12 + src/appbase/CPlatformServices.h | 2 + src/appbase/CStartPage.cpp | 115 ++++++++++ src/appbase/CStartPage.h | 29 +++ src/appbase/CStartPage.ui | 145 ++++++++++++ src/appbase/appbase.pri | 2 +- src/commonui/CAttributesEditorUI.cpp | 2 +- src/commonui/CAttributesEditorUI.h | 2 +- src/commonui/CClassAttributesEditorUI.cpp | 2 +- src/commonui/CClassAttributesEditorUI.h | 2 +- src/commonui/CCommutationTable.cpp | 2 +- src/commonui/CCommutationTable.h | 2 +- src/commonui/CDOTExportDialog.cpp | 28 +++ src/commonui/CDOTExportDialog.h | 25 +++ src/commonui/CDOTExportDialog.ui | 107 +++++++++ src/commonui/CNewAttributeDialog.cpp | 2 +- src/commonui/CNewAttributeDialog.h | 2 +- src/commonui/CNodeEdgePropertiesUI.cpp | 21 +- src/commonui/CNodeEdgePropertiesUI.h | 5 +- src/commonui/CNodeEdgePropertiesUI.ui | 66 ++++-- src/commonui/CNodeEditorUIController.cpp | 93 ++++---- src/commonui/CNodeEditorUIController.h | 11 +- src/commonui/CSceneMenuUIController.cpp | 18 +- src/commonui/CSceneMenuUIController.h | 5 + src/commonui/CSceneOptionsDialog.cpp | 2 +- src/commonui/CSceneOptionsDialog.h | 2 +- src/commonui/CSearchDialog.cpp | 2 +- src/commonui/CSearchDialog.h | 2 +- src/commonui/commonui.qrc | 3 + src/qvge/CAttribute.cpp | 2 +- src/qvge/CAttribute.h | 2 +- src/qvge/CControlPoint.cpp | 2 +- src/qvge/CControlPoint.h | 2 +- src/qvge/CDiffUndoManager.cpp | 2 +- src/qvge/CDiffUndoManager.h | 2 +- src/qvge/CDirectEdge.cpp | 2 +- src/qvge/CDirectEdge.h | 2 +- src/qvge/CEdge.cpp | 2 +- src/qvge/CEdge.h | 2 +- src/qvge/CEditorScene.cpp | 235 +++++++++++++++----- src/qvge/CEditorScene.h | 40 +++- src/qvge/CEditorSceneActions.cpp | 44 ++++ src/qvge/CEditorSceneActions.h | 28 +++ src/qvge/CEditorSceneDefines.h | 5 +- src/qvge/CEditorView.cpp | 62 +----- src/qvge/CEditorView.h | 6 +- src/qvge/CFileSerializerCSV.cpp | 2 +- src/qvge/CFileSerializerCSV.h | 2 +- src/qvge/CFileSerializerDOT.cpp | 52 +++-- src/qvge/CFileSerializerDOT.h | 11 +- src/qvge/CFileSerializerGEXF.cpp | 6 +- src/qvge/CFileSerializerGEXF.h | 2 +- src/qvge/CFileSerializerGraphML.cpp | 2 +- src/qvge/CFileSerializerGraphML.h | 2 +- src/qvge/CFileSerializerXGR.cpp | 2 +- src/qvge/CFileSerializerXGR.h | 2 +- src/qvge/CImageExport.cpp | 12 +- src/qvge/CItem.cpp | 2 +- src/qvge/CItem.h | 2 +- src/qvge/CNode.cpp | 6 + src/qvge/CNode.h | 13 +- src/qvge/CNodeEditorScene.cpp | 45 ++++ src/qvge/CNodeEditorScene.h | 8 +- src/qvge/CNodePort.cpp | 2 +- src/qvge/CNodePort.h | 2 +- src/qvge/CNodeSceneActions.cpp | 4 +- src/qvge/CNodeSceneActions.h | 6 +- src/qvge/CPDFExport.cpp | 11 +- src/qvge/CPolyEdge.cpp | 2 +- src/qvge/CPolyEdge.h | 2 +- src/qvge/CSimpleUndoManager.cpp | 2 +- src/qvge/CSimpleUndoManager.h | 2 +- src/qvge/CTextLabelEdit.cpp | 12 +- src/qvge/CTextLabelEdit.h | 2 +- src/qvge/CUtils.cpp | 10 + src/qvge/CUtils.h | 5 +- src/qvge/IFileExport.h | 2 +- src/qvge/IFileSerializer.h | 2 +- src/qvge/ISceneItemFactory.h | 2 +- src/qvge/IUndoManager.h | 2 +- src/qvge/Properties.h | 2 +- src/qvgeapp/main.cpp | 6 +- src/qvgeapp/qvgeMainWindow.cpp | 4 +- src/qvgeapp/qvgeMainWindow.h | 2 +- src/qvgeapp/qvgeVersion.h | 4 +- src/qvgeapp/qvgeapp.pro | 4 +- src/qvgeio/CFormatGraphML.cpp | 65 +++++- src/qvgeio/CFormatGraphML.h | 4 +- src/qvgeio/CGraphBase.cpp | 2 +- src/qvgeio/CGraphBase.h | 2 +- 94 files changed, 1323 insertions(+), 405 deletions(-) create mode 100644 src/appbase/CStartPage.cpp create mode 100644 src/appbase/CStartPage.h create mode 100644 src/appbase/CStartPage.ui create mode 100644 src/commonui/CDOTExportDialog.cpp create mode 100644 src/commonui/CDOTExportDialog.h create mode 100644 src/commonui/CDOTExportDialog.ui create mode 100644 src/qvge/CEditorSceneActions.cpp create mode 100644 src/qvge/CEditorSceneActions.h diff --git a/CHANGES b/CHANGES index 1f0cf32b..8b472f71 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,19 @@ +QVGE 0.5.3 +------------------------------------------------------------------------------- +- default paste behavior modified: items will be preferably pasted into a visible scene's area +- selection copied to clipboard can be pasted as an image to any software +- DOT export: scene background attribute exported as well +- DOT export: extended to optionally export only the topology (#63) +- added more action hints +- added fast movement of the selected items by Shift + Arrow keys +- added start page with common file actions (#59) +- added exit out of the complete application (with all windows) + +- fixed crash on deleting items via Cut or Delete actions (#55) +- fixed some item selection issues +- fixed export of image and PDF documents (auto crop added as well) + + QVGE 0.5.2 ------------------------------------------------------------------------------- - View Menu: added Toolbars & Panels submenu (#52) diff --git a/src/3rdParty/qsint-widgets/qsplitbutton.cpp b/src/3rdParty/qsint-widgets/qsplitbutton.cpp index bb586814..f65de342 100644 --- a/src/3rdParty/qsint-widgets/qsplitbutton.cpp +++ b/src/3rdParty/qsint-widgets/qsplitbutton.cpp @@ -94,6 +94,9 @@ void QSplitButton::actionEvent(QActionEvent *event) void QSplitButton::onAction(QAction* act) { setDefaultAction(act); + + if (act) + Q_EMIT activated(act->data()); } @@ -109,9 +112,6 @@ void QSplitButton::setDefaultAction(QAction* act) if (statusTip().isEmpty()) setStatusTip(oldStatusTip); - - if (act) - Q_EMIT activated(act->data()); } } diff --git a/src/appbase/CMainWindow.cpp b/src/appbase/CMainWindow.cpp index 56fec544..e60b53b2 100644 --- a/src/appbase/CMainWindow.cpp +++ b/src/appbase/CMainWindow.cpp @@ -1,5 +1,6 @@ #include "CMainWindow.h" #include "CPlatformServices.h" +#include "CStartPage.h" #include #include @@ -46,6 +47,25 @@ void CMainWindow::onQuit() } +void CMainWindow::exit() +{ + // close all instances + QVariantMap pidFileMap = getActiveInstances(); + for (auto it = pidFileMap.constBegin(); it != pidFileMap.constEnd(); ++it) + { + bool isCurrent = (m_stringPID == it.key()); + if (!isCurrent) + { + QVariantMap dataMap = it.value().value(); + CPlatformServices::CloseWindow(dataMap["hwnd"].toUInt()); + } + } + + // close me as well + close(); +} + + void CMainWindow::addDocument(const CDocument& doc) { if (doc.canCreate) @@ -86,6 +106,8 @@ void CMainWindow::init(const QStringList& args) readSettings(); + createStartPage(); + processParams(args); } @@ -150,7 +172,7 @@ void CMainWindow::processParams(const QStringList& args) if (command == "create") { - doCreateNewDocument(args.at(2).toLocal8Bit()); + createNewDocument(args.at(2).toLocal8Bit()); return; } @@ -205,8 +227,12 @@ void CMainWindow::createMainMenu() m_fileMenu->addSeparator(); - QAction *exitApp = m_fileMenu->addAction(tr("E&xit"), this, SLOT(close())); - exitApp->setStatusTip(tr("Leave the application")); + QAction *closeDocument = m_fileMenu->addAction(tr("Close"), this, SLOT(close())); + closeDocument->setStatusTip(tr("Close current document")); + closeDocument->setShortcut(QKeySequence::Close); + + QAction *exitApp = m_fileMenu->addAction(tr("E&xit"), this, SLOT(exit())); + exitApp->setStatusTip(tr("Leave the application closing all windows")); exitApp->setShortcut(QKeySequence::Quit); } @@ -261,6 +287,13 @@ void CMainWindow::createFileToolbar() } +void CMainWindow::createStartPage() +{ + CStartPage *startPage = new CStartPage(this); + setCentralWidget(startPage); +} + + void CMainWindow::updateTitle() { setWindowTitle(QString("%1 - %2") @@ -309,18 +342,18 @@ void CMainWindow::onCurrentFileChanged() void CMainWindow::createNewDocument() { - doCreateNewDocument(*m_docTypeCreate.begin()); + createNewDocument(*m_docTypeCreate.begin()); } void CMainWindow::createNewDocument(QAction *act) { QByteArray docType = act->data().toByteArray(); - doCreateNewDocument(docType); + createNewDocument(docType); } -void CMainWindow::doCreateNewDocument(const QByteArray &docType) +void CMainWindow::createNewDocument(const QByteArray &docType) { // document presents - run new instance if (m_currentDocType.size()) @@ -362,6 +395,18 @@ bool CMainWindow::createDocument(const QByteArray &docType) } +void CMainWindow::selectAndOpenDocument() +{ + on_actionOpen_triggered(); +} + + +bool CMainWindow::openDocument(const QString &fileName) +{ + return doOpenDocument(fileName); +} + + void CMainWindow::on_actionOpen_triggered() { QString title = tr("Open File"); @@ -641,12 +686,20 @@ bool CMainWindow::saveOnExit() // recent files management +QStringList CMainWindow::getRecentFilesList() const +{ + QSettings &settings = getApplicationSettings(); + + return settings.value("recentFiles").toStringList(); +} + + void CMainWindow::updateRecentFiles() { if (m_currentFileName.isEmpty()) return; - QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); + QSettings &settings = getApplicationSettings(); QStringList recentFiles = settings.value("recentFiles").toStringList(); int index = recentFiles.indexOf(m_currentFileName); @@ -672,7 +725,7 @@ void CMainWindow::fillRecentFilesMenu() { m_recentFilesMenu->clear(); - QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); + QSettings &settings = getApplicationSettings(); QStringList recentFiles = settings.value("recentFiles").toStringList(); @@ -692,7 +745,7 @@ void CMainWindow::onRecentFilesMenuAction(QAction *recentAction) return; // failed - remove - QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); + QSettings &settings = getApplicationSettings(); QStringList recentFiles = settings.value("recentFiles").toStringList(); recentFiles.removeAt(recentAction->data().toInt()); @@ -703,10 +756,40 @@ void CMainWindow::onRecentFilesMenuAction(QAction *recentAction) // instance management -void CMainWindow::updateInstance() +QVariantMap CMainWindow::getActiveInstances() { QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); + QVariantMap pidFileMap = settings.value("instances").value(); + + CPlatformServices::PIDs livingPids = CPlatformServices::GetRunningPIDs(); + bool mapUpdated = false; + + // check if alive + QList spids = pidFileMap.keys(); + for (auto spid : spids) + { + if (!livingPids.contains(spid.toUInt())) + { + pidFileMap.remove(spid); + mapUpdated = true; + } + } + + // write cleaned map back + if (mapUpdated) + { + settings.setValue("instances", pidFileMap); + } + + return pidFileMap; +} + + +void CMainWindow::updateInstance() +{ + QSettings &settings = getApplicationSettings(); + QVariantMap pidFileMap = settings.value("instances").value(); QVariantMap dataMap = pidFileMap[m_stringPID].value(); dataMap["title"] = m_mainTitleText; @@ -720,7 +803,7 @@ void CMainWindow::updateInstance() void CMainWindow::removeInstance() { - QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); + QSettings &settings = getApplicationSettings(); QVariantMap pidFileMap = settings.value("instances").value(); pidFileMap.remove(m_stringPID); @@ -728,33 +811,42 @@ void CMainWindow::removeInstance() } -QVariantMap CMainWindow::getActiveInstances() +bool CMainWindow::activateInstance(const QString &fileName) { - QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); + QString normalizedName = fileName; // QDir::toNativeSeparators(QFileInfo(fileName).canonicalFilePath()); +#ifdef WIN32 + normalizedName = normalizedName.toLower(); +#endif - QVariantMap pidFileMap = settings.value("instances").value(); + // current instance? + if (normalizedName == m_currentFileName) + { + raise(); + activateWindow(); + return true; + } - CPlatformServices::PIDs livingPids = CPlatformServices::GetRunningPIDs(); - bool mapUpdated = false; + // else check running instances + QVariantMap pidFileMap = getActiveInstances(); - // check if alive - QList spids = pidFileMap.keys(); - for (auto spid: spids) + for (auto it = pidFileMap.constBegin(); it != pidFileMap.constEnd(); ++it) { - if (!livingPids.contains(spid.toUInt())) + QVariantMap dataMap = it.value().value(); + + QString fileName = dataMap["file"].toString(); +#ifdef WIN32 + fileName = fileName.toLower(); +#endif + + if (normalizedName == fileName) { - pidFileMap.remove(spid); - mapUpdated = true; + // found: switch to instance + CPlatformServices::SetActiveWindow(dataMap["hwnd"].toUInt()); + return true; } } - // write cleaned map back - if (mapUpdated) - { - settings.setValue("instances", pidFileMap); - } - - return pidFileMap; + return false; } @@ -802,45 +894,6 @@ void CMainWindow::onWindowsMenuAction(QAction *windowAction) } -bool CMainWindow::activateInstance(const QString &fileName) -{ - QString normalizedName = fileName; // QDir::toNativeSeparators(QFileInfo(fileName).canonicalFilePath()); -#ifdef WIN32 - normalizedName = normalizedName.toLower(); -#endif - - // current instance? - if (normalizedName == m_currentFileName) - { - raise(); - activateWindow(); - return true; - } - - // else check running instances - QVariantMap pidFileMap = getActiveInstances(); - - for (auto it = pidFileMap.constBegin(); it != pidFileMap.constEnd(); ++it) - { - QVariantMap dataMap = it.value().value(); - - QString fileName = dataMap["file"].toString(); -#ifdef WIN32 - fileName = fileName.toLower(); -#endif - - if (normalizedName == fileName) - { - // found: switch to instance - CPlatformServices::SetActiveWindow(dataMap["hwnd"].toUInt()); - return true; - } - } - - return false; -} - - // help void CMainWindow::createHelpMenu() @@ -871,7 +924,7 @@ QString CMainWindow::getAboutText() const // settings -QSettings& CMainWindow::getApplicationSettings() +QSettings& CMainWindow::getApplicationSettings() const { static QSettings settings(QCoreApplication::organizationName(), QCoreApplication::applicationName()); return settings; @@ -890,14 +943,16 @@ void CMainWindow::readSettings() void CMainWindow::doReadSettings(QSettings& settings) { + showNormal(); + + // window geometry const QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray(); if (geometry.isEmpty()) { const QRect availableGeometry = QApplication::desktop()->availableGeometry(this); - resize(availableGeometry.width() / 3, availableGeometry.height() / 2); - move((availableGeometry.width() - width()) / 2, - (availableGeometry.height() - height()) / 2); + resize(availableGeometry.width()-200, availableGeometry.height()-100); + move(100, 50); } else { restoreGeometry(geometry); diff --git a/src/appbase/CMainWindow.h b/src/appbase/CMainWindow.h index 287d9e70..3e386f16 100644 --- a/src/appbase/CMainWindow.h +++ b/src/appbase/CMainWindow.h @@ -40,14 +40,15 @@ class CMainWindow : public QMainWindow virtual void init(const QStringList& args); - void addDocument(const CDocument& doc); - QDockWidget* createDockWindow(const QString& name, const QString& title, Qt::DockWidgetArea area, QWidget* widget = nullptr); - virtual void readSettings(); - virtual void writeSettings(); + virtual QSettings& getApplicationSettings() const; + virtual void readSettings(); + virtual void writeSettings(); - virtual QSettings& getApplicationSettings(); + void addDocument(const CDocument& doc); + QList getRegisteredDocumentTypes() const { return m_docTypes.values(); } + QStringList getRecentFilesList() const; QAction* getFileExportAction() { return m_exportDocument; } QMenu* getFileMenu() { return m_fileMenu; } @@ -58,6 +59,11 @@ public Q_SLOTS: virtual void onDocumentChanged(); virtual void onAboutApplication(); + virtual void createNewDocument(const QByteArray &docType); + + void selectAndOpenDocument(); + bool openDocument(const QString &fileName); + protected: void closeEvent(QCloseEvent *event); @@ -71,6 +77,8 @@ public Q_SLOTS: virtual void createMainMenu(); virtual void createWindowsMenu(); virtual void createHelpMenu(); + + virtual void createStartPage(); virtual void fillNewFileMenu(); virtual void createFileToolbar(); @@ -81,7 +89,6 @@ public Q_SLOTS: virtual void updateTitle(); virtual QString getAboutText() const; - virtual void doCreateNewDocument(const QByteArray &docType); virtual bool createDocument(const QByteArray &docType); virtual void onNewDocumentCreated(const QByteArray &docType) {} @@ -121,6 +128,7 @@ protected Q_SLOTS: void onWindowsMenuAction(QAction*); private Q_SLOTS: + void exit(); void onQuit(); protected: diff --git a/src/appbase/CPlatformServices.cpp b/src/appbase/CPlatformServices.cpp index 2829b4a9..86229df4 100644 --- a/src/appbase/CPlatformServices.cpp +++ b/src/appbase/CPlatformServices.cpp @@ -61,6 +61,18 @@ bool CPlatformServices::SetActiveWindow(uint id) } +bool CPlatformServices::CloseWindow(uint id) +{ + HWND hWnd = (HWND)id; + if (!hWnd) + return false; + + int result = SendMessage(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0); + + return true; +} + + CPlatformServices::PIDs CPlatformServices::GetRunningPIDs() { PIDs result; diff --git a/src/appbase/CPlatformServices.h b/src/appbase/CPlatformServices.h index 2446eb46..17b4d0a9 100644 --- a/src/appbase/CPlatformServices.h +++ b/src/appbase/CPlatformServices.h @@ -9,6 +9,8 @@ class CPlatformServices public: static bool SetActiveWindow(uint id); + static bool CloseWindow(uint id); + typedef QSet PIDs; static PIDs GetRunningPIDs(); diff --git a/src/appbase/CStartPage.cpp b/src/appbase/CStartPage.cpp new file mode 100644 index 00000000..3d54bd80 --- /dev/null +++ b/src/appbase/CStartPage.cpp @@ -0,0 +1,115 @@ +#include "CStartPage.h" +#include "CMainWindow.h" + +#include +#include +#include +#include + + +CStartPage::CStartPage(CMainWindow *parent) : QWidget(parent) +{ + ui.setupUi(this); + + m_parent = parent; + + createActions(); + createRecentDocs(); +} + +CStartPage::~CStartPage() +{ +} + + +void CStartPage::createActions() +{ + const auto &docTypes = m_parent->getRegisteredDocumentTypes(); + + // create document actions + for (auto &doc : docTypes) + { + if (doc.canCreate) + { + QCommandLinkButton *newFileButton = new QCommandLinkButton( + tr("Create") + " " + doc.name, doc.description, this + ); + + newFileButton->setIcon(QIcon(":/Icons/New")); + + QAction *newFile = new QAction(newFileButton); + newFile->setData(doc.type); + + connect(newFileButton, &QCommandLinkButton::clicked, newFile, &QAction::triggered); + connect(newFile, &QAction::triggered, this, &CStartPage::onCreateDocument); + + ui.LeftWidget->layout()->addWidget(newFileButton); + } + } + + // spacer + ui.LeftWidget->layout()->addItem(new QSpacerItem(1, 50)); + + + // open document actions + QCommandLinkButton *openFileButton = new QCommandLinkButton( + tr("Open..."), tr("Open existing document(s)"), this + ); + + openFileButton->setIcon(QIcon(":/Icons/Open")); + + connect(openFileButton, &QCommandLinkButton::clicked, m_parent, &CMainWindow::selectAndOpenDocument); + + ui.LeftWidget->layout()->addWidget(openFileButton); +} + + +void CStartPage::onCreateDocument() +{ + QAction *act = dynamic_cast(sender()); + if (act) + m_parent->createNewDocument(act->data().toByteArray()); +} + + +void CStartPage::createRecentDocs() +{ + const auto &recentList = m_parent->getRecentFilesList(); + int i = 0; + + for (const QString &fileName : recentList) + { + QFileInfo fi(fileName); + + QCommandLinkButton *fileButton = new QCommandLinkButton( + fi.baseName(), + fi.lastModified().toString() + " | " + fileName, + this + ); + + fileButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + + QAction *recentAction = new QAction(fileName, fileButton); + recentAction->setData(i++); + + connect(fileButton, &QCommandLinkButton::clicked, recentAction, &QAction::triggered); + connect(recentAction, &QAction::triggered, this, &CStartPage::onRecentDocument); + + + ui.RightWidget->layout()->addWidget(fileButton); + } + + + // spacer + QWidget *temp = new QWidget(this); + temp->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + ui.RightWidget->layout()->addWidget(temp); +} + + +void CStartPage::onRecentDocument() +{ + QAction *act = dynamic_cast(sender()); + if (act) + m_parent->openDocument(act->text()); +} diff --git a/src/appbase/CStartPage.h b/src/appbase/CStartPage.h new file mode 100644 index 00000000..e70c4623 --- /dev/null +++ b/src/appbase/CStartPage.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +#include "ui_CStartPage.h" + +class CMainWindow; + + +class CStartPage : public QWidget +{ + Q_OBJECT + +public: + CStartPage(CMainWindow *parent); + ~CStartPage(); + +protected: + void createActions(); + void createRecentDocs(); + +protected Q_SLOTS: + void onCreateDocument(); + void onRecentDocument(); + +private: + Ui::CStartPage ui; + CMainWindow *m_parent; +}; diff --git a/src/appbase/CStartPage.ui b/src/appbase/CStartPage.ui new file mode 100644 index 00000000..1bd8f704 --- /dev/null +++ b/src/appbase/CStartPage.ui @@ -0,0 +1,145 @@ + + + CStartPage + + + + 0 + 0 + 658 + 424 + + + + Start Page + + + + + + + + + 0 + 100 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Vertical + + + + + + + + + + Segoe UI + 12 + + + + Recently used files + + + + + + + QFrame::NoFrame + + + true + + + + + 0 + 0 + 310 + 379 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 100 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + diff --git a/src/appbase/appbase.pri b/src/appbase/appbase.pri index e5b08ce7..fc94c5ec 100644 --- a/src/appbase/appbase.pri +++ b/src/appbase/appbase.pri @@ -1,6 +1,6 @@ SOURCES += $$files($$PWD/*.cpp) HEADERS += $$files($$PWD/*.h) -#FORMS += $$files($$PWD/*.ui) +FORMS += $$files($$PWD/*.ui) RESOURCES += $$files($$PWD/*.qrc) unix{ diff --git a/src/commonui/CAttributesEditorUI.cpp b/src/commonui/CAttributesEditorUI.cpp index 7adb6184..04004411 100644 --- a/src/commonui/CAttributesEditorUI.cpp +++ b/src/commonui/CAttributesEditorUI.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/commonui/CAttributesEditorUI.h b/src/commonui/CAttributesEditorUI.h index 2cfc785d..a4a56b9e 100644 --- a/src/commonui/CAttributesEditorUI.h +++ b/src/commonui/CAttributesEditorUI.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/commonui/CClassAttributesEditorUI.cpp b/src/commonui/CClassAttributesEditorUI.cpp index 82623d00..990463d9 100644 --- a/src/commonui/CClassAttributesEditorUI.cpp +++ b/src/commonui/CClassAttributesEditorUI.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/commonui/CClassAttributesEditorUI.h b/src/commonui/CClassAttributesEditorUI.h index 87201931..87433dec 100644 --- a/src/commonui/CClassAttributesEditorUI.h +++ b/src/commonui/CClassAttributesEditorUI.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/commonui/CCommutationTable.cpp b/src/commonui/CCommutationTable.cpp index 028b08ec..80744d4e 100644 --- a/src/commonui/CCommutationTable.cpp +++ b/src/commonui/CCommutationTable.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/commonui/CCommutationTable.h b/src/commonui/CCommutationTable.h index 10231431..d2e85cb7 100644 --- a/src/commonui/CCommutationTable.h +++ b/src/commonui/CCommutationTable.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/commonui/CDOTExportDialog.cpp b/src/commonui/CDOTExportDialog.cpp new file mode 100644 index 00000000..b9058c0f --- /dev/null +++ b/src/commonui/CDOTExportDialog.cpp @@ -0,0 +1,28 @@ +#include "CDOTExportDialog.h" +#include "ui_CDOTExportDialog.h" + + +CDOTExportDialog::CDOTExportDialog(QWidget *parent): + QDialog(parent), + ui(new Ui::CDOTExportDialog) +{ + ui->setupUi(this); +} + + +CDOTExportDialog::~CDOTExportDialog() +{ +} + + +bool CDOTExportDialog::writeBackground() const +{ + return ui->WriteBackground->isChecked(); +} + + +bool CDOTExportDialog::writeAttributes() const +{ + return ui->WriteAttributes->isChecked(); +} + diff --git a/src/commonui/CDOTExportDialog.h b/src/commonui/CDOTExportDialog.h new file mode 100644 index 00000000..011763a6 --- /dev/null +++ b/src/commonui/CDOTExportDialog.h @@ -0,0 +1,25 @@ +#pragma once + +#include + + +namespace Ui { + class CDOTExportDialog; +} + + +class CDOTExportDialog : public QDialog +{ + Q_OBJECT + +public: + CDOTExportDialog(QWidget *parent = 0); + ~CDOTExportDialog(); + + bool writeBackground() const; + bool writeAttributes() const; + +private: + Ui::CDOTExportDialog *ui; +}; + diff --git a/src/commonui/CDOTExportDialog.ui b/src/commonui/CDOTExportDialog.ui new file mode 100644 index 00000000..05a6c3e2 --- /dev/null +++ b/src/commonui/CDOTExportDialog.ui @@ -0,0 +1,107 @@ + + + CDOTExportDialog + + + + 0 + 0 + 293 + 119 + + + + Export to DOT + + + + + + Write background + + + true + + + + + + + Write node && edge attributes + + + true + + + + + + + false + + + Write IDs && topology + + + true + + + true + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + ButtonBox + accepted() + CDOTExportDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + ButtonBox + rejected() + CDOTExportDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/commonui/CNewAttributeDialog.cpp b/src/commonui/CNewAttributeDialog.cpp index 900c76bd..48f63a80 100644 --- a/src/commonui/CNewAttributeDialog.cpp +++ b/src/commonui/CNewAttributeDialog.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/commonui/CNewAttributeDialog.h b/src/commonui/CNewAttributeDialog.h index b233fd3b..48d91d88 100644 --- a/src/commonui/CNewAttributeDialog.h +++ b/src/commonui/CNewAttributeDialog.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/commonui/CNodeEdgePropertiesUI.cpp b/src/commonui/CNodeEdgePropertiesUI.cpp index 8bcd06b9..d76c4fb6 100644 --- a/src/commonui/CNodeEdgePropertiesUI.cpp +++ b/src/commonui/CNodeEdgePropertiesUI.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -59,6 +59,14 @@ CNodeEdgePropertiesUI::CNodeEdgePropertiesUI(QWidget *parent) : ui->EdgeAttrBox->setChecked(false); + // font size + QVector fontSizes = { 5,6,7,8,9,10,11,12,14,16,18,20,24,28,32,36,40,44,48,54,60,66,72,80,88,96 }; + for (int i : fontSizes) + ui->LabelFontSize->addItem(QString::number(i), i); + auto v = new QIntValidator(4, 200, this); + ui->LabelFontSize->setValidator(v); + + // update status & tooltips etc. ui->retranslateUi(this); } @@ -134,8 +142,9 @@ void CNodeEdgePropertiesUI::updateFromScene(CEditorScene* scene) QFont f(edgeAttrs["label.font"].defaultValue.value()); ui->LabelFont->setCurrentFont(f); - ui->LabelFontSize->setValue(f.pointSize()); + //ui->LabelFontSize->setValue(f.pointSize()); ui->LabelColor->setColor(edgeAttrs["label.color"].defaultValue.value()); + ui->LabelFontSize->setCurrentText(QString::number(f.pointSize())); } @@ -233,7 +242,7 @@ void CNodeEdgePropertiesUI::onSelectionChanged() { QFont f(item->getAttribute("label.font").value()); ui->LabelFont->setCurrentFont(f); - ui->LabelFontSize->setValue(f.pointSize()); + ui->LabelFontSize->setCurrentText(QString::number(f.pointSize())); ui->LabelFontBold->setChecked(f.bold()); ui->LabelFontItalic->setChecked(f.italic()); ui->LabelFontUnderline->setChecked(f.underline()); @@ -381,7 +390,7 @@ void CNodeEdgePropertiesUI::on_EdgeDirection_activated(QVariant data) void CNodeEdgePropertiesUI::on_LabelFont_activated(const QFont &font) { ui->LabelFontSize->blockSignals(true); - ui->LabelFontSize->setValue(font.pointSize()); + ui->LabelFontSize->setCurrentText(QString::number(font.pointSize())); ui->LabelFontSize->blockSignals(false); if (m_updateLock || m_scene == NULL) @@ -418,7 +427,7 @@ void CNodeEdgePropertiesUI::on_LabelColor_activated(const QColor &color) } -void CNodeEdgePropertiesUI::on_LabelFontSize_valueChanged(int value) +void CNodeEdgePropertiesUI::on_LabelFontSize_currentTextChanged(const QString &text) { if (m_updateLock || m_scene == NULL) return; @@ -427,6 +436,8 @@ void CNodeEdgePropertiesUI::on_LabelFontSize_valueChanged(int value) if (items.isEmpty()) return; + int value = text.toInt(); + bool set = false; for (auto item : items) diff --git a/src/commonui/CNodeEdgePropertiesUI.h b/src/commonui/CNodeEdgePropertiesUI.h index c0a73c2b..09dcf861 100644 --- a/src/commonui/CNodeEdgePropertiesUI.h +++ b/src/commonui/CNodeEdgePropertiesUI.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -65,7 +65,8 @@ protected Q_SLOTS: void on_LabelFont_activated(const QFont &font); void on_LabelColor_activated(const QColor &color); - void on_LabelFontSize_valueChanged(int value); + //void on_LabelFontSize_valueChanged(int value); + void on_LabelFontSize_currentTextChanged(const QString &text); void on_LabelFontBold_toggled(bool on); void on_LabelFontItalic_toggled(bool on); void on_LabelFontUnderline_toggled(bool on); diff --git a/src/commonui/CNodeEdgePropertiesUI.ui b/src/commonui/CNodeEdgePropertiesUI.ui index 3590ef78..6d0918bc 100644 --- a/src/commonui/CNodeEdgePropertiesUI.ui +++ b/src/commonui/CNodeEdgePropertiesUI.ui @@ -6,7 +6,7 @@ 0 0 - 303 + 322 430 @@ -19,6 +19,22 @@ Form + + /* +QToolButton, QComboBox, QDoubleSpinBox, QSpinBox +{ +border: 1px solid #aaa; +border-radius: 2px; +} +*/ + +QToolButton:on +{ +border: 1px solid #aaa; +background: #bbb; +} + + 0 @@ -113,6 +129,9 @@ Set width of the selected nodes + + + QAbstractSpinBox::CorrectToNearestValue @@ -157,6 +176,9 @@ Set height of the selected nodes + + + QAbstractSpinBox::CorrectToNearestValue @@ -281,6 +303,9 @@ Set stroke width of the selected nodes + + + QAbstractSpinBox::CorrectToNearestValue @@ -443,6 +468,9 @@ Set weight of the selected edges + + + QAbstractSpinBox::CorrectToNearestValue @@ -613,36 +641,24 @@ - + - + 0 0 - - - 50 - 28 - + + - - - 16777215 - 28 - - - - Set font size of the selected labels - - - QAbstractSpinBox::CorrectToNearestValue + + true - - 1 + + 30 - - 200 + + QComboBox::AdjustToContents @@ -819,6 +835,10 @@ EdgeAttrBox LabelColor LabelFont + LabelFontSize + LabelFontBold + LabelFontItalic + LabelFontUnderline diff --git a/src/commonui/CNodeEditorUIController.cpp b/src/commonui/CNodeEditorUIController.cpp index 4027da8e..44af6dcd 100644 --- a/src/commonui/CNodeEditorUIController.cpp +++ b/src/commonui/CNodeEditorUIController.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -17,6 +17,7 @@ It can be used freely, maintaining the information above. #include #include #include +#include #ifdef USE_OGDF #include @@ -104,6 +105,9 @@ CNodeEditorUIController::CNodeEditorUIController(CMainWindow *parent) : // search dialog m_searchDialog = new CSearchDialog(parent); + // export dialogs + m_dotDialog = new CDOTExportDialog(parent); + // OGDF #ifdef USE_OGDF m_ogdfController = new COGDFLayoutUIController(parent, m_editorScene); @@ -167,29 +171,16 @@ void CNodeEditorUIController::createMenus() editMenu->addSeparator(); - cutAction = editMenu->addAction(QIcon(":/Icons/Cut"), tr("Cu&t")); - cutAction->setStatusTip(tr("Cut selected item(s) to clipboard")); - cutAction->setToolTip(tr("Cut selection")); - cutAction->setShortcut(QKeySequence::Cut); - connect(cutAction, &QAction::triggered, m_editorScene, &CEditorScene::cut); - - copyAction = editMenu->addAction(QIcon(":/Icons/Copy"), tr("&Copy")); - copyAction->setStatusTip(tr("Copy selected item(s) to clipboard")); - copyAction->setToolTip(tr("Copy selection")); - copyAction->setShortcut(QKeySequence::Copy); - connect(copyAction, &QAction::triggered, m_editorScene, &CEditorScene::copy); - - pasteAction = editMenu->addAction(QIcon(":/Icons/Paste"), tr("&Paste")); - pasteAction->setStatusTip(tr("Paste item(s) from clipboard")); - pasteAction->setToolTip(tr("Paste from clipboard")); - pasteAction->setShortcut(QKeySequence::Paste); - connect(pasteAction, &QAction::triggered, m_editorScene, &CEditorScene::paste); + editMenu->addAction(m_editorScene->actions()->cutAction); + editMenu->addAction(m_editorScene->actions()->copyAction); + editMenu->addAction(m_editorScene->actions()->pasteAction); + editMenu->addAction(m_editorScene->actions()->delAction); - delAction = editMenu->addAction(QIcon(":/Icons/Delete"), tr("&Delete")); - delAction->setStatusTip(tr("Delete selected item(s)")); - delAction->setToolTip(tr("Delete selection")); - delAction->setShortcut(QKeySequence::Delete); - connect(delAction, &QAction::triggered, m_editorScene, &CEditorScene::del); + QAction *selAction = editMenu->addAction(QIcon(":/Icons/SelectAll"), tr("Select All")); + selAction->setStatusTip(tr("Select all items on the scene")); + selAction->setToolTip(tr("Select all items")); + selAction->setShortcut(QKeySequence::SelectAll); + connect(selAction, &QAction::triggered, m_editorScene, &CEditorScene::selectAll); // edit modes @@ -227,7 +218,7 @@ void CNodeEditorUIController::createMenus() QAction *sceneCropAction = editMenu->addAction(QIcon(":/Icons/Crop"), tr("&Crop Area")); sceneCropAction->setStatusTip(tr("Crop document area to contents")); - connect(sceneCropAction, &QAction::triggered, this, &CNodeEditorUIController::sceneCrop); + connect(sceneCropAction, &QAction::triggered, m_editorScene, &CEditorScene::crop); // color schemes @@ -258,10 +249,10 @@ void CNodeEditorUIController::createMenus() editToolbar->addSeparator(); - editToolbar->addAction(cutAction); - editToolbar->addAction(copyAction); - editToolbar->addAction(pasteAction); - editToolbar->addAction(delAction); + editToolbar->addAction(m_editorScene->actions()->cutAction); + editToolbar->addAction(m_editorScene->actions()->copyAction); + editToolbar->addAction(m_editorScene->actions()->pasteAction); + editToolbar->addAction(m_editorScene->actions()->delAction); editToolbar->addSeparator(); @@ -446,10 +437,6 @@ void CNodeEditorUIController::onSelectionChanged() { int selectionCount = m_editorScene->selectedItems().size(); - cutAction->setEnabled(selectionCount > 0); - copyAction->setEnabled(selectionCount > 0); - delAction->setEnabled(selectionCount > 0); - fitZoomSelectedAction->setEnabled(selectionCount > 0); } @@ -474,14 +461,20 @@ void CNodeEditorUIController::onSceneHint(const QString& text) void CNodeEditorUIController::onSceneStatusChanged(int status) { bool isAddNodesMode = (m_editorScene->getEditMode() == EM_AddNodes); + + const QString arrowMoveHint = tr(" | Ctrl + Arrow keys - move selected items by one point | Shift + Arrow keys - move selected items by grid step"); switch (status) { + case SIS_Edit_Label: + onSceneHint(tr("Enter - finish edit | Esc - cancel edit | Shift + Enter - insert line break")); + return; + case SIS_Hover: if (isAddNodesMode) - onSceneHint(tr("Click & drag - create new connection")); + onSceneHint(tr("Click & drag - create new connection | Double click - edit item's label") + arrowMoveHint); else - onSceneHint(tr("Ctrl+Click - (un)select item | Click & drag - move selected items | Ctrl+Click & drag - clone selected items")); + onSceneHint(tr("Ctrl+Click - (un)select item | Click & drag or Ctrl/Shift + Arrow keys - move selected items | Ctrl+Click & drag - clone selected items | Double click - edit item's label")); return; case SIS_Drag: @@ -489,14 +482,14 @@ void CNodeEditorUIController::onSceneStatusChanged(int status) return; case SIS_Hover_Port: - onSceneHint(tr("Click & drag - make a connection at this port")); + onSceneHint(tr("Click & drag - make a connection at this port | Double click - show port properties")); return; default: if (isAddNodesMode) - onSceneHint(tr("Click - create new node | Click & drag - create new connection")); + onSceneHint(tr("Click - create new node | Click & drag - create new connection") + arrowMoveHint); else - onSceneHint(tr("Click & drag - select an area")); + onSceneHint(tr("Click & drag - select an area") + arrowMoveHint); } } @@ -637,7 +630,15 @@ void CNodeEditorUIController::exportFile() void CNodeEditorUIController::exportDOT() { - doExport(CFileSerializerDOT()); + if (m_dotDialog->exec() == QDialog::Rejected) + return; + + doExport( + CFileSerializerDOT( + m_dotDialog->writeBackground(), + m_dotDialog->writeAttributes() + ) + ); } @@ -927,6 +928,9 @@ void CNodeEditorUIController::onDocumentLoaded(const QString &fileName) m_editorScene->setClassAttributeVisible(class_item, attr_label, true); m_editorScene->setClassAttributeVisible(class_node, attr_label, true); m_editorScene->setClassAttributeVisible(class_edge, attr_label, true); + + // store newly created state + m_editorScene->setInitialState(); } @@ -984,19 +988,6 @@ void CNodeEditorUIController::find() } -void CNodeEditorUIController::sceneCrop() -{ - QRectF itemsRect = m_editorScene->itemsBoundingRect().adjusted(-20, -20, 20, 20); - if (itemsRect == m_editorScene->sceneRect()) - return; - - // update scene rect - m_editorScene->setSceneRect(itemsRect); - - m_editorScene->addUndoState(); -} - - void CNodeEditorUIController::showNodeIds(bool on) { m_editorScene->setClassAttributeVisible(class_node, attr_id, on); diff --git a/src/commonui/CNodeEditorUIController.h b/src/commonui/CNodeEditorUIController.h index fb3bb0fe..2578dca0 100644 --- a/src/commonui/CNodeEditorUIController.h +++ b/src/commonui/CNodeEditorUIController.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -20,12 +20,14 @@ It can be used freely, maintaining the information above. #include + class CMainWindow; class CNodeEditorScene; class CNodePort; class CEditorView; class IFileSerializer; +class CDOTExportDialog; class CNodeEditorUIController : public QObject @@ -76,7 +78,6 @@ private Q_SLOTS: void unzoom(); void resetZoom(); - void sceneCrop(); void sceneOptions(); void showNodeIds(bool on); @@ -121,11 +122,6 @@ private Q_SLOTS: QMenu *m_viewMenu; - QAction *cutAction; - QAction *copyAction; - QAction *pasteAction; - QAction *delAction; - QAction *findAction; QActionGroup *m_editModesGroup; @@ -164,4 +160,5 @@ private Q_SLOTS: class CClassAttributesEditorUI *m_defaultsPanel; class CSearchDialog *m_searchDialog; + class CDOTExportDialog *m_dotDialog; }; diff --git a/src/commonui/CSceneMenuUIController.cpp b/src/commonui/CSceneMenuUIController.cpp index 611fb040..53df0887 100644 --- a/src/commonui/CSceneMenuUIController.cpp +++ b/src/commonui/CSceneMenuUIController.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -22,6 +23,9 @@ CSceneMenuUIController::~CSceneMenuUIController() bool CSceneMenuUIController::exec(CEditorScene *scene, QGraphicsItem *triggerItem, QGraphicsSceneContextMenuEvent *contextMenuEvent) { + m_scene = dynamic_cast(scene); + m_scene->setPastePosition(contextMenuEvent->scenePos()); + QMenu menu; fillMenu(menu, scene, triggerItem, contextMenuEvent); @@ -30,14 +34,15 @@ bool CSceneMenuUIController::exec(CEditorScene *scene, QGraphicsItem *triggerIte // execute menu.exec(contextMenuEvent->screenPos()); + m_scene->setPastePosition(QPointF()); return false; } -void CSceneMenuUIController::fillMenu(QMenu &menu, CEditorScene *scene, QGraphicsItem *triggerItem, QGraphicsSceneContextMenuEvent *contextMenuEvent) +void CSceneMenuUIController::fillMenu(QMenu &menu, CEditorScene *scene, QGraphicsItem *triggerItem, QGraphicsSceneContextMenuEvent* /*contextMenuEvent*/) { auto sceneActions = scene->getActions(); - auto nodeScene = dynamic_cast(scene); + auto nodeScene = m_scene; int nodesCount = nodeScene->getSelectedNodes().size(); bool nodesSelected = (nodesCount > 0); @@ -49,8 +54,12 @@ void CSceneMenuUIController::fillMenu(QMenu &menu, CEditorScene *scene, QGraphic QAction *changeIdAction = menu.addAction(tr("Change Id..."), parent(), SLOT(changeItemId())); changeIdAction->setEnabled((nodesCount + edgesCount) == 1); - QAction *deleteAction = menu.addAction(tr("Delete"), scene, SLOT(onActionDelete())); - deleteAction->setEnabled(scene->createSelectedList(CDeletableItems()).size()); + menu.addSeparator(); + + menu.addAction(scene->actions()->cutAction); + menu.addAction(scene->actions()->copyAction); + menu.addAction(scene->actions()->pasteAction); + menu.addAction(scene->actions()->delAction); // add default node actions menu.addSeparator(); @@ -89,3 +98,4 @@ void CSceneMenuUIController::fillMenu(QMenu &menu, CEditorScene *scene, QGraphic arrowsMenu->addSeparator(); arrowsMenu->addAction(tr("Reverse"), sceneActions, SLOT(onActionEdgeReverse())); } + diff --git a/src/commonui/CSceneMenuUIController.h b/src/commonui/CSceneMenuUIController.h index 236fc56f..88fb930e 100644 --- a/src/commonui/CSceneMenuUIController.h +++ b/src/commonui/CSceneMenuUIController.h @@ -5,6 +5,8 @@ #include +class CNodeEditorScene; + class CSceneMenuUIController : public QObject, public ISceneMenuController { @@ -23,6 +25,9 @@ class CSceneMenuUIController : public QObject, public ISceneMenuController Q_SIGNALS: // emitted before \a menu is about to show. void onContextMenu(QMenu &menu); + +private: + CNodeEditorScene* m_scene; }; diff --git a/src/commonui/CSceneOptionsDialog.cpp b/src/commonui/CSceneOptionsDialog.cpp index 89e304a9..cb8a9937 100644 --- a/src/commonui/CSceneOptionsDialog.cpp +++ b/src/commonui/CSceneOptionsDialog.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/commonui/CSceneOptionsDialog.h b/src/commonui/CSceneOptionsDialog.h index 3bad1e7d..c656a7e7 100644 --- a/src/commonui/CSceneOptionsDialog.h +++ b/src/commonui/CSceneOptionsDialog.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/commonui/CSearchDialog.cpp b/src/commonui/CSearchDialog.cpp index 4de07011..81aca51e 100644 --- a/src/commonui/CSearchDialog.cpp +++ b/src/commonui/CSearchDialog.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/commonui/CSearchDialog.h b/src/commonui/CSearchDialog.h index d985cfa3..a4d6d9d4 100644 --- a/src/commonui/CSearchDialog.h +++ b/src/commonui/CSearchDialog.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/commonui/commonui.qrc b/src/commonui/commonui.qrc index 026ccd61..f321622f 100644 --- a/src/commonui/commonui.qrc +++ b/src/commonui/commonui.qrc @@ -33,5 +33,8 @@ Icons/text-label.png Icons/Graph.png Icons/Search.png + Icons/Format-DOT.png + Icons/Format-GEXF.png + Icons/Format-GraphML.png diff --git a/src/qvge/CAttribute.cpp b/src/qvge/CAttribute.cpp index 8fc51112..d3c46054 100644 --- a/src/qvge/CAttribute.cpp +++ b/src/qvge/CAttribute.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CAttribute.h b/src/qvge/CAttribute.h index f4542a6d..2cad71f9 100644 --- a/src/qvge/CAttribute.h +++ b/src/qvge/CAttribute.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CControlPoint.cpp b/src/qvge/CControlPoint.cpp index 9a09f49e..360c3d6a 100644 --- a/src/qvge/CControlPoint.cpp +++ b/src/qvge/CControlPoint.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CControlPoint.h b/src/qvge/CControlPoint.h index 619450c6..a9d8755b 100644 --- a/src/qvge/CControlPoint.h +++ b/src/qvge/CControlPoint.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CDiffUndoManager.cpp b/src/qvge/CDiffUndoManager.cpp index 8cd0ea47..74f21c09 100644 --- a/src/qvge/CDiffUndoManager.cpp +++ b/src/qvge/CDiffUndoManager.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CDiffUndoManager.h b/src/qvge/CDiffUndoManager.h index 7d611a57..5fabdf19 100644 --- a/src/qvge/CDiffUndoManager.h +++ b/src/qvge/CDiffUndoManager.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CDirectEdge.cpp b/src/qvge/CDirectEdge.cpp index ab862533..de528f31 100644 --- a/src/qvge/CDirectEdge.cpp +++ b/src/qvge/CDirectEdge.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CDirectEdge.h b/src/qvge/CDirectEdge.h index 53075748..2d258002 100644 --- a/src/qvge/CDirectEdge.h +++ b/src/qvge/CDirectEdge.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CEdge.cpp b/src/qvge/CEdge.cpp index 5c2f0c02..0699cdcd 100644 --- a/src/qvge/CEdge.cpp +++ b/src/qvge/CEdge.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CEdge.h b/src/qvge/CEdge.h index ba226271..37f28067 100644 --- a/src/qvge/CEdge.h +++ b/src/qvge/CEdge.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CEditorScene.cpp b/src/qvge/CEditorScene.cpp index 47473d8c..830e9e22 100644 --- a/src/qvge/CEditorScene.cpp +++ b/src/qvge/CEditorScene.cpp @@ -10,6 +10,7 @@ It can be used freely, maintaining the information above. #include "CEditorScene.h" #include "CEditorScene_p.h" #include "CEditorSceneDefines.h" +#include "CEditorSceneActions.h" #include "CItem.h" #include "CControlPoint.h" #include "CSimpleUndoManager.h" @@ -75,6 +76,7 @@ CEditorScene::CEditorScene(QObject *parent): QGraphicsScene(parent), connect(this, &CEditorScene::focusItemChanged, this, &CEditorScene::onFocusItemChanged); } + CEditorScene::~CEditorScene() { disconnect(); @@ -83,6 +85,7 @@ CEditorScene::~CEditorScene() delete m_pimpl; } + void CEditorScene::reset() { initialize(); @@ -93,6 +96,7 @@ void CEditorScene::reset() setSceneRect(QRectF(-500,-500,1000,1000)); } + void CEditorScene::initialize() { removeItems(); @@ -131,6 +135,7 @@ void CEditorScene::initialize() setClassAttributeConstrains(class_scene, attr_labels_policy, labelsPolicy); } + void CEditorScene::removeItems() { CItem::beginRestore(); @@ -193,6 +198,29 @@ void CEditorScene::setFontAntialiased(bool on) update(); } +void CEditorScene::copyProperties(const CEditorScene& from) +{ + m_classAttributes = from.m_classAttributes; + m_classToSuperIds = from.m_classToSuperIds; + m_classAttributesVis = from.m_classAttributesVis; +} + +CEditorScene* CEditorScene::clone() +{ + QByteArray buffer; + QDataStream out(&buffer, QIODevice::WriteOnly); + if (!storeTo(out, true)) + return nullptr; + + CEditorScene* tempScene = createScene(); + QDataStream in(buffer); + if (tempScene->restoreFrom(in, true)) + return tempScene; + + delete tempScene; + return nullptr; +} + // undo-redo @@ -208,6 +236,7 @@ void CEditorScene::undo() } } + void CEditorScene::redo() { if (m_undoManager) @@ -220,6 +249,7 @@ void CEditorScene::redo() } } + void CEditorScene::addUndoState() { onSceneChanged(); @@ -238,6 +268,7 @@ void CEditorScene::addUndoState() } } + void CEditorScene::revertUndoState() { if (m_undoManager) @@ -250,16 +281,30 @@ void CEditorScene::revertUndoState() onSceneChanged(); } + +void CEditorScene::setInitialState() +{ + if (m_undoManager) + { + m_undoManager->reset(); + } + + addUndoState(); +} + + int CEditorScene::availableUndoCount() const { return m_undoManager ? m_undoManager->availableUndoCount() : 0; } + int CEditorScene::availableRedoCount() const { return m_undoManager ? m_undoManager->availableRedoCount() : 0; } + void CEditorScene::checkUndoState() { Q_EMIT undoAvailable(m_undoManager->availableUndoCount() > 0); @@ -329,6 +374,7 @@ bool CEditorScene::storeTo(QDataStream& out, bool storeOptions) const return true; } + bool CEditorScene::restoreFrom(QDataStream& out, bool readOptions) { initialize(); @@ -701,12 +747,6 @@ void CEditorScene::setClassAttributeConstrains(const QByteArray& classId, const // copy-paste -QList CEditorScene::copyPasteItems() const -{ - return selectedItems(); -} - - void CEditorScene::cut() { copy(); @@ -720,12 +760,16 @@ void CEditorScene::del() if (itemList.isEmpty()) return; + beginSelection(); + for (QGraphicsItem* item : itemList) { if (items().contains(item)) delete item; } + endSelection(); + addUndoState(); } @@ -769,13 +813,63 @@ void CEditorScene::copy() QMimeData* mimeData = new QMimeData; mimeData->setData("qvge/selection", buffer); QApplication::clipboard()->setMimeData(mimeData); + + // paste it to a temp scene & render into mime image + CEditorScene* tempScene = createScene(); + tempScene->copyProperties(*this); + tempScene->enableGrid(false); + tempScene->paste(); + tempScene->deselectAll(); + tempScene->crop(); + + QImage image(tempScene->sceneRect().size().toSize(), QImage::Format_ARGB32); + image.fill(Qt::white); + + QPainter painter(&image); + painter.setRenderHint(QPainter::Antialiasing); + painter.setRenderHint(QPainter::TextAntialiasing); + tempScene->render(&painter); + painter.end(); + + mimeData->setImageData(QVariant(image)); + QApplication::clipboard()->setMimeData(mimeData); + + delete tempScene; } void CEditorScene::paste() { - deselectAll(); + if (!m_pastePos.isNull()) + { + pasteAt(m_pastePos); + return; + } + auto *view = getCurrentView(); + if (view) + { + if (view->underMouse()) + { + auto p = view->mapFromGlobal(QCursor::pos()); + pasteAt(view->mapToScene(p)); + } + else + { + QRectF vp = view->mapToScene(view->viewport()->geometry()).boundingRect(); + auto center = vp.center(); + pasteAt(center); + } + } + else + { + pasteAt(QPointF()); + } +} + + +void CEditorScene::pasteAt(const QPointF &anchor) +{ const QClipboard *clipboard = QApplication::clipboard(); const QMimeData *mimeData = clipboard->mimeData(); if (mimeData == NULL) @@ -783,6 +877,8 @@ void CEditorScene::paste() if (!mimeData->hasFormat("qvge/selection")) return; + deselectAll(); + // read items from the buffer QByteArray buffer = mimeData->data("qvge/selection"); QDataStream out(buffer); @@ -838,26 +934,32 @@ void CEditorScene::paste() QMap ids; auto allItems = getItems(); for (auto item : allItems) - ids[item->getId()]++; - - // shift - moveSelectedItemsBy(100, 0); + ids[item->getId() + item->typeId()]++; + // shift if not in-place auto selItems = selectedItems(); - for (auto sceneItem : selItems) + + if (!anchor.isNull()) { - //sceneItem->moveBy(100, 0); + QRectF r = CUtils::getBoundingRect(selItems); + QPointF d = anchor - r.center(); + moveSelectedItemsBy(d); + } + // rename pasted items + for (auto sceneItem : selItems) + { CItem* item = dynamic_cast(sceneItem); if (item) { QString id = item->getId(); - if (ids[id] > 1) + QString typeId = item->typeId(); + if (ids[id + typeId] > 1) { int counter = 1; QString newId = id; - while (ids.contains(newId)) + while (ids.contains(newId + typeId)) newId = QString("Copy%1 of %2").arg(counter++).arg(id); item->setId(newId); @@ -878,6 +980,12 @@ void CEditorScene::paste() } +QList CEditorScene::copyPasteItems() const +{ + return selectedItems(); +} + + QList CEditorScene::cloneSelectedItems() { CItem::CItemLinkMap idToItem; @@ -925,6 +1033,21 @@ QList CEditorScene::cloneSelectedItems() } +// crop + +void CEditorScene::crop() +{ + QRectF itemsRect = itemsBoundingRect().adjusted(-20, -20, 20, 20); + if (itemsRect == sceneRect()) + return; + + // update scene rect + setSceneRect(itemsRect); + + addUndoState(); +} + + // transform QList CEditorScene::transformableItems() const @@ -985,6 +1108,11 @@ void CEditorScene::onSceneChanged() void CEditorScene::onSelectionChanged() { + int selectionCount = selectedItems().size(); + actions()->cutAction->setEnabled(selectionCount > 0); + actions()->copyAction->setEnabled(selectionCount > 0); + actions()->delAction->setEnabled(selectionCount > 0); + calculateTransformRect(); } @@ -1758,6 +1886,18 @@ QGraphicsItem* CEditorScene::getItemAt(const QPointF& pos) const } +QGraphicsView* CEditorScene::getCurrentView() +{ + for (auto view: views()) + { + if (view->underMouse() || view->hasFocus()) + return view; + } + + return nullptr; +} + + // private void CEditorScene::setSceneCursor(const QCursor& c) @@ -1781,13 +1921,18 @@ void CEditorScene::keyReleaseEvent(QKeyEvent *keyEvent) void CEditorScene::keyPressEvent(QKeyEvent *keyEvent) { + bool isCtrl = (keyEvent->modifiers() == Qt::ControlModifier); + bool isAlt = (keyEvent->modifiers() == Qt::AltModifier); + bool isShift = (keyEvent->modifiers() == Qt::ShiftModifier); + Super::keyPressEvent(keyEvent); updateCursorState(); - if (keyEvent->isAccepted()) + if (isAlt || keyEvent->isAccepted()) return; + if (keyEvent->key() == Qt::Key_Delete) { onActionDelete(); @@ -1796,7 +1941,8 @@ void CEditorScene::keyPressEvent(QKeyEvent *keyEvent) return; } - if (keyEvent->key() == Qt::Key_A && keyEvent->modifiers() == Qt::ControlModifier) + + if (keyEvent->key() == Qt::Key_A && isCtrl) { onActionSelectAll(); @@ -1804,51 +1950,45 @@ void CEditorScene::keyPressEvent(QKeyEvent *keyEvent) return; } - if (keyEvent->key() == Qt::Key_Right && keyEvent->modifiers() == Qt::ControlModifier) + + // no modifier moves by 1 pixel, shift moves by grid size + int moveStep = isShift ? m_gridSize : 1; + + if (keyEvent->key() == Qt::Key_Right) { - moveSelectedItemsBy(1, 0); + moveSelectedItemsBy(moveStep, 0); addUndoState(); keyEvent->accept(); return; } - if (keyEvent->key() == Qt::Key_Left && keyEvent->modifiers() == Qt::ControlModifier) + if (keyEvent->key() == Qt::Key_Left) { - moveSelectedItemsBy(-1, 0); + moveSelectedItemsBy(-moveStep, 0); addUndoState(); keyEvent->accept(); return; } - if (keyEvent->key() == Qt::Key_Up && keyEvent->modifiers() == Qt::ControlModifier) + if (keyEvent->key() == Qt::Key_Up) { - moveSelectedItemsBy(0, -1); + moveSelectedItemsBy(0, -moveStep); addUndoState(); keyEvent->accept(); return; } - if (keyEvent->key() == Qt::Key_Down && keyEvent->modifiers() == Qt::ControlModifier) + if (keyEvent->key() == Qt::Key_Down) { - moveSelectedItemsBy(0, 1); + moveSelectedItemsBy(0, moveStep); addUndoState(); keyEvent->accept(); return; } - - // test - - //if (keyEvent->modifiers() == Qt::ControlModifier && !m_leftClickPos.isNull() && !m_doubleClick) - //{ - // setSceneCursor(Qt::SizeHorCursor); - - // keyEvent->accept(); - // return; - //} } @@ -1914,21 +2054,9 @@ void CEditorScene::onActionSelectAll() void CEditorScene::onActionEditLabel(CItem *item) { - m_pimpl->m_labelEditor.startEdit(item); - - //bool ok = false; + setInfoStatus(SIS_Edit_Label); - //QString text = QInputDialog::getMultiLineText(NULL, - // tr("Item Label"), tr("New label text:"), - // item->getAttribute("label").toString(), - // &ok); - - //if (ok) - //{ - // item->setAttribute("label", text); - - // addUndoState(); - //} + m_pimpl->m_labelEditor.startEdit(item); } @@ -2031,6 +2159,12 @@ bool CDeletableItems::evaluate(const QGraphicsItem& item) const // actions +CEditorSceneActions* CEditorScene::actions() +{ + return dynamic_cast(getActions()); +} + + QObject* CEditorScene::getActions() { if (m_actions == NULL) @@ -2042,7 +2176,6 @@ QObject* CEditorScene::getActions() QObject* CEditorScene::createActions() { - // temp - return new QObject(this); + return new CEditorSceneActions(this); } diff --git a/src/qvge/CEditorScene.h b/src/qvge/CEditorScene.h index c97afc95..a68148e5 100644 --- a/src/qvge/CEditorScene.h +++ b/src/qvge/CEditorScene.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -19,12 +19,14 @@ It can be used freely, maintaining the information above. #include "CAttribute.h" -class CItem; class IUndoManager; class ISceneItemFactory; class IInteractive; class ISceneMenuController; +class CItem; +class CEditorSceneActions; + struct Graph; @@ -49,7 +51,7 @@ class CEditorScene : public QGraphicsScene public: typedef QGraphicsScene Super; - CEditorScene(QObject *parent); + CEditorScene(QObject *parent = NULL); virtual ~CEditorScene(); virtual void reset(); @@ -88,6 +90,8 @@ class CEditorScene : public QGraphicsScene void addUndoState(); // must be called to discard recent changes without undo void revertUndoState(); + // sets initial scene state + void setInitialState(); // serialization virtual bool storeTo(QDataStream& out, bool storeOptions) const; @@ -118,6 +122,15 @@ class CEditorScene : public QGraphicsScene m_itemFactoryFilter = filter; } + // scene factory & copy + virtual CEditorScene* createScene() const { + return new CEditorScene(); + } + + virtual CEditorScene* clone(); + + virtual void copyProperties(const CEditorScene& from); + // attributes QByteArray getSuperClassId(const QByteArray& classId) const { if (m_classToSuperIds.contains(classId)) @@ -208,11 +221,14 @@ class CEditorScene : public QGraphicsScene return m_infoStatus; } + QGraphicsView* getCurrentView(); + // callbacks virtual void onItemDestroyed(CItem *citem); // actions QObject* getActions(); + CEditorSceneActions* actions(); public Q_SLOTS: void enableGrid(bool on = true); @@ -222,19 +238,19 @@ public Q_SLOTS: void undo(); void redo(); - void onActionDelete(); - void onActionSelectAll(); - void onActionEditLabel(CItem *item); - void selectAll(); void deselectAll(); void selectItems(const QList& items, bool exclusive = true); - // copy-paste + void del(); void cut(); void copy(); + + void setPastePosition(const QPointF &anchor) { m_pastePos = anchor; } + void pasteAt(const QPointF &anchor); void paste(); - void del(); + + void crop(); Q_SIGNALS: void undoAvailable(bool); @@ -300,6 +316,10 @@ protected Q_SLOTS: virtual void onSelectionChanged(); void onFocusItemChanged(QGraphicsItem *newFocusItem, QGraphicsItem *oldFocusItem, Qt::FocusReason reason); + void onActionDelete(); + void onActionSelectAll(); + void onActionEditLabel(CItem *item); + private: void removeItems(); void checkUndoState(); @@ -339,6 +359,8 @@ protected Q_SLOTS: bool m_needUpdateItems; + QPointF m_pastePos; + // selector QRectF m_transformRect; diff --git a/src/qvge/CEditorSceneActions.cpp b/src/qvge/CEditorSceneActions.cpp new file mode 100644 index 00000000..6766512a --- /dev/null +++ b/src/qvge/CEditorSceneActions.cpp @@ -0,0 +1,44 @@ +/* +This file is a part of +QVGE - Qt Visual Graph Editor + +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) + +It can be used freely, maintaining the information above. +*/ + +#include +#include + +#include "CEditorSceneActions.h" +#include "CEditorScene.h" +#include "CNode.h" +#include "CEdge.h" + + +CEditorSceneActions::CEditorSceneActions(CEditorScene *scene) +{ + cutAction = new QAction(QIcon(":/Icons/Cut"), tr("Cut"), scene); + cutAction->setStatusTip(tr("Cut selected item(s) to clipboard")); + cutAction->setToolTip(tr("Cut selection")); + cutAction->setShortcut(QKeySequence::Cut); + connect(cutAction, &QAction::triggered, scene, &CEditorScene::cut); + + copyAction = new QAction(QIcon(":/Icons/Copy"), tr("Copy"), scene); + copyAction->setStatusTip(tr("Copy selected item(s) to clipboard")); + copyAction->setToolTip(tr("Copy selection")); + copyAction->setShortcut(QKeySequence::Copy); + connect(copyAction, &QAction::triggered, scene, &CEditorScene::copy); + + pasteAction = new QAction(QIcon(":/Icons/Paste"), tr("Paste"), scene); + pasteAction->setStatusTip(tr("Paste item(s) from clipboard")); + pasteAction->setToolTip(tr("Paste from clipboard")); + pasteAction->setShortcut(QKeySequence::Paste); + connect(pasteAction, &QAction::triggered, scene, &CEditorScene::paste); + + delAction = new QAction(QIcon(":/Icons/Delete"), QObject::tr("Delete"), scene); + delAction->setStatusTip(QObject::tr("Delete selected item(s)")); + delAction->setToolTip(QObject::tr("Delete selection")); + delAction->setShortcut(QKeySequence::Delete); + QObject::connect(delAction, &QAction::triggered, scene, &CEditorScene::del); +} diff --git a/src/qvge/CEditorSceneActions.h b/src/qvge/CEditorSceneActions.h new file mode 100644 index 00000000..940da98a --- /dev/null +++ b/src/qvge/CEditorSceneActions.h @@ -0,0 +1,28 @@ +/* +This file is a part of +QVGE - Qt Visual Graph Editor + +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) + +It can be used freely, maintaining the information above. +*/ + +#pragma once + +#include + + +class CEditorScene; + + +class CEditorSceneActions: public QObject +{ +public: + CEditorSceneActions(CEditorScene *scene); + + QAction *cutAction; + QAction *copyAction; + QAction *pasteAction; + QAction *delAction; +}; + diff --git a/src/qvge/CEditorSceneDefines.h b/src/qvge/CEditorSceneDefines.h index 250d80c2..2a81220f 100644 --- a/src/qvge/CEditorSceneDefines.h +++ b/src/qvge/CEditorSceneDefines.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -19,7 +19,8 @@ enum SceneInfoState SIS_Select = 0, SIS_Hover, SIS_Drag, - SIS_Hover_Port + SIS_Hover_Port, + SIS_Edit_Label }; diff --git a/src/qvge/CEditorView.cpp b/src/qvge/CEditorView.cpp index c6f6d41c..4eaf7b4d 100644 --- a/src/qvge/CEditorView.cpp +++ b/src/qvge/CEditorView.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -33,11 +33,13 @@ CEditorView::CEditorView(QWidget *parent) setOptimizationFlags(DontAdjustForAntialiasing); } + CEditorView::CEditorView(CEditorScene *scene, QWidget *parent): CEditorView(parent) { setScene(scene); } + CEditorView::~CEditorView() { } @@ -291,65 +293,7 @@ void CEditorView::wheelEvent(QWheelEvent *e) void CEditorView::onLeftClickMouseMove(QMouseEvent *e) { - if (dragMode() == QGraphicsView::RubberBandDrag) - { - QPointF loc = e->pos(); - QPointF d; - const QRect& vp = viewport()->geometry(); - - qDebug() << e->pos() << viewport()->geometry(); - - if (loc.x() > vp.right()) - { - scrollContentsBy(-5, 0); - QTimer::singleShot(10, this, SLOT(repaint())); - } - - //if ((loc.x() <= rect().center().x()) && (loc.y() <= rect().center().y())) - //{ - // //top left - // d.setX(frameGeometry().left() + loc.x()); - // d.setY(loc.y()); - // doClamp(d); - // if (d.x() || d.y()) scrollContentsBy(d.x() / 2, d.y() / 2); - // repaint(); - //} - //else if ((loc.x() <= rect().center().x()) && (loc.y() > rect().center().y())) - //{ - // //bottom left - // d.setX(frameGeometry().left() + loc.x()); - // d.setY(frameGeometry().bottom() - loc.y() - m_scrollThreshold); - // doClamp(d); - // if (d.x() || d.y()) scrollContentsBy(d.x() / 2, -(d.y() / 2)); - // repaint(); - //} - //else if ((loc.x() > rect().center().x()) && (loc.y() > rect().center().y())) - //{ - // //bottom right - // d.setX(frameGeometry().right() - loc.x()); - // d.setY(frameGeometry().bottom() - loc.y() - m_scrollThreshold); - // doClamp(d); - // if (d.x() || d.y()) scrollContentsBy(-(d.x() / 2), -(d.y() / 2)); - // repaint(); - //} - //else - //{ - // //top right - // d.setX(frameGeometry().right() - loc.x()); - // d.setY(loc.y()); - // doClamp(d); - // if (d.x() || d.y()) scrollContentsBy(-(d.x() / 2), d.y() / 2); - // repaint(); - //} - } } -void CEditorView::doClamp(QPointF &value) -{ - if ((value.x() > m_scrollThreshold) || (value.x() < 0)) value.rx() = 0; - else value.rx() = qAbs(value.x() - m_scrollThreshold); - if ((value.y() > m_scrollThreshold) || (value.y() < 0)) value.ry() = 0; - else value.ry() = qAbs(value.y() - m_scrollThreshold); -} diff --git a/src/qvge/CEditorView.h b/src/qvge/CEditorView.h index f053e8fc..661e697b 100644 --- a/src/qvge/CEditorView.h +++ b/src/qvge/CEditorView.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -26,6 +26,9 @@ class CEditorView : public QGraphicsView CEditorView(QWidget *parent = NULL); virtual ~CEditorView(); + // actions + QAction *pasteAction; + // zoom double getZoom() const { return m_currentZoom; } // target is % value to zoom to (1.0 = 100% = reset zoom, 0.25 = 25% = 1/4 etc.) @@ -57,7 +60,6 @@ private Q_SLOTS: private: void onLeftClickMouseMove(QMouseEvent *e); - void doClamp(QPointF &value); Qt::ContextMenuPolicy m_menuModeTmp; bool m_interactiveTmp = false; diff --git a/src/qvge/CFileSerializerCSV.cpp b/src/qvge/CFileSerializerCSV.cpp index 9a6336f0..e9055218 100644 --- a/src/qvge/CFileSerializerCSV.cpp +++ b/src/qvge/CFileSerializerCSV.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CFileSerializerCSV.h b/src/qvge/CFileSerializerCSV.h index 5a2afee4..9a69f285 100644 --- a/src/qvge/CFileSerializerCSV.h +++ b/src/qvge/CFileSerializerCSV.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CFileSerializerDOT.cpp b/src/qvge/CFileSerializerDOT.cpp index afac14e6..3844ba09 100644 --- a/src/qvge/CFileSerializerDOT.cpp +++ b/src/qvge/CFileSerializerDOT.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -27,18 +27,26 @@ bool CFileSerializerDOT::save(const QString& fileName, CEditorScene& scene, QStr QString graphId = QFileInfo(fileName).completeBaseName(); - ts << "digraph \"" << graphId << "\" {\n"; + ts << "digraph \"" << graphId << "\"\n{"; + ts << "\n\n"; // we'll output points, not inches //ts << "\n\n"; //ts << "inputscale = 72;"; - ts << "\n\n"; + // background + if (m_writeBackground) + { + ts << "bgcolor = \"" << scene.backgroundBrush().color().name() << "\""; + ts << "\n\n"; + } // nodes - doWriteNodeDefaults(ts, scene); - - ts << "\n\n"; + if (m_writeAttrs) + { + doWriteNodeDefaults(ts, scene); + ts << "\n\n"; + } auto nodes = scene.getItems(); for (auto node: nodes) @@ -50,9 +58,11 @@ bool CFileSerializerDOT::save(const QString& fileName, CEditorScene& scene, QStr // edges - doWriteEdgeDefaults(ts, scene); - - ts << "\n\n"; + if (m_writeAttrs) + { + doWriteEdgeDefaults(ts, scene); + ts << "\n\n"; + } auto edges = scene.getItems(); for (auto edge: edges) @@ -60,8 +70,7 @@ bool CFileSerializerDOT::save(const QString& fileName, CEditorScene& scene, QStr doWriteEdge(ts, *edge, scene); } - ts << "\n\n"; - ts << "}\n"; + ts << "\n}\n"; return true; } @@ -124,15 +133,21 @@ void CFileSerializerDOT::doWriteNodeDefaults(QTextStream& ts, const CEditorScene void CFileSerializerDOT::doWriteNode(QTextStream& ts, const CNode& node, const CEditorScene& /*scene*/) const { ts << "\"" << node.getId() << "\""; - ts << " [\n"; - ts << "pos = \"" << node.pos().x() / 72.0 << "," << -node.pos().y() / 72.0 << "!\"\n"; // / 72.0 -> point to inch; -y + if (m_writeAttrs) + { + ts << " [\n"; + + ts << "pos = \"" << node.pos().x() / 72.0 << "," << -node.pos().y() / 72.0 << "!\"\n"; // / 72.0 -> point to inch; -y - const QMap& nodeAttrs = node.getLocalAttributes(); + const QMap& nodeAttrs = node.getLocalAttributes(); - doWriteNodeAttrs(ts, nodeAttrs); + doWriteNodeAttrs(ts, nodeAttrs); - ts << "];\n\n"; + ts << "]"; + } + + ts << "\n\n"; } @@ -254,7 +269,10 @@ void CFileSerializerDOT::doWriteEdge(QTextStream& ts, const CEdge& edge, const C ts << " [id = \"" << edge.getId() << "\"\n"; - doWriteEdgeAttrs(ts, edgeAttrs); + if (m_writeAttrs) + { + doWriteEdgeAttrs(ts, edgeAttrs); + } ts << "];\n\n"; } diff --git a/src/qvge/CFileSerializerDOT.h b/src/qvge/CFileSerializerDOT.h index 2da9d8b3..a577fa17 100644 --- a/src/qvge/CFileSerializerDOT.h +++ b/src/qvge/CFileSerializerDOT.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -24,6 +24,12 @@ class QTextStream; class CFileSerializerDOT : public IFileSerializer { public: + CFileSerializerDOT(bool writeBackground = true, bool writeAttrs = true) : + m_writeBackground(writeBackground), + m_writeAttrs(writeAttrs) + {} + + // reimp virtual QString description() const { return "DOT/GraphViz graph format"; @@ -59,5 +65,8 @@ class CFileSerializerDOT : public IFileSerializer void doWriteEdgeDefaults(QTextStream& ts, const CEditorScene& scene) const; void doWriteEdge(QTextStream& ts, const CEdge& edge, const CEditorScene& scene) const; void doWriteEdgeAttrs(QTextStream& ts, QMap edgeAttrs) const; + + bool m_writeBackground = true; + bool m_writeAttrs = true; }; diff --git a/src/qvge/CFileSerializerGEXF.cpp b/src/qvge/CFileSerializerGEXF.cpp index a36fd16d..fb0a4017 100644 --- a/src/qvge/CFileSerializerGEXF.cpp +++ b/src/qvge/CFileSerializerGEXF.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -379,7 +379,7 @@ bool CFileSerializerGEXF::readEdge(int /*index*/, const QDomNode &domNode, const } -bool CFileSerializerGEXF::save(const QString& fileName, CEditorScene& scene, QString* lastError) const +bool CFileSerializerGEXF::save(const QString& fileName, CEditorScene& scene, QString* /*lastError*/) const { QFile file(fileName); if (!file.open(QIODevice::WriteOnly)) @@ -550,7 +550,7 @@ void CFileSerializerGEXF::writeNodes(QTextStream &ts, const CEditorScene& scene) ts << " \n"; auto nodes = scene.getItems(); - for (auto node : nodes) + for (const auto &node : nodes) { QMap nodeAttrs = node->getLocalAttributes(); diff --git a/src/qvge/CFileSerializerGEXF.h b/src/qvge/CFileSerializerGEXF.h index 2cf14ca7..d318c1c8 100644 --- a/src/qvge/CFileSerializerGEXF.h +++ b/src/qvge/CFileSerializerGEXF.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CFileSerializerGraphML.cpp b/src/qvge/CFileSerializerGraphML.cpp index 867a1bd6..41c868f8 100644 --- a/src/qvge/CFileSerializerGraphML.cpp +++ b/src/qvge/CFileSerializerGraphML.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CFileSerializerGraphML.h b/src/qvge/CFileSerializerGraphML.h index 5f6614a6..59c755a8 100644 --- a/src/qvge/CFileSerializerGraphML.h +++ b/src/qvge/CFileSerializerGraphML.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CFileSerializerXGR.cpp b/src/qvge/CFileSerializerXGR.cpp index d9827887..033f7c1b 100644 --- a/src/qvge/CFileSerializerXGR.cpp +++ b/src/qvge/CFileSerializerXGR.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CFileSerializerXGR.h b/src/qvge/CFileSerializerXGR.h index 5fab8dce..312c51a1 100644 --- a/src/qvge/CFileSerializerXGR.h +++ b/src/qvge/CFileSerializerXGR.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CImageExport.cpp b/src/qvge/CImageExport.cpp index edfeab87..a0b5f291 100644 --- a/src/qvge/CImageExport.cpp +++ b/src/qvge/CImageExport.cpp @@ -79,12 +79,20 @@ QString CImageExport::filters() const bool CImageExport::save(const QString& fileName, CEditorScene& scene, QString* /*lastError*/) const { - QImage image(scene.sceneRect().size().toSize(), QImage::Format_ARGB32); + CEditorScene* tempScene = scene.clone(); + + tempScene->crop(); + + QImage image(tempScene->sceneRect().size().toSize(), QImage::Format_ARGB32); image.fill(Qt::white); + QPainter painter(&image); painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::TextAntialiasing); - scene.render(&painter); + tempScene->render(&painter); + painter.end(); + + delete tempScene; return image.save(fileName); } diff --git a/src/qvge/CItem.cpp b/src/qvge/CItem.cpp index b230e9e4..b3924235 100644 --- a/src/qvge/CItem.cpp +++ b/src/qvge/CItem.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CItem.h b/src/qvge/CItem.h index 94e1b99a..bfd27157 100644 --- a/src/qvge/CItem.h +++ b/src/qvge/CItem.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CNode.cpp b/src/qvge/CNode.cpp index 21ce796f..968816f7 100644 --- a/src/qvge/CNode.cpp +++ b/src/qvge/CNode.cpp @@ -337,6 +337,12 @@ CNodePort* CNode::getPort(const QByteArray& portId) const } +QByteArrayList CNode::getPortIds() const +{ + return m_ports.keys(); +} + + // serialization bool CNode::storeTo(QDataStream& out, quint64 version64) const diff --git a/src/qvge/CNode.h b/src/qvge/CNode.h index b19061f9..a94767fa 100644 --- a/src/qvge/CNode.h +++ b/src/qvge/CNode.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -64,11 +64,12 @@ class CNode : public CItem, public QGraphicsRectItem virtual QByteArray superClassId() const { return Super::classId(); } // ports - virtual CNodePort* addPort(const QByteArray& portId = "", int align = Qt::AlignCenter, double xoff = 0, double yoff = 0); - virtual bool removePort(const QByteArray& portId); - virtual bool movePort(const QByteArray& portId, int align = Qt::AlignCenter, double xoff = 0, double yoff = 0); - virtual bool renamePort(const QByteArray& portId, const QByteArray& newId); - virtual CNodePort* getPort(const QByteArray& portId) const; + CNodePort* addPort(const QByteArray& portId = "", int align = Qt::AlignCenter, double xoff = 0, double yoff = 0); + bool removePort(const QByteArray& portId); + bool movePort(const QByteArray& portId, int align = Qt::AlignCenter, double xoff = 0, double yoff = 0); + bool renamePort(const QByteArray& portId, const QByteArray& newId); + CNodePort* getPort(const QByteArray& portId) const; + QByteArrayList getPortIds() const; // serialization virtual bool storeTo(QDataStream& out, quint64 version64) const; diff --git a/src/qvge/CNodeEditorScene.cpp b/src/qvge/CNodeEditorScene.cpp index 76c8650a..f342a03e 100644 --- a/src/qvge/CNodeEditorScene.cpp +++ b/src/qvge/CNodeEditorScene.cpp @@ -147,6 +147,51 @@ bool CNodeEditorScene::toGraph(Graph& g) g.edgeAttrs[it.key()] = attr; } + + // nodes + auto nodes = getItems(); + for (const auto &node : nodes) + { + Node n; + n.id = node->getId().toLocal8Bit(); + + QByteArrayList ports = node->getPortIds(); + for (const auto &portId : ports) + { + auto port = node->getPort(portId); + Q_ASSERT(port != NULL); + + NodePort p; + p.name = portId; + + // TO DO: other attrs + + n.ports[portId] = p; + } + + n.attrs = node->getLocalAttributes(); + + g.nodes.append(n); + } + + + // edges + auto edges = getItems(); + for (const auto &edge : edges) + { + Edge e; + e.id = edge->getId().toLocal8Bit(); + e.startNodeId = edge->firstNode()->getId().toLocal8Bit(); + e.endNodeId = edge->lastNode()->getId().toLocal8Bit(); + e.startPortId = edge->firstPortId(); + e.endPortId = edge->lastPortId(); + + e.attrs = edge->getLocalAttributes(); + + g.edges.append(e); + } + + // TODO return true; diff --git a/src/qvge/CNodeEditorScene.h b/src/qvge/CNodeEditorScene.h index 354309e9..a84b2632 100644 --- a/src/qvge/CNodeEditorScene.h +++ b/src/qvge/CNodeEditorScene.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -32,9 +32,13 @@ class CNodeEditorScene : public CEditorScene public: typedef CEditorScene Super; - CNodeEditorScene(QObject *parent); + CNodeEditorScene(QObject *parent = NULL); // reimp + virtual CEditorScene* createScene() const { + return new CNodeEditorScene(); + } + virtual void initialize(); virtual bool fromGraph(const Graph& g); virtual bool toGraph(Graph& g); diff --git a/src/qvge/CNodePort.cpp b/src/qvge/CNodePort.cpp index 82696a4f..9dccfd11 100644 --- a/src/qvge/CNodePort.cpp +++ b/src/qvge/CNodePort.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CNodePort.h b/src/qvge/CNodePort.h index 65d8da76..3b5046c2 100644 --- a/src/qvge/CNodePort.h +++ b/src/qvge/CNodePort.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CNodeSceneActions.cpp b/src/qvge/CNodeSceneActions.cpp index c977d2d4..36bbfc20 100644 --- a/src/qvge/CNodeSceneActions.cpp +++ b/src/qvge/CNodeSceneActions.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -18,7 +18,7 @@ It can be used freely, maintaining the information above. CNodeSceneActions::CNodeSceneActions(CNodeEditorScene *scene) : - QObject(scene), + CEditorSceneActions(scene), nodeScene(*scene) { } diff --git a/src/qvge/CNodeSceneActions.h b/src/qvge/CNodeSceneActions.h index b4ab877a..900f34b0 100644 --- a/src/qvge/CNodeSceneActions.h +++ b/src/qvge/CNodeSceneActions.h @@ -2,21 +2,21 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ #pragma once -#include +#include "CEditorSceneActions.h" class CNodeEditorScene; class CNode; class CEdge; -class CNodeSceneActions : public QObject +class CNodeSceneActions : public CEditorSceneActions { Q_OBJECT diff --git a/src/qvge/CPDFExport.cpp b/src/qvge/CPDFExport.cpp index cc7d7381..f8d5e129 100644 --- a/src/qvge/CPDFExport.cpp +++ b/src/qvge/CPDFExport.cpp @@ -15,8 +15,12 @@ It can be used freely, maintaining the information above. #include "CEditorScene.h" -bool CPDFExport::save(const QString& fileName, CEditorScene& scene, QString* lastError) const +bool CPDFExport::save(const QString& fileName, CEditorScene& scene, QString* /*lastError*/) const { + CEditorScene* tempScene = scene.clone(); + + tempScene->crop(); + QPrinter printer(QPrinter::HighResolution); printer.setPageSize(QPrinter::A4); printer.setOrientation(QPrinter::Portrait); @@ -26,7 +30,10 @@ bool CPDFExport::save(const QString& fileName, CEditorScene& scene, QString* las QPainter painter(&printer); painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::TextAntialiasing); - scene.render(&painter); + tempScene->render(&painter); + painter.end(); + + delete tempScene; return true; } \ No newline at end of file diff --git a/src/qvge/CPolyEdge.cpp b/src/qvge/CPolyEdge.cpp index 0c60cd09..c6b5a561 100644 --- a/src/qvge/CPolyEdge.cpp +++ b/src/qvge/CPolyEdge.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CPolyEdge.h b/src/qvge/CPolyEdge.h index 3fcfdec7..07710fe3 100644 --- a/src/qvge/CPolyEdge.h +++ b/src/qvge/CPolyEdge.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CSimpleUndoManager.cpp b/src/qvge/CSimpleUndoManager.cpp index d37bf555..bef97479 100644 --- a/src/qvge/CSimpleUndoManager.cpp +++ b/src/qvge/CSimpleUndoManager.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CSimpleUndoManager.h b/src/qvge/CSimpleUndoManager.h index eecd7760..ea38d9da 100644 --- a/src/qvge/CSimpleUndoManager.h +++ b/src/qvge/CSimpleUndoManager.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CTextLabelEdit.cpp b/src/qvge/CTextLabelEdit.cpp index a0472883..4d12850a 100644 --- a/src/qvge/CTextLabelEdit.cpp +++ b/src/qvge/CTextLabelEdit.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -45,16 +45,6 @@ bool CTextLabelEdit::sceneEvent(QEvent *event) { QKeyEvent *keyEvent = static_cast (event); if (keyEvent->matches(QKeySequence::Cancel)) // Esc - { - finishEdit(false); - return true; - } - } - - if (event->type() == QEvent::KeyPress) - { - QKeyEvent *keyEvent = static_cast (event); - if (keyEvent->matches(QKeySequence::InsertParagraphSeparator)) // Enter { finishEdit(true); return true; diff --git a/src/qvge/CTextLabelEdit.h b/src/qvge/CTextLabelEdit.h index 42ae1276..0d92f30d 100644 --- a/src/qvge/CTextLabelEdit.h +++ b/src/qvge/CTextLabelEdit.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/CUtils.cpp b/src/qvge/CUtils.cpp index 4cc5a82f..3739cd6d 100644 --- a/src/qvge/CUtils.cpp +++ b/src/qvge/CUtils.cpp @@ -148,3 +148,13 @@ QString CUtils::cutLastSuffix(const QString& fileName) return fileName.left(idx); } + +QRectF CUtils::getBoundingRect(const QList& items) +{ + QRectF r; + + for (const auto item : items) + r |= item->sceneBoundingRect(); + + return r; +} diff --git a/src/qvge/CUtils.h b/src/qvge/CUtils.h index 178c606a..aeb603ba 100644 --- a/src/qvge/CUtils.h +++ b/src/qvge/CUtils.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -16,6 +16,7 @@ It can be used freely, maintaining the information above. #include #include #include +#include class CUtils @@ -33,6 +34,8 @@ class CUtils static QPointF closestIntersection(const QLineF& line, const QPolygonF& with); static QString cutLastSuffix(const QString& fileName); + + static QRectF getBoundingRect(const QList& items); }; diff --git a/src/qvge/IFileExport.h b/src/qvge/IFileExport.h index 5f45e6d3..c3dc099e 100644 --- a/src/qvge/IFileExport.h +++ b/src/qvge/IFileExport.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/IFileSerializer.h b/src/qvge/IFileSerializer.h index c6220d53..6e2b4f6e 100644 --- a/src/qvge/IFileSerializer.h +++ b/src/qvge/IFileSerializer.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/ISceneItemFactory.h b/src/qvge/ISceneItemFactory.h index 8d056d63..adc2c8ce 100644 --- a/src/qvge/ISceneItemFactory.h +++ b/src/qvge/ISceneItemFactory.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/IUndoManager.h b/src/qvge/IUndoManager.h index 099a098a..82f03186 100644 --- a/src/qvge/IUndoManager.h +++ b/src/qvge/IUndoManager.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvge/Properties.h b/src/qvge/Properties.h index d1d46b1f..34d9dd95 100644 --- a/src/qvge/Properties.h +++ b/src/qvge/Properties.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvgeapp/main.cpp b/src/qvgeapp/main.cpp index e50e3ab5..81b3f6b5 100644 --- a/src/qvgeapp/main.cpp +++ b/src/qvgeapp/main.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -17,11 +17,11 @@ int main(int argc, char *argv[]) QApplication a(argc, argv); Q_INIT_RESOURCE(commonui); Q_INIT_RESOURCE(appbase); + a.setWindowIcon(QIcon(":/Icons/AppIcon")); - a.setWindowIcon(QIcon(":/Icons/AppIcon")); qvgeMainWindow w; w.init(QCoreApplication::arguments()); - w.show(); + return a.exec(); } diff --git a/src/qvgeapp/qvgeMainWindow.cpp b/src/qvgeapp/qvgeMainWindow.cpp index 8932fd52..25c6e94d 100644 --- a/src/qvgeapp/qvgeMainWindow.cpp +++ b/src/qvgeapp/qvgeMainWindow.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -178,7 +178,7 @@ QString qvgeMainWindow::getAboutText() const + QString( "

This is a free software." "
It comes without warranty of any kind. Use it on your own risk." - "

© 2016-2018 Ars L. Masiuk" + "

© 2016-2019 Ars L. Masiuk" "


" "

Credits:" "
Qt framework © The Qt Company Ltd" diff --git a/src/qvgeapp/qvgeMainWindow.h b/src/qvgeapp/qvgeMainWindow.h index 8f0a9aba..1d59d433 100644 --- a/src/qvgeapp/qvgeMainWindow.h +++ b/src/qvgeapp/qvgeMainWindow.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvgeapp/qvgeVersion.h b/src/qvgeapp/qvgeVersion.h index 732f804c..7ea30499 100644 --- a/src/qvgeapp/qvgeVersion.h +++ b/src/qvgeapp/qvgeVersion.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -13,7 +13,7 @@ It can be used freely, maintaining the information above. #include -static QString qvgeVersionString("0.5.2"); +static QString qvgeVersionString("0.5.3"); static QVersionNumber qvgeVersion = QVersionNumber::fromString(qvgeVersionString); diff --git a/src/qvgeapp/qvgeapp.pro b/src/qvgeapp/qvgeapp.pro index 59a2f851..af5983d1 100644 --- a/src/qvgeapp/qvgeapp.pro +++ b/src/qvgeapp/qvgeapp.pro @@ -10,9 +10,9 @@ TEMPLATE = app TARGET = qvgeapp win32{ - VERSION = 0.5.1.0 + VERSION = 0.5.3.0 RC_ICONS = $$PWD/win32/icon.ico - QMAKE_TARGET_COPYRIGHT = (C) 2016-2018 Ars L. Masiuk + QMAKE_TARGET_COPYRIGHT = (C) 2016-2019 Ars L. Masiuk QMAKE_TARGET_DESCRIPTION = Qt Visual Graph Editor QMAKE_TARGET_PRODUCT = qvge } diff --git a/src/qvgeio/CFormatGraphML.cpp b/src/qvgeio/CFormatGraphML.cpp index cb3e4ea1..3c8b1a86 100644 --- a/src/qvgeio/CFormatGraphML.cpp +++ b/src/qvgeio/CFormatGraphML.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -39,7 +39,18 @@ bool CFormatGraphML::save(const QString& fileName, Graph& graph, QString* lastEr xsw.writeStartElement("graph"); - // TO DO: Nodes & Edges + // graph attrs + if (graph.edgeAttrs.contains("direction")) + { + xsw.writeAttribute("edgedefault", graph.edgeAttrs["direction"].defaultValue.toString()); + } + + // nodes + writeNodes(xsw, graph); + + // edges + writeEdges(xsw, graph); + xsw.writeEndElement(); // graph @@ -50,6 +61,56 @@ bool CFormatGraphML::save(const QString& fileName, Graph& graph, QString* lastEr } +void CFormatGraphML::writeNodes(QXmlStreamWriter &xsw, const Graph& graph) const +{ + for (const auto& node : graph.nodes) + { + xsw.writeStartElement("node"); + + // topology + xsw.writeAttribute("id", node.id); + + for (const auto& port : node.ports) + { + xsw.writeStartElement("port"); + + xsw.writeAttribute("name", port.name); + // TO DO: placement, attrs... + + xsw.writeEndElement(); + } + + // attributes + // TO DO + + xsw.writeEndElement(); + } +} + + +void CFormatGraphML::writeEdges(QXmlStreamWriter &xsw, const Graph& graph) const +{ + for (const auto& edge: graph.edges) + { + xsw.writeStartElement("edge"); + + // topology + xsw.writeAttribute("id", edge.id); + xsw.writeAttribute("source", edge.startNodeId); + xsw.writeAttribute("target", edge.endNodeId); + if (edge.startPortId.size()) + xsw.writeAttribute("sourceport", edge.startPortId); + if (edge.endPortId.size()) + xsw.writeAttribute("endport", edge.endPortId); + + // attributes + // TO DO + + xsw.writeEndElement(); + } +} + + void CFormatGraphML::writeAttributes(QXmlStreamWriter &xsw, const AttributeInfos &attrs, const QByteArray &classId) const { for (auto& attr : attrs) diff --git a/src/qvgeio/CFormatGraphML.h b/src/qvgeio/CFormatGraphML.h index 58e1cd8a..4bbb1ef3 100644 --- a/src/qvgeio/CFormatGraphML.h +++ b/src/qvgeio/CFormatGraphML.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ @@ -33,6 +33,8 @@ class CFormatGraphML bool readEdge(int index, const QDomNode &domNode, Graph& graph, const KeyAttrMap& cka) const; void writeAttributes(QXmlStreamWriter &xsw, const AttributeInfos &attrs, const QByteArray &classId) const; + void writeNodes(QXmlStreamWriter &xsw, const Graph& graph) const; + void writeEdges(QXmlStreamWriter &xsw, const Graph& graph) const; enum EdgeType { Directed, diff --git a/src/qvgeio/CGraphBase.cpp b/src/qvgeio/CGraphBase.cpp index 8ac6e092..2ea1dc93 100644 --- a/src/qvgeio/CGraphBase.cpp +++ b/src/qvgeio/CGraphBase.cpp @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */ diff --git a/src/qvgeio/CGraphBase.h b/src/qvgeio/CGraphBase.h index 0ac8cd28..52d34e37 100644 --- a/src/qvgeio/CGraphBase.h +++ b/src/qvgeio/CGraphBase.h @@ -2,7 +2,7 @@ This file is a part of QVGE - Qt Visual Graph Editor -(c) 2016-2018 Ars L. Masiuk (ars.masiuk@gmail.com) +(c) 2016-2019 Ars L. Masiuk (ars.masiuk@gmail.com) It can be used freely, maintaining the information above. */