aboutsummaryrefslogtreecommitdiffstats
path: root/gui
diff options
context:
space:
mode:
Diffstat (limited to 'gui')
-rw-r--r--gui/base.qrc1
-rw-r--r--gui/basewindow.cc27
-rw-r--r--gui/basewindow.h2
-rw-r--r--gui/line_editor.cc30
-rw-r--r--gui/line_editor.h1
-rw-r--r--gui/resources/save_svg.pngbin0 -> 1569 bytes
-rw-r--r--gui/treemodel.cc11
7 files changed, 58 insertions, 14 deletions
diff --git a/gui/base.qrc b/gui/base.qrc
index 0671fa9e..509a584f 100644
--- a/gui/base.qrc
+++ b/gui/base.qrc
@@ -30,5 +30,6 @@
<file>resources/group.png</file>
<file>resources/camera.png</file>
<file>resources/film.png</file>
+ <file>resources/save_svg.png</file>
</qresource>
</RCC>
diff --git a/gui/basewindow.cc b/gui/basewindow.cc
index 7f767c58..08cbafe4 100644
--- a/gui/basewindow.cc
+++ b/gui/basewindow.cc
@@ -266,6 +266,11 @@ void BaseMainWindow::createMenusAndBars()
actionMovie->setChecked(false);
connect(actionMovie, &QAction::triggered, this, &BaseMainWindow::saveMovie);
+ actionSaveSVG = new QAction("Save SVG", this);
+ actionSaveSVG->setIcon(QIcon(":/icons/resources/save_svg.png"));
+ actionSaveSVG->setStatusTip("Saving a SVG");
+ connect(actionSaveSVG, &QAction::triggered, this, &BaseMainWindow::saveSVG);
+
// set initial state
fpgaView->enableDisableDecals(actionDisplayBel->isChecked(), actionDisplayWire->isChecked(),
actionDisplayPip->isChecked(), actionDisplayGroups->isChecked());
@@ -334,6 +339,7 @@ void BaseMainWindow::createMenusAndBars()
deviceViewToolBar->addSeparator();
deviceViewToolBar->addAction(actionScreenshot);
deviceViewToolBar->addAction(actionMovie);
+ deviceViewToolBar->addAction(actionSaveSVG);
// Add status bar with progress bar
statusBar = new QStatusBar();
@@ -416,6 +422,27 @@ void BaseMainWindow::saveMovie()
fpgaView->movieStop();
}
}
+
+void BaseMainWindow::saveSVG()
+{
+ QString fileName = QFileDialog::getSaveFileName(this, QString("Save SVG"), QString(), QString("*.svg"));
+ if (!fileName.isEmpty()) {
+ if (!fileName.endsWith(".svg"))
+ fileName += ".svg";
+ bool ok;
+ QString options =
+ QInputDialog::getText(this, "Save SVG", tr("Save options:"), QLineEdit::Normal, "scale=500", &ok);
+ if (ok) {
+ try {
+ ctx->writeSVG(fileName.toStdString(), options.toStdString());
+ log("Saving SVG successful.\n");
+ } catch (const log_execution_error_exception &ex) {
+ log("Saving SVG failed.\n");
+ }
+ }
+ }
+}
+
void BaseMainWindow::pack_finished(bool status)
{
disableActions();
diff --git a/gui/basewindow.h b/gui/basewindow.h
index fe9dfdf2..f90991e1 100644
--- a/gui/basewindow.h
+++ b/gui/basewindow.h
@@ -85,6 +85,7 @@ class BaseMainWindow : public QMainWindow
void screenshot();
void saveMovie();
+ void saveSVG();
Q_SIGNALS:
void contextChanged(Context *ctx);
@@ -134,6 +135,7 @@ class BaseMainWindow : public QMainWindow
QAction *actionScreenshot;
QAction *actionMovie;
+ QAction *actionSaveSVG;
};
NEXTPNR_NAMESPACE_END
diff --git a/gui/line_editor.cc b/gui/line_editor.cc
index b25f4031..3e1000dc 100644
--- a/gui/line_editor.cc
+++ b/gui/line_editor.cc
@@ -19,6 +19,8 @@
*/
#include "line_editor.h"
+#include <QApplication>
+#include <QClipboard>
#include <QKeyEvent>
#include <QToolTip>
#include "ColumnFormatter.h"
@@ -43,8 +45,19 @@ LineEditor::LineEditor(ParseHelper *helper, QWidget *parent) : QLineEdit(parent)
void LineEditor::keyPressEvent(QKeyEvent *ev)
{
-
- if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) {
+ if (ev->matches(QKeySequence::Paste)) {
+ QString clipboard = QApplication::clipboard()->text();
+ if (clipboard.isEmpty())
+ return;
+ if (clipboard.contains('\n')) {
+ QStringList clipboard_lines = clipboard.split('\n');
+ for (int i = 0; i < clipboard_lines.size(); i++) {
+ addLineToHistory(clipboard_lines[i]);
+ Q_EMIT textLineInserted(clipboard_lines[i]);
+ }
+ return;
+ }
+ } else if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) {
QToolTip::hideText();
if (lines.empty())
return;
@@ -79,13 +92,18 @@ bool LineEditor::focusNextPrevChild(bool next) { return false; }
void LineEditor::textInserted()
{
- if (lines.empty() || lines.back() != text())
- lines += text();
+ addLineToHistory(text());
+ clear();
+ Q_EMIT textLineInserted(lines.back());
+}
+
+void LineEditor::addLineToHistory(QString line)
+{
+ if (lines.empty() || lines.back() != line)
+ lines += line;
if (lines.size() > 100)
lines.removeFirst();
index = lines.size();
- clear();
- Q_EMIT textLineInserted(lines.back());
}
void LineEditor::showContextMenu(const QPoint &pt) { contextMenu->exec(mapToGlobal(pt)); }
diff --git a/gui/line_editor.h b/gui/line_editor.h
index a779072f..05a6cf1c 100644
--- a/gui/line_editor.h
+++ b/gui/line_editor.h
@@ -47,6 +47,7 @@ class LineEditor : public QLineEdit
void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE;
bool focusNextPrevChild(bool next) Q_DECL_OVERRIDE;
void autocomplete();
+ void addLineToHistory(QString line);
private:
int index;
diff --git a/gui/resources/save_svg.png b/gui/resources/save_svg.png
new file mode 100644
index 00000000..c7a5da5e
--- /dev/null
+++ b/gui/resources/save_svg.png
Binary files differ
diff --git a/gui/treemodel.cc b/gui/treemodel.cc
index 97cc8883..448c9794 100644
--- a/gui/treemodel.cc
+++ b/gui/treemodel.cc
@@ -97,12 +97,7 @@ void IdStringList::updateElements(Context *ctx, std::vector<IdString> elements)
auto parts_a = alphaNumSplit(a->name());
auto parts_b = alphaNumSplit(b->name());
- // Short-circuit for different part count.
- if (parts_a.size() != parts_b.size()) {
- return parts_a.size() < parts_b.size();
- }
-
- for (size_t i = 0; i < parts_a.size(); i++) {
+ for (size_t i = 0; i < parts_a.size() && i < parts_b.size(); i++) {
auto &part_a = parts_a.at(i);
auto &part_b = parts_b.at(i);
@@ -134,8 +129,8 @@ void IdStringList::updateElements(Context *ctx, std::vector<IdString> elements)
return part_a < part_b;
}
- // Same string.
- return true;
+ // One string is equal to or a subset of the other, compare length.
+ return parts_a.size() < parts_b.size();
});
}