diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index ef30d0747..f0a335267 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -49,30 +49,6 @@ jobs: cc: clang cxx: clang++ publish: true - - # Qt 5.15 only supports MinGW 8.11. The `windows-latest` and `windows-2022` - # images bundle only 11.2. For now, we must use the older image `windows-2019`. - - name: Windows_MingGW - flavor: Debug - runner: windows-2022 - generator: MinGW Makefiles - qtver: 5.15.2 - qtdir: mingw81_64 - qtstr: windows desktop win64_mingw81 - cc: gcc - cxx: g++ - ctest_exe_args: -tap - - - name: Windows_Release - flavor: Release - runner: windows-2022 - generator: Visual Studio 17 2022 - qtver: 5.15.2 - qtdir: msvc2019_64 - qtstr: windows desktop win64_msvc2019_64 - ctest_exe_args: -tap - publish: true - runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v2 @@ -96,33 +72,6 @@ jobs: brew ls --formula | grep -wq msgpack || brew install msgpack brew link qt5 --force - - name: Windows - Setup - if: ${{ startsWith(matrix.runner, 'windows') }} - env: - QT_DIR: ${{ github.workspace }}\${{ matrix.qtver }}\${{ matrix.qtdir }} - run: | - New-Item -Path .\build -Name "build" -ItemType "directory" - Invoke-WebRequest https://github.com/neovim/neovim/releases/download/stable/nvim-win64.zip -OutFile nvim-win64.zip - Expand-Archive -Path nvim-win64.zip -DestinationPath .\build\ - Add-Content -Path $env:GITHUB_PATH -Value ${{ github.workspace }}\build\nvim-win64\bin\ - Add-Content -Path $env:GITHUB_ENV -Value "CMAKE_PREFIX_PATH=$env:QT_DIR;$env:QT_DIR\lib\cmake" - Add-Content -Path $env:GITHUB_PATH -Value "${{ env.qt_dir }}" - Add-Content -Path $env:GITHUB_PATH -Value "${{ env.qt_dir }}\bin" - - - name: Qt Cache Restore - if: ${{ matrix.qtver }} - id: cache-qt - uses: actions/cache@v2 - with: - path: ${{ matrix.qtver }}\${{ matrix.qtdir }} - key: qt-${{ runner.os }}-${{ matrix.qtver }}-${{ matrix.qtdir }} - - - name: Qt Cache Install - if: ${{ matrix.qtver && steps.cache-qt.outputs.cache-hit != 'true' }} - run: | - pip install aqtinstall - python -m aqt install ${{ matrix.qtver }} ${{ matrix.qtstr }} - # # Build and Test # @@ -169,16 +118,6 @@ jobs: macdeployqt ./build/bin/nvim-qt.app -dmg mv ./build/bin/nvim-qt.dmg neovim-qt.dmg - - name: Windows - Publish - if: ${{ matrix.publish && startsWith(matrix.runner, 'windows') }} - run: | - cmake --build ./build --target install - Push-Location ${{ github.workspace }}/build - cpack --verbose -G WIX - Pop-Location - Compress-Archive -Path ./install -DestinationPath neovim-qt.zip - Move-Item -Path ./build/neovim-qt-installer.msi -Destination neovim-qt-installer.msi - - name: Upload Artifacts if: ${{ matrix.publish }} uses: actions/upload-artifact@v2 diff --git a/contrib/appveyor.yml b/contrib/appveyor.yml index 41d6a863f..ded7cfd9f 100644 --- a/contrib/appveyor.yml +++ b/contrib/appveyor.yml @@ -10,16 +10,19 @@ environment: GENERATOR: MinGW Makefiles RELEASE_ARTIFACT: true CMAKE_PATH_PREFIX: C:\Qt\5.15\mingw81_64\lib\cmake + CMAKE_BUILD_TYPE: Release - PlatformToolset: VisualStudio2019 QTPATH: C:\Qt\5.15\msvc2019_64 GENERATOR: Visual Studio 16 CMAKE_PATH_PREFIX: C:\Qt\5.15\msvc2019_64\lib\cmake + CMAKE_BUILD_TYPE: Debug - PlatformToolset: MinGW-Win64-Qt6 QTPATH: C:\Qt\6.2.4\mingw_64 GENERATOR: MinGW Makefiles RELEASE_ARTIFACT: false CMAKE_PATH_PREFIX: C:\Qt\6.2.4\mingw_64\lib\cmake EXTRA_CMAKE_ARGS: -DWITH_QT=Qt6 + CMAKE_BUILD_TYPE: Release configuration: - RelWithDebInfo matrix: @@ -42,7 +45,7 @@ build_script: - echo %PATH% - mkdir build - cd build -- cmake -G "%GENERATOR%" -DCMAKE_PREFIX_PATH="%CMAKE_PATH_PREFIX%" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../INSTALL -DENABLE_TESTS=ON %EXTRA_CMAKE_ARGS% .. +- cmake -G "%GENERATOR%" -DCMAKE_PREFIX_PATH="%CMAKE_PATH_PREFIX%" -DCMAKE_BUILD_TYPE=%CMAKE_BUILD_TYPE% -DCMAKE_INSTALL_PREFIX=../INSTALL -DENABLE_TESTS=ON %EXTRA_CMAKE_ARGS% .. - cmake --build . --config Release --target install - cpack --verbose -G WIX test_script: diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 4079279a7..7fa1f8d1f 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -1,6 +1,7 @@ #include "mainwindow.h" #include +#include #include #include #include @@ -42,11 +43,11 @@ void MainWindow::init(NeovimConnector *c) } m_shell = new Shell(c); + m_shell->setParent(this); addToolBar(&m_tabline); m_nvim = c; - m_nvim->setParent(this); // GuiShowContextMenu - right click context menu and actions. m_contextMenu = new ContextMenu(c, this); @@ -235,6 +236,18 @@ void MainWindow::neovimGuiCloseRequest(int status) { m_neovim_requested_close = true; m_exitStatus = status; + + // Try to wait for neovim to quit + QTimer timer; + timer.setSingleShot(true); + QEventLoop loop; + connect(m_nvim, &NeovimConnector::processExited, &loop, &QEventLoop::quit); + connect(m_nvim, &NeovimConnector::aboutToClose, &loop, &QEventLoop::quit); + timer.start(500); + loop.exec(); + bool timed_out = !timer.isActive(); + qDebug() << "Waited for neovim close, timed out:" << timed_out; + QMainWindow::close(); m_neovim_requested_close = false; } diff --git a/src/gui/shell.cpp b/src/gui/shell.cpp index 28152bc0a..475787e9c 100644 --- a/src/gui/shell.cpp +++ b/src/gui/shell.cpp @@ -92,6 +92,8 @@ Shell::Shell(NeovimConnector *nvim, QWidget *parent) return; } + m_nvim->setParent(this); + connect(m_nvim, &NeovimConnector::error, this, &Shell::neovimError); connect(m_nvim, &NeovimConnector::processExited, diff --git a/src/gui/shell.h b/src/gui/shell.h index 674618180..695c88a54 100644 --- a/src/gui/shell.h +++ b/src/gui/shell.h @@ -70,6 +70,7 @@ class Shell: public ShellWidget static void DispatchRedrawNotifications( T* pThis, const QVariantList& args) noexcept; + NeovimConnector* nvim() { return m_nvim; } signals: void neovimTitleChanged(const QString &title); void neovimBusyChanged(bool); diff --git a/src/msgpackiodevice.cpp b/src/msgpackiodevice.cpp index 13864de5a..23ea6a9d6 100644 --- a/src/msgpackiodevice.cpp +++ b/src/msgpackiodevice.cpp @@ -60,6 +60,7 @@ MsgpackIODevice::MsgpackIODevice(QIODevice* dev, QObject* parent) m_dev->setParent(this); connect(m_dev, &QAbstractSocket::readyRead, this, &MsgpackIODevice::dataAvailable); + connect(m_dev, &QIODevice::aboutToClose, this, &MsgpackIODevice::aboutToClose); if ( !m_dev->isSequential() ) { setError(InvalidDevice, tr("IO device needs to be sequential")); diff --git a/src/msgpackiodevice.h b/src/msgpackiodevice.h index c58cbbef6..0810543ad 100644 --- a/src/msgpackiodevice.h +++ b/src/msgpackiodevice.h @@ -71,6 +71,7 @@ class MsgpackIODevice: public QObject /** A notification with the given name and arguments was received */ void notification(const QByteArray &name, const QVariantList& args); void encodingChanged(const QByteArray& encoding); + void aboutToClose(); protected: void sendError(const msgpack_object& req, const QString& msg); diff --git a/src/neovimconnector.cpp b/src/neovimconnector.cpp index c9b4e6b1d..0d82d28b2 100644 --- a/src/neovimconnector.cpp +++ b/src/neovimconnector.cpp @@ -37,6 +37,9 @@ NeovimConnector::NeovimConnector(MsgpackIODevice *dev) connect(m_dev, &MsgpackIODevice::error, this, &NeovimConnector::msgpackError); + connect(m_dev, &MsgpackIODevice::aboutToClose, this, &NeovimConnector::aboutToClose); + + m_dev->setParent(this); if ( !m_dev->isOpen() ) { return; diff --git a/src/neovimconnector.h b/src/neovimconnector.h index 065d42206..7f96174e5 100644 --- a/src/neovimconnector.h +++ b/src/neovimconnector.h @@ -106,6 +106,7 @@ class NeovimConnector: public QObject void ready(); void error(NeovimQt::NeovimConnector::NeovimError); void processExited(int exitCode); + void aboutToClose(); public slots: void fatalTimeout(); diff --git a/test/common_gui.cpp b/test/common_gui.cpp index a85718c3b..456c342e3 100644 --- a/test/common_gui.cpp +++ b/test/common_gui.cpp @@ -35,7 +35,7 @@ template static void ValidateNeovimConnection(T* obj) noexcept Q_ASSERT(obj->isNeovimAttached()); } -std::pair CreateShellWidget() noexcept +QSharedPointer CreateShellWidget() noexcept { DisableLocalGInitVim(); NeovimConnector* c{ NeovimConnector::spawn(cs_argsNone) }; @@ -45,10 +45,10 @@ std::pair CreateShellWidget() noexcept ValidateNeovimConnection(s); - return { c, s }; + return QSharedPointer(s); } -std::pair CreateMainWindow() noexcept +QSharedPointer CreateMainWindow() noexcept { NeovimConnector* c{ NeovimConnector::spawn(cs_argsNone) }; MainWindow* w{ new MainWindow{ c } }; @@ -57,10 +57,10 @@ std::pair CreateMainWindow() noexcept ValidateNeovimConnection(w); - return { c, w }; + return QSharedPointer(w); } -std::pair CreateMainWindowWithRuntime() noexcept +QSharedPointer CreateMainWindowWithRuntime() noexcept { static const QStringList cs_argsNoneRuntime{ "-u", "NONE", "--cmd", "set rtp+=" + GetRuntimeAbsolutePath() @@ -74,7 +74,7 @@ std::pair CreateMainWindowWithRuntime() noexcept ValidateNeovimConnection(w); - return { c, w }; + return QSharedPointer(w); } } // namespace NeovimQt diff --git a/test/common_gui.h b/test/common_gui.h index 4c981a013..24a1bd74b 100644 --- a/test/common_gui.h +++ b/test/common_gui.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -7,10 +8,10 @@ namespace NeovimQt { -std::pair CreateShellWidget() noexcept; +QSharedPointer CreateShellWidget() noexcept; -std::pair CreateMainWindow() noexcept; +QSharedPointer CreateMainWindow() noexcept; -std::pair CreateMainWindowWithRuntime() noexcept; +QSharedPointer CreateMainWindowWithRuntime() noexcept; } // namespace NeovimQt diff --git a/test/tst_neovimconnector.cpp b/test/tst_neovimconnector.cpp index 07098832e..15a6dccd7 100644 --- a/test/tst_neovimconnector.cpp +++ b/test/tst_neovimconnector.cpp @@ -20,6 +20,7 @@ private slots: QCOMPARE(c.canReconnect(), false); NeovimConnector *spawned = NeovimConnector::spawn({"-u", "NONE"}); + spawned->setParent(this); QCOMPARE(spawned->connectionType(), NeovimConnector::SpawnedConnection); QCOMPARE(spawned->canReconnect(), true); @@ -29,6 +30,7 @@ private slots: void isReady() { NeovimConnector *c = NeovimConnector::spawn({"-u", "NONE"}); + c->setParent(this); QSignalSpy onReady(c, SIGNAL(ready())); QVERIFY(onReady.isValid()); @@ -38,7 +40,7 @@ private slots: void encodeDecode() { NeovimConnector *c = NeovimConnector::spawn({"-u", "NONE"}); - + c->setParent(this); // This will print a warning, but should succeed QString s = "ç日本語"; QByteArray bytes = c->encode(s); @@ -55,6 +57,7 @@ private slots: void connectToNeovimTCP() { NeovimConnector *c = NeovimConnector::connectToNeovim("127.0.0.1:64999"); + c->setParent(this); QCOMPARE(c->connectionType(), NeovimConnector::HostConnection); QSignalSpy onError(c, SIGNAL(error(NeovimError))); QVERIFY(onError.isValid()); @@ -68,6 +71,7 @@ private slots: void connectToNeovimSocket() { NeovimConnector *c = NeovimConnector::connectToNeovim("NoSuchFile"); + c->setParent(this); QCOMPARE(c->connectionType(), NeovimConnector::SocketConnection); QSignalSpy onError(c, SIGNAL(error(NeovimError))); QVERIFY(onError.isValid()); @@ -82,6 +86,7 @@ private slots: void connectToNeovimEnvEmpty() { // This is the same as ::spawn() NeovimConnector *c = NeovimConnector::connectToNeovim(""); + c->setParent(this); QSignalSpy onReady(c, SIGNAL(ready())); QVERIFY(onReady.isValid()); QVERIFY(SPYWAIT(onReady)); diff --git a/test/tst_qsettings.cpp b/test/tst_qsettings.cpp index a5b1c4ae7..1e5172d43 100644 --- a/test/tst_qsettings.cpp +++ b/test/tst_qsettings.cpp @@ -25,9 +25,9 @@ private slots: void GuiTreeView() noexcept; }; -static void SendNeovimCommand(NeovimConnector& connector, const QString& command) noexcept +static void SendNeovimCommand(NeovimConnector* connector, const QString& command) noexcept { - QSignalSpy spyCommand{ connector.api0()->vim_command_output(connector.encode(command)), + QSignalSpy spyCommand{ connector->api0()->vim_command_output(connector->encode(command)), &MsgpackRequest::finished }; QVERIFY(spyCommand.isValid()); @@ -59,15 +59,13 @@ void TestQSettings::OptionLineGrid() noexcept QSettings settings; settings.setValue("ext_linegrid", true); - auto csWithLineGrid{ CreateShellWidget() }; - Shell* sWithLineGrid{ csWithLineGrid.second }; + auto sWithLineGrid = CreateShellWidget(); ShellOptions shellOptionsWithLineGrid{ sWithLineGrid->GetShellOptions() }; QCOMPARE(shellOptionsWithLineGrid.IsLineGridEnabled(), true); settings.setValue("ext_linegrid", false); - auto csLegacy{ CreateShellWidget() }; - Shell* sLegacy{ csLegacy.second }; + auto sLegacy = CreateShellWidget(); ShellOptions shellOptionsLegacy{ sLegacy->GetShellOptions() }; QCOMPARE(shellOptionsLegacy.IsLineGridEnabled(), false); @@ -75,22 +73,25 @@ void TestQSettings::OptionLineGrid() noexcept void TestQSettings::OptionPopupMenu() noexcept { - auto cw{ CreateMainWindowWithRuntime() }; - NeovimConnector& connector{ *cw.first }; + auto w = CreateMainWindowWithRuntime(); + NeovimConnector* connector = w->shell()->nvim(); QSettings settings; + QSignalSpy spy_fontchange(w->shell(), &ShellWidget::shellFontChanged); SendNeovimCommand(connector, "GuiPopupmenu 1"); + SPYWAIT(spy_fontchange, 2500 /*msec*/); QCOMPARE(settings.value("ext_popupmenu").toBool(), true); SendNeovimCommand(connector, "GuiPopupmenu 0"); + SPYWAIT(spy_fontchange, 2500 /*msec*/); QCOMPARE(settings.value("ext_popupmenu").toBool(), false); } void TestQSettings::OptionTabline() noexcept { - auto cw{ CreateMainWindowWithRuntime() }; - NeovimConnector& connector{ *cw.first }; + auto w = CreateMainWindowWithRuntime(); + NeovimConnector* connector = w->shell()->nvim(); QSettings settings; @@ -103,9 +104,8 @@ void TestQSettings::OptionTabline() noexcept void TestQSettings::GuiFont() noexcept { - auto cw{ CreateMainWindowWithRuntime() }; - NeovimConnector& connector{ *cw.first }; - MainWindow& window{ *cw.second }; + auto w = CreateMainWindowWithRuntime(); + NeovimConnector* connector = w->shell()->nvim(); QSettings settings; @@ -113,14 +113,14 @@ void TestQSettings::GuiFont() noexcept const QString fontCommand{ QStringLiteral("GuiFont! %1").arg(fontDesc) }; SendNeovimCommand(connector, fontCommand); - QCOMPARE(window.shell()->fontDesc(), fontDesc); + QCOMPARE(w->shell()->fontDesc(), fontDesc); QCOMPARE(settings.value("Gui/Font").toString(), fontDesc); } void TestQSettings::GuiScrollBar() noexcept { - auto cw{ CreateMainWindowWithRuntime() }; - NeovimConnector& connector{ *cw.first }; + auto w = CreateMainWindowWithRuntime(); + NeovimConnector* connector = w->shell()->nvim(); QSettings settings; @@ -132,8 +132,8 @@ void TestQSettings::GuiScrollBar() noexcept } void TestQSettings::GuiTreeView() noexcept { - auto cw{ CreateMainWindowWithRuntime() }; - NeovimConnector& connector{ *cw.first }; + auto w = CreateMainWindowWithRuntime(); + NeovimConnector* connector = w->shell()->nvim(); QSettings settings; diff --git a/test/tst_shell.cpp b/test/tst_shell.cpp index 83a6d651a..3d3f27f32 100644 --- a/test/tst_shell.cpp +++ b/test/tst_shell.cpp @@ -64,10 +64,9 @@ void TestShell::benchStart() noexcept { QBENCHMARK { - auto cs{ CreateShellWidget() }; - Shell* s{ cs.second }; + auto s = CreateShellWidget(); - QSignalSpy onResize(s, &Shell::neovimResized); + QSignalSpy onResize(s.get(), &Shell::neovimResized); QVERIFY(onResize.isValid()); QVERIFY(SPYWAIT(onResize)); } @@ -75,24 +74,22 @@ void TestShell::benchStart() noexcept void TestShell::startVarsShellWidget() noexcept { - auto cs{ CreateShellWidget() }; - NeovimConnector* c{ cs.first }; + auto s = CreateShellWidget(); - checkStartVars(c); + checkStartVars(s->nvim()); } void TestShell::startVarsMainWindow() noexcept { - auto cw{ CreateMainWindow() }; - NeovimConnector* c{ cw.first }; - - checkStartVars(c); + auto w = CreateMainWindow(); + checkStartVars(w->shell()->nvim()); } void TestShell::gviminit() noexcept { qputenv("GVIMINIT", "let g:test_gviminit = 1"); - NeovimConnector* c{ CreateShellWidget().first }; + auto s = CreateShellWidget(); + NeovimConnector* c = s->nvim(); MsgpackRequest* req{ c->api0()->vim_command_output(c->encode("echo g:test_gviminit")) }; QSignalSpy cmd{ req, &MsgpackRequest::finished }; @@ -103,9 +100,8 @@ void TestShell::gviminit() noexcept void TestShell::guiShimCommands() noexcept { - auto cw{ CreateMainWindowWithRuntime() }; - NeovimConnector* c{ cw.first }; - MainWindow* w{ cw.second }; + auto w = CreateMainWindowWithRuntime(); + auto c = w->shell()->nvim(); QObject::connect(c->neovimObject(), &NeovimApi1::err_vim_command_output, SignalPrintError); @@ -173,9 +169,8 @@ void TestShell::CloseEvent_data() noexcept void TestShell::CloseEvent() noexcept { - auto cw{ CreateMainWindowWithRuntime() }; - NeovimConnector* c{ cw.first }; - MainWindow* w{ cw.second }; + auto w = CreateMainWindowWithRuntime(); + auto c = w->shell()->nvim(); QFETCH(int, msgpack_status); QFETCH(int, exit_status); @@ -185,7 +180,7 @@ void TestShell::CloseEvent() noexcept QSignalSpy onClose(w->shell(), &Shell::neovimGuiCloseRequest); QVERIFY(onClose.isValid()); - QSignalSpy onWindowClosing(w, &MainWindow::closing); + QSignalSpy onWindowClosing(w.get(), &MainWindow::closing); QVERIFY(onWindowClosing.isValid()); c->api0()->vim_command(c->encode(command)); @@ -229,8 +224,8 @@ void TestShell::GetClipboard_data() noexcept void TestShell::GetClipboard() noexcept { - auto cw{ CreateMainWindowWithRuntime() }; - NeovimConnector* c{ cw.first }; + auto w = CreateMainWindowWithRuntime(); + NeovimConnector* c = w->shell()->nvim(); QFETCH(char, reg); QFETCH(QByteArray, register_data); @@ -267,8 +262,8 @@ void TestShell::SetClipboard_data() noexcept void TestShell::SetClipboard() noexcept { - auto cw{ CreateMainWindowWithRuntime() }; - NeovimConnector* c{ cw.first }; + auto w = CreateMainWindowWithRuntime(); + NeovimConnector* c = w->shell()->nvim(); QFETCH(char, reg); QFETCH(QByteArray, register_data);