diff --git a/MiniZincIDE/mainwindow.cpp b/MiniZincIDE/mainwindow.cpp
index e8ac8af..932ff85 100644
--- a/MiniZincIDE/mainwindow.cpp
+++ b/MiniZincIDE/mainwindow.cpp
@@ -3085,17 +3085,19 @@ void MainWindow::startVisualisation(const QString& model, const QStringList& dat
QSettings settings;
settings.beginGroup("ide");
bool reuseVis = settings.value("reuseVis", false).toBool();
- int port = settings.value("visPort", 3000).toInt();
+ int httpPort = settings.value("visPort", 3000).toInt();
+ int wsPort = settings.value("visWsPort", 3100).toInt();
bool printUrl = settings.value("printVisUrl", false).toBool();
settings.endGroup();
- if (server == nullptr || server->desiredPort() != port) {
- try {
- server = new Server(port, this);
- } catch (ServerError& e) {
- QMessageBox::warning(this, "MiniZinc IDE", e.message(), QMessageBox::Ok);
- return;
- }
+ if (server == nullptr) {
+ server = new Server(this);
+ }
+ try {
+ server->listen(httpPort, wsPort);
+ } catch (ServerError& e) {
+ QMessageBox::warning(this, "MiniZinc IDE", e.message(), QMessageBox::Ok);
+ return;
}
QFileInfo modelFileInfo(model);
diff --git a/MiniZincIDE/preferencesdialog.cpp b/MiniZincIDE/preferencesdialog.cpp
index 50e25ab..8380bfb 100644
--- a/MiniZincIDE/preferencesdialog.cpp
+++ b/MiniZincIDE/preferencesdialog.cpp
@@ -72,6 +72,7 @@ PreferencesDialog::PreferencesDialog(bool addNewSolver, QWidget *parent) :
}
ui->reuseVis_checkBox->setChecked(settings.value("reuseVis", false).toBool());
ui->visPort_spinBox->setValue(settings.value("visPort", 3000).toInt());
+ ui->visWsPort_spinBox->setValue(settings.value("visWsPort", 3100).toInt());
ui->visUrl_checkBox->setChecked(settings.value("printVisUrl", false).toBool());
ui->printCommand_checkBox->setChecked(settings.value("printCommand", false).toBool());
ui->indentSize_spinBox->setValue(settings.value("indentSize", 2).toInt());
@@ -919,6 +920,7 @@ void PreferencesDialog::on_PreferencesDialog_accepted()
settings.setValue("printCommand", ui->printCommand_checkBox->isChecked());
settings.setValue("reuseVis", ui->reuseVis_checkBox->isChecked());
settings.setValue("visPort", ui->visPort_spinBox->value());
+ settings.setValue("visWsPort", ui->visWsPort_spinBox->value());
settings.setValue("printVisUrl", ui->visUrl_checkBox->isChecked());
settings.setValue("theme", ui->theme_comboBox->currentIndex());
settings.setValue("indentTabs", ui->indentTabs_radioButton->isChecked());
diff --git a/MiniZincIDE/preferencesdialog.ui b/MiniZincIDE/preferencesdialog.ui
index b712f84..6d9239c 100644
--- a/MiniZincIDE/preferencesdialog.ui
+++ b/MiniZincIDE/preferencesdialog.ui
@@ -794,34 +794,52 @@
Visualisation
-
- -
-
-
- Reuse existing visualisation window when starting a new run
-
-
-
- -
-
-
- Start the visualisation server on this port (0 for auto):
-
-
-
- -
-
-
- 65535
-
-
-
- -
-
-
- Print the visualisation server URL in the output window
-
-
+
+
-
+
+
-
+
+
+ Reuse existing visualisation window when starting a new run
+
+
+
+ -
+
+
+ HTTP server port (0 for auto):
+
+
+
+ -
+
+
+ 65535
+
+
+
+ -
+
+
+ WebSocket server port (0 for auto):
+
+
+
+ -
+
+
+ 65535
+
+
+
+ -
+
+
+ Print the visualisation server URL in the output window
+
+
+
+
diff --git a/MiniZincIDE/server.cpp b/MiniZincIDE/server.cpp
index caf4eb9..441c23c 100644
--- a/MiniZincIDE/server.cpp
+++ b/MiniZincIDE/server.cpp
@@ -178,26 +178,11 @@ void VisConnector::webSocketMessageReceived(const QString& message)
}
}
-Server::Server(quint16 port, QObject *parent) :
+Server::Server(QObject *parent) :
QObject(parent),
http(new QTcpServer(this)),
ws(new QWebSocketServer("MiniZincIDE", QWebSocketServer::NonSecureMode, this))
{
- initialPort = port;
- qint16 p = port;
- for (int i = 0; i < 10; i++) {
- if (http->listen(QHostAddress::LocalHost, p) || p == 0) {
- break;
- }
- p++;
- }
- if (!http->isListening()) {
- throw ServerError("Failed to start HTTP visualisation server");
- }
- if (!ws->listen(QHostAddress::LocalHost)) {
- throw ServerError("Failed to start WebSocket visualisation server");
- }
-
connect(http, &QTcpServer::newConnection, this, &Server::newHttpClient);
connect(ws, &QWebSocketServer::newConnection, this, &Server::newWebSocketClient);
}
@@ -209,6 +194,39 @@ Server::~Server()
}
}
+void Server::listen(quint16 httpPort, quint16 wsPort)
+{
+ if (!http->isListening() || httpPort != initialHttpPort) {
+ initialHttpPort = httpPort;
+ qint16 p = httpPort;
+ http->close();
+ for (int i = 0; i < 10; i++) {
+ if (http->listen(QHostAddress::LocalHost, p) || p == 0) {
+ break;
+ }
+ p++;
+ }
+ if (!http->isListening()) {
+ throw ServerError("Failed to start HTTP visualisation server");
+ }
+ }
+
+ if (!ws->isListening() || wsPort != initialWsPort) {
+ initialWsPort = wsPort;
+ quint16 p = wsPort;
+ ws->close();
+ for (int i = 0; i < 10; i++) {
+ if (ws->listen(QHostAddress::LocalHost, p) || p == 0) {
+ break;
+ }
+ p++;
+ }
+ if (!ws->isListening()) {
+ throw ServerError("Failed to start WebSocket visualisation server");
+ }
+ }
+}
+
VisConnector* Server::addConnector(const QString& label, const QStringList& roots)
{
auto* c = new VisConnector(this);
diff --git a/MiniZincIDE/server.h b/MiniZincIDE/server.h
index 9c08001..49711a3 100644
--- a/MiniZincIDE/server.h
+++ b/MiniZincIDE/server.h
@@ -53,11 +53,15 @@ class Server : public QObject
{
Q_OBJECT
public:
- explicit Server(quint16 port = 3000, QObject *parent = nullptr);
+ explicit Server(QObject *parent = nullptr);
~Server();
+
+ void listen(quint16 httpPort = 3000, quint16 wsPort = 3100);
+
QString address() const { return http->serverAddress().toString(); }
quint16 port() const { return http->serverPort(); }
- quint16 desiredPort() const { return initialPort; }
+ quint16 desiredHttpPort() const { return initialHttpPort; }
+ quint16 desiredWsPort() const { return initialWsPort; }
VisConnector* addConnector(const QString& label, const QStringList& roots);
void clear();
@@ -78,7 +82,8 @@ private slots:
QWebSocketServer* ws;
QList connectors;
QList clients;
- quint16 initialPort;
+ quint16 initialHttpPort;
+ quint16 initialWsPort;
};
#endif // SERVER_H