From 5db4b129c02b46ccdfe912017878793544d4f96a Mon Sep 17 00:00:00 2001 From: kleph Date: Fri, 27 Oct 2023 16:33:56 +0200 Subject: [PATCH 1/4] Implement open recent file menu --- resources/ui/carla_host.ui | 21 ++++++++-- source/frontend/carla_host.py | 73 +++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/resources/ui/carla_host.ui b/resources/ui/carla_host.ui index 30e4cb6ec..34abef0a1 100644 --- a/resources/ui/carla_host.ui +++ b/resources/ui/carla_host.ui @@ -67,7 +67,16 @@ 0 - + + 0 + + + 0 + + + 0 + + 0 @@ -463,17 +472,23 @@ 0 0 1045 - 25 + 30 &File + + + Open Recent... + + + @@ -1008,7 +1023,7 @@ 0 - + false diff --git a/source/frontend/carla_host.py b/source/frontend/carla_host.py index 5c7f46b98..216d6d177 100644 --- a/source/frontend/carla_host.py +++ b/source/frontend/carla_host.py @@ -169,6 +169,8 @@ class HostWindow(QMainWindow): self.fCurrentlyRemovingAllPlugins = False self.fHasLoadedLv2Plugins = False + self.fRecentFileList = [] + self.fLastTransportBPM = 0.0 self.fLastTransportFrame = 0 self.fLastTransportState = False @@ -249,6 +251,7 @@ class HostWindow(QMainWindow): if self.host.isControl: self.ui.act_file_new.setVisible(False) self.ui.act_file_open.setVisible(False) + self.ui.menu_Open_Recent.setVisible(False) self.ui.act_file_save_as.setVisible(False) self.ui.tabUtils.removeTab(0) else: @@ -275,6 +278,7 @@ class HostWindow(QMainWindow): self.ui.act_file_new.setEnabled(False) self.ui.act_file_open.setEnabled(False) + self.ui.menu_Open_Recent.setEnabled(False) self.ui.act_file_save.setEnabled(False) self.ui.act_file_save_as.setEnabled(False) self.ui.act_engine_stop.setEnabled(False) @@ -438,6 +442,7 @@ class HostWindow(QMainWindow): # Load Settings self.loadSettings(True) + self.updateRecentFiles() # ---------------------------------------------------------------------------------------------------- # Set-up Canvas @@ -460,6 +465,7 @@ class HostWindow(QMainWindow): self.ui.act_file_refresh.setIcon(getIcon('view-refresh', 16, 'svgz')) self.ui.act_file_new.setIcon(getIcon('document-new', 16, 'svgz')) self.ui.act_file_open.setIcon(getIcon('document-open', 16, 'svgz')) + self.ui.menu_Open_Recent.setIcon(getIcon('document-open', 16, 'svgz')) self.ui.act_file_save.setIcon(getIcon('document-save', 16, 'svgz')) self.ui.act_file_save_as.setIcon(getIcon('document-save-as', 16, 'svgz')) self.ui.act_file_quit.setIcon(getIcon('application-exit', 16, 'svgz')) @@ -897,6 +903,70 @@ class HostWindow(QMainWindow): self.loadProjectNow() self.fProjectFilename = filenameOld + self.addToRecentFilesList(self.fProjectFilename) + + def addToRecentFilesList(self, filePath): + # FIXME: move this constant elsewhere? or add it to global settings? + MAX_RECENT_FILES = 4 + settings = QSafeSettings() + recentFileList = settings.value("RecentFileList", [], list) + + # TODO: reorder the list so last used are listed first? + if filePath not in recentFileList: + recentFileList.insert(0, filePath) + if len(recentFileList) > MAX_RECENT_FILES: + recentFileList.pop() + + settings.setValue("RecentFileList", recentFileList) + del settings + self.updateRecentFiles() + + def updateRecentFiles(self): + settings = QSafeSettings() + recentFileList = settings.value("RecentFileList", [], list) + del settings + + menu = self.ui.menu_Open_Recent + menu.clear() + + for f in recentFileList: + act = menu.addAction(f) + act.triggered.connect(self.slot_fileMenuOpenRecent) + act = menu.addSeparator() + act = menu.addAction("Clear") + act.triggered.connect(self.slot_clearRecentFiles) + + @pyqtSlot() + def slot_clearRecentFiles(self): + menu = self.ui.menu_Open_Recent + menu.clear() + settings = QSafeSettings() + settings.setValue("RecentFileList", []) + del settings + + @pyqtSlot() + def slot_fileMenuOpenRecent(self): + sender = self.sender() + filename = sender.text() + + newFile = True + + if self.fPluginCount > 0: + ask = QMessageBox.question(self, self.tr("Question"), self.tr("There are some plugins loaded, do you want to remove them now?"), + QMessageBox.Yes | QMessageBox.No, QMessageBox.No) + newFile = (ask == QMessageBox.Yes) + + if newFile: + self.pluginRemoveAll() + self.fProjectFilename = filename + self.setProperWindowTitle() + self.loadProjectNow() + else: + filenameOld = self.fProjectFilename + self.fProjectFilename = filename + self.loadProjectNow() + self.fProjectFilename = filenameOld + @pyqtSlot() def slot_fileSave(self, saveAs=False): if self.fProjectFilename and not saveAs: @@ -916,6 +986,7 @@ class HostWindow(QMainWindow): self.fProjectFilename = filename self.setProperWindowTitle() + self.addToRecentFilesList(filename) self.saveProjectNow() @pyqtSlot() @@ -1096,6 +1167,7 @@ class HostWindow(QMainWindow): if self.host.isPlugin or not self.fSessionManagerName: self.ui.act_file_open.setEnabled(True) + self.ui.menu_Open_Recent.setEnabled(True) self.ui.act_file_save_as.setEnabled(True) self.ui.cb_transport_jack.setChecked(transportMode == ENGINE_TRANSPORT_MODE_JACK) @@ -1139,6 +1211,7 @@ class HostWindow(QMainWindow): if self.host.isPlugin or not self.fSessionManagerName: self.ui.act_file_open.setEnabled(False) + self.ui.act_file_open_recent.setEnabled(False) self.ui.act_file_save_as.setEnabled(False) @pyqtSlot(int, str) From 4e9107d6a3303180c853e8f0c9be9225e595c9f7 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 3 Jan 2026 12:38:39 +0100 Subject: [PATCH 2/4] Fix carla-plugin embed usage in Qt6 Signed-off-by: falkTX --- source/frontend/qt_compat.py | 1 + 1 file changed, 1 insertion(+) diff --git a/source/frontend/qt_compat.py b/source/frontend/qt_compat.py index 3cec424a1..58de62ffe 100644 --- a/source/frontend/qt_compat.py +++ b/source/frontend/qt_compat.py @@ -167,6 +167,7 @@ elif qt_config == 6: Qt.SmoothTransformation = Qt.TransformationMode.SmoothTransformation + Qt.WA_LayoutUsesWidgetRect = Qt.WidgetAttribute.WA_LayoutUsesWidgetRect Qt.WA_OpaquePaintEvent = Qt.WidgetAttribute.WA_OpaquePaintEvent Qt.WindowModal = Qt.WindowModality.WindowModal From a3f7b7524c008ee3b05048978ff7ce0098dc6eb0 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 3 Jan 2026 12:40:47 +0100 Subject: [PATCH 3/4] Bump to macos-14 for CI Signed-off-by: falkTX --- .github/workflows/build.yml | 1 - .github/workflows/dpf.yml | 2 +- .github/workflows/release.yml | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c2c79a69b..ece601a8d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,7 +43,6 @@ jobs: strategy: matrix: include: - - target: macos-13 - target: macos-14 - target: macos-15 runs-on: ${{ matrix.target }} diff --git a/.github/workflows/dpf.yml b/.github/workflows/dpf.yml index d8b0abac2..fe5836352 100644 --- a/.github/workflows/dpf.yml +++ b/.github/workflows/dpf.yml @@ -28,7 +28,7 @@ jobs: strategy: matrix: target: [macos-intel, macos-universal, macos-universal-10.15] - runs-on: macos-13 + runs-on: macos-14 steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 918d476cd..37068dfd1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,7 +3,7 @@ name: release on: [push, pull_request] env: - CACHE_VERSION: 4 + CACHE_VERSION: 5 DEBIAN_FRONTEND: noninteractive HOMEBREW_NO_AUTO_UPDATE: 1 HOMEBREW_NO_INSTALL_CLEANUP: 1 @@ -14,7 +14,7 @@ env: jobs: # macOS native universal build macos_universal: - runs-on: macos-13 + runs-on: macos-14 steps: - uses: actions/checkout@v4 - name: Set up cache From c4096238363d77b2b516f837edba042c2280d486 Mon Sep 17 00:00:00 2001 From: Kirill Rekhov Date: Sat, 3 Jan 2026 21:03:18 +0000 Subject: [PATCH 4/4] INSTALL.md: Add Qt6 support notes and Debian install instructions --- INSTALL.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index f2f592b9e..52b57f8a4 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -27,7 +27,7 @@ $ make install PREFIX=/usr DESTDIR=./test-dir There are no required build dependencies. The default build is probably not what you want though. -If you want the frontend (which is likely), you will need PyQt5 (python3 version). +If you want the frontend (which is likely), you will need PyQt5 or PyQt6 (python3 version). You likely will also want: @@ -63,13 +63,20 @@ $ make features To find out which dependencies are missing. -Under Debian based systems, you can use this command to install everything: +Under Debian based systems, you can use this command to install everything with Qt5 packages: ``` sudo apt install python3-pyqt5.qtsvg python3-rdflib pyqt5-dev-tools \ libmagic-dev liblo-dev libasound2-dev libpulse-dev libx11-dev libxcursor-dev libxext-dev \ qtbase5-dev libfluidsynth-dev ``` +Under Debian based systems, you can alternatively install everything with Qt6 packages: +``` +sudo apt install python3-pyqt6.qtsvg python3-rdflib pyqt6-dev-tools \ + libmagic-dev liblo-dev libasound2-dev libpulse-dev libx11-dev libxcursor-dev libxext-dev \ + qt6-base-dev libfluidsynth-dev +``` + Under Fedora, you can use the following command instead: ``` sudo dnf install python3-qt5-devel python3-rdflib \