From ff85315fef748df8afe0b548b01ba7c5147d719f Mon Sep 17 00:00:00 2001 From: Christian Halaszovich Date: Mon, 4 May 2026 18:37:09 +0200 Subject: [PATCH 1/7] data file support in introduction: add unbundled Updated introduction to clarify file types supported: unbundled as well --- doc/introduction.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/introduction.rst b/doc/introduction.rst index 0269126..44c3999 100644 --- a/doc/introduction.rst +++ b/doc/introduction.rst @@ -3,7 +3,7 @@ What can :program:`PMbrowser` do for you? ----------------------------------------- -It can open bundled data files (:file:`.dat`) created by :program:`PATCHMASTER` or +It can open data (bundled and unbundled) files (:file:`.dat`) created by :program:`PATCHMASTER` or :program:`PATCHMASTER NEXT`. It has been tested with files created by versions of :program:`PATCHMASTER` @@ -50,4 +50,4 @@ You can use it freely. The source code can be found `here Date: Mon, 4 May 2026 18:39:27 +0200 Subject: [PATCH 2/7] Bump project version to 2.5.1 and update copyright and decrp Updated project version and release details. --- CMakeLists.txt | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4eb37ef..14c169d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,10 @@ cmake_minimum_required(VERSION 3.25) set(CMAKE_OSX_DEPLOYMENT_TARGET "13.3" CACHE STRING "needs at least 13.3") -project(QtPMbrowser VERSION 2.5.0 LANGUAGES CXX) -set(MY_RELEASE_DAY "2026-03-13") -set(MY_COPYRIGHT "2020 - 2025 Christian R. Halaszovich") +project(QtPMbrowser VERSION 2.5.1 LANGUAGES CXX) +set(MY_RELEASE_DAY "2026-05-4") +set(MY_COPYRIGHT "2020 - 2026 Christian R. Halaszovich") set(LINUX_RELEASE_DESCRIPTION " -

improved feature: show stimulus protocols in table view

-

improved feature: 'Select Parameters Dialog' allows selecting / de-selecting all options of a section

-

improved feature: show amplifier state in table view

-

bugfix: handle unicode in filenames (for loading and exporting)

+

new feature: support unbundled PM files

") set(CMAKE_CXX_STANDARD 20) From 9cc5eb46ba4a3aa7a48c1b0772eb6529d0bbdbf2 Mon Sep 17 00:00:00 2001 From: Christian Halaszovich Date: Mon, 4 May 2026 18:49:07 +0200 Subject: [PATCH 3/7] Update documentation for PMbrowser formats - export formats Clarify the export formats supported by PMbrowser. --- doc/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index 7571b4c..94cb055 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -15,8 +15,8 @@ Welcome to PMbrowser's documentation! :program:`PMbrowser` is open-source software aimed at electrophysiologists who use :program:`PATCHMASTER` or :program:`PATCHMASTER NEXT` from `HEKA `_ and -:program:`IgorPro` of `WaveMetrics `_. It can open bundled data files (:file:`.dat`) and -export :program:`IgorPro` compatible files (and supports some additional export formats, +:program:`IgorPro` of `WaveMetrics `_. It can open data files (:file:`.dat`) and +export :program:`IgorPro` compatible files (and supports some additional export formats, e.g. :program:`numpy`, see :ref:`intro-label` for details). But even if you do not use :program:`IgorPro`, you might find :program:`PMbrowser` useful for browsing PatchMaster files From f8d3c2e11d2216a810db016aa2b063b7cd42aca9 Mon Sep 17 00:00:00 2001 From: ChrisHal Date: Tue, 5 May 2026 08:59:52 +0200 Subject: [PATCH 4/7] Update copyright year to 2026 in multiple source files --- QtPMbrowser/pmbrowserwindow.cpp | 2 +- QtPMbrowser/pmbrowserwindow.h | 2 +- hekatoolslib/DatFile.h | 2 +- hekatoolslib/hkTree.cpp | 2 +- hekatoolslib/hkTree.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/QtPMbrowser/pmbrowserwindow.cpp b/QtPMbrowser/pmbrowserwindow.cpp index 04f3fde..592ea15 100644 --- a/QtPMbrowser/pmbrowserwindow.cpp +++ b/QtPMbrowser/pmbrowserwindow.cpp @@ -1,5 +1,5 @@ /* - Copyright 2020 - 2025 Christian R. Halaszovich + Copyright 2020 - 2026 Christian R. Halaszovich This file is part of PMbrowser. diff --git a/QtPMbrowser/pmbrowserwindow.h b/QtPMbrowser/pmbrowserwindow.h index 7b2ad70..0198286 100644 --- a/QtPMbrowser/pmbrowserwindow.h +++ b/QtPMbrowser/pmbrowserwindow.h @@ -1,5 +1,5 @@ /* - Copyright 2020 - 2023 Christian R. Halaszovich + Copyright 2020 - 2026 Christian R. Halaszovich This file is part of PMbrowser. diff --git a/hekatoolslib/DatFile.h b/hekatoolslib/DatFile.h index 62c34cd..d0f34cc 100644 --- a/hekatoolslib/DatFile.h +++ b/hekatoolslib/DatFile.h @@ -3,7 +3,7 @@ */ /* - Copyright 2020 - 2023 Christian R. Halaszovich + Copyright 2020 - 2026 Christian R. Halaszovich This file is part of PMbrowser. diff --git a/hekatoolslib/hkTree.cpp b/hekatoolslib/hkTree.cpp index cd1eb47..13b0589 100644 --- a/hekatoolslib/hkTree.cpp +++ b/hekatoolslib/hkTree.cpp @@ -1,5 +1,5 @@ /* - Copyright 2020 - 2022 Christian R. Halaszovich + Copyright 2020 - 2026 Christian R. Halaszovich This file is part of PMbrowser. diff --git a/hekatoolslib/hkTree.h b/hekatoolslib/hkTree.h index bad24cc..fba8d45 100644 --- a/hekatoolslib/hkTree.h +++ b/hekatoolslib/hkTree.h @@ -1,5 +1,5 @@ /* - Copyright 2020 - 2022 Christian R. Halaszovich + Copyright 2020 - 2026 Christian R. Halaszovich This file is part of PMbrowser. From 4fecc797e170468d2106bbbe83e4f0ae532f4d71 Mon Sep 17 00:00:00 2001 From: ChrisHal Date: Tue, 5 May 2026 09:42:06 +0200 Subject: [PATCH 5/7] Improve error handling for DatFile loading and introduce custom fileformat_error exception --- QtPMbrowser/pmbrowserwindow.cpp | 17 ++++++++++++----- hekatoolslib/DatFile.cpp | 4 ++-- hekatoolslib/DatFile.h | 6 ++++++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/QtPMbrowser/pmbrowserwindow.cpp b/QtPMbrowser/pmbrowserwindow.cpp index 592ea15..49d2982 100644 --- a/QtPMbrowser/pmbrowserwindow.cpp +++ b/QtPMbrowser/pmbrowserwindow.cpp @@ -303,18 +303,25 @@ void PMbrowserWindow::loadFile(QString filename) QSettings settings; settings.setValue("pmbrowserwindow/lastloadpath", lastloadpath); datfile = std::make_unique(); + bool do_retry = false; try { datfile->InitFromStream(infile); } + catch (const hkLib::fileformat_error& e) { + datfile = nullptr; + infile.seekg(0, std::ios_base::beg); + qDebug() << e.what(); + do_retry = true; + } catch (const std::exception& e) { - //QMessageBox::warning(this, QString("File Error"), - // QString("error while processing dat file:\n") + QString(e.what())); + QMessageBox::warning(this, QString("File Error"), + QString("error while processing dat file:\n") + QString(e.what())); qDebug() << e.what(); datfile = nullptr; - infile.seekg(0, std::ios_base::beg); - //infile.close(); + //infile.seekg(0, std::ios_base::beg); + infile.close(); } - if (!datfile) { + if (do_retry && !datfile) { try { // we might habe an unbundled dat file datfile = std::make_unique(); diff --git a/hekatoolslib/DatFile.cpp b/hekatoolslib/DatFile.cpp index f389f78..258a725 100644 --- a/hekatoolslib/DatFile.cpp +++ b/hekatoolslib/DatFile.cpp @@ -49,10 +49,10 @@ void DatFile::InitFromStream(std::istream& infile) if (!isValid) { bool isInvalidBundle = std::memcmp(bh->Signature, BundleSignatureInvalid, 8) == 0; if (isInvalidBundle) { - throw std::runtime_error("invalid bundle signature"); + throw fileformat_error("invalid bundle signature"); } else { - throw std::runtime_error("invalid file (not a PM dat file)"); + throw fileformat_error("invalid file (not a PM dat file)"); } } diff --git a/hekatoolslib/DatFile.h b/hekatoolslib/DatFile.h index d0f34cc..a35eaf9 100644 --- a/hekatoolslib/DatFile.h +++ b/hekatoolslib/DatFile.h @@ -33,11 +33,17 @@ #include #include #include +#include #include "machineinfo.h" #include "hkTree.h" #include "helpers.h" namespace hkLib { + /// @brief thrown if file is not a bundled dat file + class fileformat_error : public std::runtime_error { + public: + fileformat_error(const std::string& msg) : std::runtime_error(msg) {} + }; /// /// each BundleItem describes offset and length of From dafa01ee55915375bc2cde32dd3ded866390877a Mon Sep 17 00:00:00 2001 From: ChrisHal Date: Tue, 5 May 2026 09:58:04 +0200 Subject: [PATCH 6/7] Refactor renderTrace method to return a boolean indicating success or failure --- QtPMbrowser/pmbrowserwindow.cpp | 4 +++- QtPMbrowser/renderarea.cpp | 7 ++++--- QtPMbrowser/renderarea.h | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/QtPMbrowser/pmbrowserwindow.cpp b/QtPMbrowser/pmbrowserwindow.cpp index 49d2982..7cff4b5 100644 --- a/QtPMbrowser/pmbrowserwindow.cpp +++ b/QtPMbrowser/pmbrowserwindow.cpp @@ -172,7 +172,9 @@ void PMbrowserWindow::animateTraceList(const QString& info_text, const std::vect if (progress.wasCanceled()) { break; } - ui->renderArea->renderTrace(trace_list.at(i), infile); + if(!ui->renderArea->renderTrace(trace_list.at(i), infile)) { + break; + } ui->renderArea->repaint(); #ifdef __APPLE__ // unfortunately, on macOS Qt doesn't support QWdiget::repaint diff --git a/QtPMbrowser/renderarea.cpp b/QtPMbrowser/renderarea.cpp index f6e6dc3..0532629 100644 --- a/QtPMbrowser/renderarea.cpp +++ b/QtPMbrowser/renderarea.cpp @@ -713,7 +713,7 @@ void RenderArea::zoomIn(double x_center, double y_center, double factor) update(); } -void RenderArea::renderTrace(const hkLib::hkTreeNode* TrRecord, std::istream& infile) +bool RenderArea::renderTrace(const hkLib::hkTreeNode* TrRecord, std::istream& infile) { using namespace hkLib; char dataformat = TrRecord->getChar(TrDataFormat); @@ -736,7 +736,7 @@ void RenderArea::renderTrace(const hkLib::hkTreeNode* TrRecord, std::istream& in } else { QMessageBox::warning(this, QString("Data Format Error"), QString("Unknown Dataformat")); - return; + return false; } addTrace(DisplayTrace( @@ -751,12 +751,13 @@ void RenderArea::renderTrace(const hkLib::hkTreeNode* TrRecord, std::istream& in catch (const std::exception& e) { // newYtrace.data.clear(); QMessageBox::warning(nullptr, "File Error", e.what()); - return; + return false; } if (do_autoscale_on_load) { autoScale(); } else { update(); } // update is usually done within autoScale() setMouseTracking(true); + return true; // success } void RenderArea::addTrace(DisplayTrace&& dt) diff --git a/QtPMbrowser/renderarea.h b/QtPMbrowser/renderarea.h index 68c5032..279643d 100644 --- a/QtPMbrowser/renderarea.h +++ b/QtPMbrowser/renderarea.h @@ -48,7 +48,7 @@ class RenderArea : public QWidget explicit RenderArea(QWidget *parent = nullptr); ~RenderArea(); bool noData() { return !yTrace.isValid(); }; - void renderTrace(const hkLib::hkTreeNode* trace, std::istream& infile); + bool renderTrace(const hkLib::hkTreeNode* trace, std::istream& infile); void addTrace(DisplayTrace&& dt); /// From 09f4ea208fe7238e6cb79ba3356ee0d998aff013 Mon Sep 17 00:00:00 2001 From: ChrisHal Date: Mon, 1 Jun 2026 11:20:56 +0200 Subject: [PATCH 7/7] linux deploy: in desktop file use %f not %u since only file, not url supported --- QtPMbrowser/linux_deploy/de.halaszovich.pmbrowser.desktop.in | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/QtPMbrowser/linux_deploy/de.halaszovich.pmbrowser.desktop.in b/QtPMbrowser/linux_deploy/de.halaszovich.pmbrowser.desktop.in index 26cbe24..0da8bad 100644 --- a/QtPMbrowser/linux_deploy/de.halaszovich.pmbrowser.desktop.in +++ b/QtPMbrowser/linux_deploy/de.halaszovich.pmbrowser.desktop.in @@ -5,6 +5,5 @@ Name=PM browser Comment=Browse PM dat files Terminal=false Categories=Science -Exec=QtPMbrowser %u -#MimeType=application/octet-stream +Exec=QtPMbrowser %f Icon=${MY_APP_ID}