Compare commits

..

6 commits

13 changed files with 3696 additions and 101 deletions

View file

@ -131,11 +131,18 @@
export PS1="$PS1(toast-configs)> "
'';
};
overlays.default = final: prev: {
kasane-teto-cursor = final.callPackage ./pkgs/kasane-teto-cursor {};
kame-editor = final.callPackage ./pkgs/kame-editor {};
kame-tools = final.callPackage ./pkgs/kame-tools {};
rstmcpp = final.callPackage ./pkgs/rstmcpp {};
};
packages = {
x86_64-linux = with import nixpkgs-unstable-raw {system = "x86_64-linux";}; {
anything-sync-daemon = callPackage ./pkgs/anything-sync-daemon {};
discord-krisp-fixer = callPackage ./pkgs/discord-krisp-fixer {};
kasane-teto-cursor = callPackage ./pkgs/kasane-teto-cursor {};
x86_64-linux = with import nixpkgs-unstable-raw {
system = "x86_64-linux";
overlays = [self.overlays.default];
}; {
inherit kasane-teto-cursor kame-editor kame-tools rstmcpp;
};
};
nixosConfigurations = let

View file

@ -1,57 +0,0 @@
{
stdenv,
lib,
fetchFromGitHub,
makeWrapper,
rsync,
gawk,
pv,
gnutar,
zstd,
util-linux,
coreutils,
gnugrep,
findutils,
}:
stdenv.mkDerivation rec {
pname = "anything-sync-daemon";
version = "6.0.0";
src = fetchFromGitHub {
owner = "graysky2";
repo = pname;
rev = "v${version}";
hash = "sha256-6nfaAMH5YgK6gimuZ8j1zWLTDOi11KIwW7Bf0Iwh7+I=";
};
patches = [./disableDaemonStopTargets.patch];
nativeBuildInputs = [makeWrapper];
postPatch = ''
substituteInPlace init/asd* \
--replace /usr/bin/anything-sync-daemon $out/bin/anything-sync-daemon
'';
enableParallelBuilding = true;
makeFlags = [
"DESTDIR=${placeholder "out"}"
"PREFIX="
"INITDIR_SYSTEMD=/lib/systemd/system"
];
installTargets = ["install-systemd-all"];
postInstall = ''
wrapProgram $out/bin/anything-sync-daemon \
--suffix PATH : ${lib.makeBinPath [rsync gawk pv gnutar zstd util-linux coreutils gnugrep findutils]}
'';
meta = with lib; {
description = "Symlinks and syncs user specified dirs to RAM";
homepage = "https://github.com/graysky2/anything-sync-daemon/";
license = lib.licenses.mit;
platforms = platforms.linux;
};
}

View file

@ -1,23 +0,0 @@
diff --git a/Makefile b/Makefile
index ddf2d73..827ea8f 100644
--- a/Makefile
+++ b/Makefile
@@ -31,17 +31,7 @@ common/$(PN): Makefile common/$(PN).in
help: install
-stop-asd:
-ifneq ($(PREFIX), /usr)
- sudo -E asd unsync
-endif
-
-disable-systemd:
-ifeq ($(PREFIX), /usr)
- systemctl stop asd asd-resync || /bin/true
-endif
-
-install-bin: stop-asd disable-systemd common/$(PN)
+install-bin: common/$(PN)
$(Q)echo -e '\033[1;32mInstalling main script...\033[0m'
$(INSTALL_DIR) "$(DESTDIR)$(BINDIR)"
$(INSTALL_PROGRAM) common/$(PN) "$(DESTDIR)$(BINDIR)/$(PN)"

View file

@ -1,17 +0,0 @@
{ writeShellApplication
, rizin
, discord
}:
writeShellApplication rec {
name = "discord-krisp-fixer";
runtimeInputs = [ rizin ];
text = ''
discord_version="${discord.version}"
file="$HOME/.config/discord/$discord_version/modules/discord_krisp/discord_krisp.node"
addr=$(rz-find -x '4881ec00010000' "$file" | head -n1)
rizin -q -w -c "s $addr + 0x30 ; wao nop" "$file"
'';
}

View file

@ -0,0 +1,59 @@
{
lib,
stdenv,
fetchFromGitLab,
qt6,
portaudio,
kame-tools,
vgmstream,
rstmcpp,
}:
stdenv.mkDerivation rec {
name = "kame-editor";
version = "1.4.1";
src = fetchFromGitLab {
owner = "beelzy";
repo = name;
# tag = version;
rev = "82c9c445644b133b6d0ce3529e65b1a3df83c804";
hash = "sha256-V2nMvVIjFRM8++XQ9tkE2OiZzCvdrg0jK69HM+ZIVyA=";
};
postPatch = ''
substituteInPlace kame-editor.pro \
--replace-fail "/usr/local/bin/" "$out/bin"
'';
buildInputs = [
qt6.qtbase
portaudio
];
qtWrapperArgs = [
"--prefix PATH : ${
lib.makeBinPath [
kame-tools
vgmstream
rstmcpp
]
}"
];
nativeBuildInputs = [
qt6.qmake
qt6.wrapQtAppsHook
];
postBuild = ''
bash ./buildicons.sh
'';
postInstall = ''
mkdir -p $out/share/icons/hicolor
mkdir -p $out/share/applications
cp kame-editor.desktop $out/share/applications
cp -r icons/. $out/share/icons/hicolor
'';
}

View file

@ -0,0 +1,29 @@
{
stdenv,
fetchFromGitLab,
zip,
}:
stdenv.mkDerivation rec {
name = "kame-tools";
version = "a1fe47cc";
src = fetchFromGitLab {
owner = "beelzy";
repo = name;
rev = version;
fetchSubmodules = true;
hash = "sha256-ETl5f8M4OJPFB7NEq2mVuMm4RhBtAbMzlrvGHD14zXw=";
};
postPatch = ''
substituteInPlace buildtools/make_base \
--replace-fail "/usr/local/bin" "$out/bin"
'';
installPhase = ''
mkdir -p $out/bin
cp output/linux-x86_64/* $out/bin/
'';
nativeBuildInputs = [zip];
}

21
pkgs/rstmcpp/default.nix Normal file
View file

@ -0,0 +1,21 @@
{
stdenv,
fetchFromGitLab,
}:
stdenv.mkDerivation rec {
name = "rstmcpp";
version = "fe8bee01";
src = fetchFromGitLab {
owner = "beelzy";
repo = name;
rev = version;
fetchSubmodules = true;
hash = "sha256-T9mxTBj/eykvbBkbmEKTUFldtBp3cJgWAbeu44SwxiM=";
};
installPhase = ''
mkdir -p $out/bin
cp rstmcpp $out/bin
'';
}

View file

@ -101,6 +101,7 @@
services.automatic-timezoned.enable = true;
nixpkgs.overlays = [
flakeSelf.outputs.overlays.default
(
final: prev: {
catppuccin = prev.catppuccin.override {

View file

@ -0,0 +1,2 @@
Pr 462 https://invent.kde.org/plasma/spectacle/-/merge_requests/462
Pr 487 https://invent.kde.org/plasma/spectacle/-/merge_requests/487

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,704 @@
From d72a6fcb76053139ea709d7b1a4f45aa430a066d Mon Sep 17 00:00:00 2001
From: Jhair Paris <dev@jhairparis.com>
Date: Sat, 8 Nov 2025 17:32:20 -0500
Subject: [PATCH 1/4] Enhance OCR language settings management and
synchronization
- Improved signal handling in OcrLanguageSelector to prevent unnecessary updates.
- Added config sync suspension functionality in OcrManager to manage settings changes.
- Adjusted SettingsDialog to ensure proper synchronization of OCR configurations.
---
src/Gui/SettingsDialog/GeneralOptionsPage.cpp | 7 +-
src/Gui/SettingsDialog/GeneralOptionsPage.h | 4 +-
.../SettingsDialog/OcrLanguageSelector.cpp | 132 ++++++++----------
src/Gui/SettingsDialog/OcrLanguageSelector.h | 7 +-
src/Gui/SettingsDialog/SettingsDialog.cpp | 25 +++-
src/Gui/SettingsDialog/SettingsDialog.h | 1 +
src/OcrManager.cpp | 25 ++++
src/OcrManager.h | 3 +
8 files changed, 117 insertions(+), 87 deletions(-)
diff --git a/src/Gui/SettingsDialog/GeneralOptionsPage.cpp b/src/Gui/SettingsDialog/GeneralOptionsPage.cpp
index f6be13d56..ae0a997c3 100644
--- a/src/Gui/SettingsDialog/GeneralOptionsPage.cpp
+++ b/src/Gui/SettingsDialog/GeneralOptionsPage.cpp
@@ -10,7 +10,6 @@
#include "OcrLanguageSelector.h"
#include "OcrManager.h"
-#include "settings.h"
#include "ui_GeneralOptions.h"
#include <KLocalizedString>
@@ -49,7 +48,7 @@ GeneralOptionsPage::GeneralOptionsPage(QWidget *parent)
GeneralOptionsPage::~GeneralOptionsPage() = default;
-void GeneralOptionsPage::refreshOcrLanguageSettings()
+void GeneralOptionsPage::refreshOcrLanguageSettings(bool rebuildSelector)
{
OcrManager *ocrManager = OcrManager::instance();
@@ -62,7 +61,9 @@ void GeneralOptionsPage::refreshOcrLanguageSettings()
m_ui->ocrLanguageScrollArea->setVisible(true);
m_ui->ocrUnavailableWidget->setVisible(false);
- m_ocrLanguageSelector->refresh();
+ if (rebuildSelector) {
+ m_ocrLanguageSelector->refresh();
+ }
}
}
diff --git a/src/Gui/SettingsDialog/GeneralOptionsPage.h b/src/Gui/SettingsDialog/GeneralOptionsPage.h
index a3a5cb17d..bbb6d79a8 100644
--- a/src/Gui/SettingsDialog/GeneralOptionsPage.h
+++ b/src/Gui/SettingsDialog/GeneralOptionsPage.h
@@ -20,8 +20,8 @@ class GeneralOptionsPage : public QWidget
public:
explicit GeneralOptionsPage(QWidget *parent = nullptr);
~GeneralOptionsPage() override;
-
- void refreshOcrLanguageSettings();
+
+ void refreshOcrLanguageSettings(bool rebuildSelector = true);
/**
* @brief Get direct access to the OCR language selector widget
diff --git a/src/Gui/SettingsDialog/OcrLanguageSelector.cpp b/src/Gui/SettingsDialog/OcrLanguageSelector.cpp
index d1d809323..815b4c707 100644
--- a/src/Gui/SettingsDialog/OcrLanguageSelector.cpp
+++ b/src/Gui/SettingsDialog/OcrLanguageSelector.cpp
@@ -12,6 +12,7 @@
#include <KLocalizedString>
#include <QCheckBox>
+#include <QSignalBlocker>
#include <QVBoxLayout>
using namespace Qt::Literals::StringLiterals;
@@ -19,7 +20,6 @@ using namespace Qt::Literals::StringLiterals;
OcrLanguageSelector::OcrLanguageSelector(QWidget *parent)
: QWidget(parent)
, m_layout(new QVBoxLayout(this))
- , m_blockSignals(false)
, m_ocrManager(OcrManager::instance())
{
m_layout->setContentsMargins(0, 0, 0, 0);
@@ -46,15 +46,14 @@ QStringList OcrLanguageSelector::selectedLanguages() const
void OcrLanguageSelector::setSelectedLanguages(const QStringList &languages)
{
- m_blockSignals = true;
+ QSignalBlocker blocker(this);
for (QCheckBox *checkbox : m_languageCheckboxes) {
const QString langCode = checkbox->property("languageCode").toString();
+ QSignalBlocker checkboxBlocker(checkbox);
checkbox->setChecked(languages.contains(langCode));
}
- m_blockSignals = false;
-
enforceSelectionLimits();
}
@@ -67,18 +66,11 @@ bool OcrLanguageSelector::isDefault() const
return false;
}
- // Check if it's English (preferred default)
- for (const QCheckBox *checkbox : m_languageCheckboxes) {
- if (checkbox->property("languageCode").toString() == u"eng"_s) {
- // English is available, so default is English
- return current.contains(u"eng"_s);
- }
- }
+ QCheckBox *defaultCheckbox = findDefaultCheckbox();
- // English not available, default is the first available language
- if (!m_languageCheckboxes.isEmpty()) {
- QString firstLangCode = m_languageCheckboxes.first()->property("languageCode").toString();
- return current.contains(firstLangCode);
+ if (defaultCheckbox) {
+ QString defaultLangCode = defaultCheckbox->property("languageCode").toString();
+ return current.contains(defaultLangCode);
}
return false;
@@ -91,36 +83,28 @@ bool OcrLanguageSelector::hasChanges() const
void OcrLanguageSelector::applyDefaults()
{
- if (!m_languageCheckboxes.isEmpty()) {
- m_blockSignals = true;
-
- for (QCheckBox *checkbox : m_languageCheckboxes) {
- checkbox->setChecked(false);
- }
+ if (m_languageCheckboxes.isEmpty()) {
+ return;
+ }
- // Try to select English first
- bool foundDefault = false;
- for (QCheckBox *checkbox : m_languageCheckboxes) {
- if (checkbox->property("languageCode").toString() == u"eng"_s) {
- checkbox->setChecked(true);
- foundDefault = true;
- break;
- }
- }
+ QSignalBlocker blocker(this);
- // If English not available, select first language
- if (!foundDefault) {
- m_languageCheckboxes.first()->setChecked(true);
- }
+ QCheckBox *defaultCheckbox = findDefaultCheckbox();
- m_blockSignals = false;
+ for (QCheckBox *checkbox : m_languageCheckboxes) {
+ QSignalBlocker checkboxBlocker(checkbox);
+ checkbox->setChecked(checkbox == defaultCheckbox);
+ }
- const QStringList selected = selectedLanguages();
- Settings::setOcrLanguages(selected);
+ const int selectedCount = defaultCheckbox ? 1 : 0;
+ updateCheckboxEnabledStates(selectedCount);
- // Emit signal to notify changes
- Q_EMIT selectedLanguagesChanged(selected);
+ QStringList selected;
+ if (defaultCheckbox) {
+ selected.append(defaultCheckbox->property("languageCode").toString());
}
+
+ Q_EMIT selectedLanguagesChanged(selected);
}
void OcrLanguageSelector::refresh()
@@ -142,13 +126,17 @@ void OcrLanguageSelector::updateWidgets()
void OcrLanguageSelector::onLanguageCheckboxChanged()
{
- if (m_blockSignals) {
- return;
- }
-
enforceSelectionLimits();
- const QStringList selected = selectedLanguages();
+ QStringList selected;
+ selected.reserve(OcrManager::MAX_OCR_LANGUAGES);
+
+ for (QCheckBox *checkbox : m_languageCheckboxes) {
+ if (checkbox->isChecked()) {
+ selected.append(checkbox->property("languageCode").toString());
+ }
+ }
+
Q_EMIT selectedLanguagesChanged(selected);
}
@@ -167,21 +155,20 @@ void OcrLanguageSelector::setupLanguageCheckboxes()
}
m_languageCheckboxes.clear();
- m_availableLanguages.clear();
if (!m_ocrManager || !m_ocrManager->isAvailable()) {
qCWarning(SPECTACLE_LOG) << "OCR is not available; language selector will remain empty.";
return;
}
- m_availableLanguages = m_ocrManager->availableLanguagesWithNames();
+ const QMap<QString, QString> availableLanguages = m_ocrManager->availableLanguagesWithNames();
- if (m_availableLanguages.isEmpty()) {
+ if (availableLanguages.isEmpty()) {
qCWarning(SPECTACLE_LOG) << "No OCR language data available.";
return;
}
- for (auto it = m_availableLanguages.cbegin(); it != m_availableLanguages.cend(); ++it) {
+ for (auto it = availableLanguages.cbegin(); it != availableLanguages.cend(); ++it) {
const QString &langCode = it.key();
if (langCode == u"osd"_s) {
continue;
@@ -208,64 +195,57 @@ void OcrLanguageSelector::setupLanguageCheckboxes()
void OcrLanguageSelector::enforceSelectionLimits()
{
- const QStringList selected = selectedLanguages();
- const int count = selected.size();
+ int selectedCount = 0;
+
+ for (QCheckBox *checkbox : m_languageCheckboxes) {
+ if (checkbox->isChecked()) {
+ ++selectedCount;
+ }
+ }
- if (count > OcrManager::MAX_OCR_LANGUAGES) { // Max languages for performance
+ if (selectedCount > OcrManager::MAX_OCR_LANGUAGES) {
for (int i = m_languageCheckboxes.size() - 1; i >= 0; --i) {
QCheckBox *checkbox = m_languageCheckboxes[i];
if (checkbox->isChecked()) {
- blockSignalsAndSetChecked(checkbox, false);
+ QSignalBlocker blocker(checkbox);
+ checkbox->setChecked(false);
+ --selectedCount;
break;
}
}
}
- updateCheckboxEnabledStates();
+ updateCheckboxEnabledStates(selectedCount);
- if (selectedLanguages().size() == 0 && !m_languageCheckboxes.isEmpty()) {
+ if (selectedCount == 0 && !m_languageCheckboxes.isEmpty()) {
applyDefaults();
}
}
-QString OcrLanguageSelector::getDefaultLanguageCode() const
+QCheckBox *OcrLanguageSelector::findDefaultCheckbox() const
{
if (m_languageCheckboxes.isEmpty()) {
- return QString();
+ return nullptr;
}
// Try English first
- for (const QCheckBox *checkbox : m_languageCheckboxes) {
+ for (QCheckBox *checkbox : m_languageCheckboxes) {
if (checkbox->property("languageCode").toString() == u"eng"_s) {
- return u"eng"_s;
+ return checkbox;
}
}
// Fallback to first available
- return m_languageCheckboxes.first()->property("languageCode").toString();
+ return m_languageCheckboxes.first();
}
-void OcrLanguageSelector::updateCheckboxEnabledStates()
+void OcrLanguageSelector::updateCheckboxEnabledStates(int selectedCount)
{
- const QStringList selected = selectedLanguages();
- const int count = selected.size();
+ const bool enableUnchecked = selectedCount < OcrManager::MAX_OCR_LANGUAGES;
- // If we have max languages selected, disable all unchecked checkboxes
- // If we have less than max, enable all checkboxes
for (QCheckBox *checkbox : m_languageCheckboxes) {
- if (checkbox->isChecked()) {
- checkbox->setEnabled(true);
- } else {
- checkbox->setEnabled(count < OcrManager::MAX_OCR_LANGUAGES);
- }
+ checkbox->setEnabled(checkbox->isChecked() || enableUnchecked);
}
}
-void OcrLanguageSelector::blockSignalsAndSetChecked(QCheckBox *checkbox, bool checked)
-{
- m_blockSignals = true;
- checkbox->setChecked(checked);
- m_blockSignals = false;
-}
-
#include "moc_OcrLanguageSelector.cpp"
\ No newline at end of file
diff --git a/src/Gui/SettingsDialog/OcrLanguageSelector.h b/src/Gui/SettingsDialog/OcrLanguageSelector.h
index 59b1a3d42..e938e06fa 100644
--- a/src/Gui/SettingsDialog/OcrLanguageSelector.h
+++ b/src/Gui/SettingsDialog/OcrLanguageSelector.h
@@ -96,14 +96,11 @@ private Q_SLOTS:
private:
void setupLanguageCheckboxes();
void enforceSelectionLimits();
- void updateCheckboxEnabledStates();
- QString getDefaultLanguageCode() const;
- void blockSignalsAndSetChecked(QCheckBox *checkbox, bool checked);
+ void updateCheckboxEnabledStates(int selectedCount);
+ QCheckBox *findDefaultCheckbox() const;
QVBoxLayout *m_layout;
QList<QCheckBox *> m_languageCheckboxes;
- QMap<QString, QString> m_availableLanguages; // code -> display name
- bool m_blockSignals;
OcrManager *m_ocrManager;
};
diff --git a/src/Gui/SettingsDialog/SettingsDialog.cpp b/src/Gui/SettingsDialog/SettingsDialog.cpp
index 532bfd3c3..696636685 100644
--- a/src/Gui/SettingsDialog/SettingsDialog.cpp
+++ b/src/Gui/SettingsDialog/SettingsDialog.cpp
@@ -11,6 +11,7 @@
#include "GeneralOptionsPage.h"
#include "ImageSaveOptionsPage.h"
#include "OcrLanguageSelector.h"
+#include "OcrManager.h"
#include "ShortcutsOptionsPage.h"
#include "VideoSaveOptionsPage.h"
#include "settings.h"
@@ -46,6 +47,16 @@ SettingsDialog::SettingsDialog(QWidget *parent)
connect(this, &KConfigDialog::currentPageChanged, this, &SettingsDialog::updateButtons);
}
+SettingsDialog::~SettingsDialog()
+{
+ // Ensure OCR config sync is resumed
+ if (OcrManager *ocrManager = OcrManager::instance()) {
+ if (ocrManager->isConfigSyncSuspended()) {
+ ocrManager->setConfigSyncSuspended(false);
+ }
+ }
+}
+
QSize SettingsDialog::sizeHint() const
{
// Avoid having pages that need to be scrolled,
@@ -91,6 +102,10 @@ void SettingsDialog::updateSettings()
m_shortcutsPage->saveChanges();
m_generalPage->ocrLanguageSelector()->saveSettings();
+
+ if (OcrManager *ocrManager = OcrManager::instance()) {
+ ocrManager->setConfigSyncSuspended(false);
+ }
}
void SettingsDialog::updateWidgets()
@@ -100,15 +115,23 @@ void SettingsDialog::updateWidgets()
m_generalPage->ocrLanguageSelector()->updateWidgets();
m_generalPage->refreshOcrLanguageSettings();
+
+ if (OcrManager *ocrManager = OcrManager::instance()) {
+ ocrManager->setConfigSyncSuspended(false);
+ }
}
void SettingsDialog::updateWidgetsDefault()
{
+ if (OcrManager *ocrManager = OcrManager::instance()) {
+ ocrManager->setConfigSyncSuspended(true);
+ }
+
KConfigDialog::updateWidgetsDefault();
m_shortcutsPage->defaults();
m_generalPage->ocrLanguageSelector()->applyDefaults();
- m_generalPage->refreshOcrLanguageSettings();
+ m_generalPage->refreshOcrLanguageSettings(false);
}
#include "moc_SettingsDialog.cpp"
diff --git a/src/Gui/SettingsDialog/SettingsDialog.h b/src/Gui/SettingsDialog/SettingsDialog.h
index 50f6d85bf..64281dd09 100644
--- a/src/Gui/SettingsDialog/SettingsDialog.h
+++ b/src/Gui/SettingsDialog/SettingsDialog.h
@@ -20,6 +20,7 @@ class SettingsDialog : public KConfigDialog
public:
explicit SettingsDialog(QWidget *parent = nullptr);
+ ~SettingsDialog() override;
protected:
QSize sizeHint() const override;
diff --git a/src/OcrManager.cpp b/src/OcrManager.cpp
index 1d09db8ef..56d467993 100644
--- a/src/OcrManager.cpp
+++ b/src/OcrManager.cpp
@@ -56,6 +56,9 @@ OcrManager::OcrManager(QObject *parent)
m_workerThread->start();
connect(Settings::self(), &Settings::ocrLanguagesChanged, this, [this]() {
+ if (m_configSyncSuspended) {
+ return;
+ }
const QStringList newLanguages = Settings::ocrLanguages();
const QString combinedLanguages = newLanguages.join(u"+"_s);
if (combinedLanguages != m_currentLanguageCode) {
@@ -150,6 +153,28 @@ QString OcrManager::currentLanguageCode() const
return m_currentLanguageCode;
}
+void OcrManager::setConfigSyncSuspended(bool suspended)
+{
+ if (m_configSyncSuspended == suspended) {
+ return;
+ }
+
+ m_configSyncSuspended = suspended;
+
+ // On resume, apply any changes made to Settings
+ if (!m_configSyncSuspended) {
+ const QStringList settingsLanguages = Settings::ocrLanguages();
+ if (settingsLanguages != m_configuredLanguages) {
+ setLanguagesByCode(settingsLanguages);
+ }
+ }
+}
+
+bool OcrManager::isConfigSyncSuspended() const
+{
+ return m_configSyncSuspended;
+}
+
void OcrManager::recognizeText(const QImage &image)
{
#ifdef HAVE_TESSERACT_OCR
diff --git a/src/OcrManager.h b/src/OcrManager.h
index c71505b3e..37f490600 100644
--- a/src/OcrManager.h
+++ b/src/OcrManager.h
@@ -98,6 +98,8 @@ public:
* @return Current language code (e.g., "eng", "spa")
*/
QString currentLanguageCode() const;
+ void setConfigSyncSuspended(bool suspended);
+ bool isConfigSyncSuspended() const;
public Q_SLOTS:
/**
@@ -169,6 +171,7 @@ private:
bool m_shouldRestoreToConfigured;
QStringList m_availableLanguages;
QMap<QString, QString> m_languageNames;
+ bool m_configSyncSuspended = false;
bool m_initialized;
private:
--
GitLab
From 642600410714c783515f2416a9be08ef3406b0d9 Mon Sep 17 00:00:00 2001
From: Jhair Paris <dev@jhairparis.com>
Date: Sat, 8 Nov 2025 21:30:41 -0500
Subject: [PATCH 2/4] Fix flickering in settings dialog during OCR
initialization
---
src/Gui/SettingsDialog/GeneralOptionsPage.cpp | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/Gui/SettingsDialog/GeneralOptionsPage.cpp b/src/Gui/SettingsDialog/GeneralOptionsPage.cpp
index ae0a997c3..adfc045e6 100644
--- a/src/Gui/SettingsDialog/GeneralOptionsPage.cpp
+++ b/src/Gui/SettingsDialog/GeneralOptionsPage.cpp
@@ -38,7 +38,7 @@ GeneralOptionsPage::GeneralOptionsPage(QWidget *parent)
connect(m_ocrLanguageSelector, &OcrLanguageSelector::selectedLanguagesChanged, this, &GeneralOptionsPage::ocrLanguageChanged);
- refreshOcrLanguageSettings();
+ refreshOcrLanguageSettings(false);
//On Wayland we can't programmatically raise and focus the window so we have to hide the option
if (KWindowSystem::isPlatformWayland() || qstrcmp(qgetenv("XDG_SESSION_TYPE").constData(), "wayland") == 0) {
@@ -51,8 +51,9 @@ GeneralOptionsPage::~GeneralOptionsPage() = default;
void GeneralOptionsPage::refreshOcrLanguageSettings(bool rebuildSelector)
{
OcrManager *ocrManager = OcrManager::instance();
-
- if (!ocrManager->isAvailable()) {
+ const bool ocrAvailable = ocrManager->isAvailable();
+
+ if (!ocrAvailable) {
m_ui->ocrLanguageLabel->setVisible(false);
m_ui->ocrLanguageScrollArea->setVisible(false);
m_ui->ocrUnavailableWidget->setVisible(true);
@@ -60,10 +61,10 @@ void GeneralOptionsPage::refreshOcrLanguageSettings(bool rebuildSelector)
m_ui->ocrLanguageLabel->setVisible(true);
m_ui->ocrLanguageScrollArea->setVisible(true);
m_ui->ocrUnavailableWidget->setVisible(false);
+ }
- if (rebuildSelector) {
- m_ocrLanguageSelector->refresh();
- }
+ if (ocrAvailable && rebuildSelector) {
+ m_ocrLanguageSelector->refresh();
}
}
--
GitLab
From 6c6d95f3fd87ff70f8c1d25786a5a7f047e9d74f Mon Sep 17 00:00:00 2001
From: Jhair Paris <dev@jhairparis.com>
Date: Sat, 8 Nov 2025 21:51:05 -0500
Subject: [PATCH 3/4] Improve OCR language handling in settings dialog
---
src/Gui/SettingsDialog/SettingsDialog.cpp | 24 ++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/src/Gui/SettingsDialog/SettingsDialog.cpp b/src/Gui/SettingsDialog/SettingsDialog.cpp
index 696636685..0bfab8bb9 100644
--- a/src/Gui/SettingsDialog/SettingsDialog.cpp
+++ b/src/Gui/SettingsDialog/SettingsDialog.cpp
@@ -88,12 +88,20 @@ void SettingsDialog::showEvent(QShowEvent *event)
bool SettingsDialog::hasChanged()
{
- return m_shortcutsPage->isModified() || m_generalPage->ocrLanguageSelector()->hasChanges() || KConfigDialog::hasChanged();
+ bool ocrHasChanges = false;
+ if (OcrManager::instance()->isAvailable()) {
+ ocrHasChanges = m_generalPage->ocrLanguageSelector()->hasChanges();
+ }
+ return m_shortcutsPage->isModified() || ocrHasChanges || KConfigDialog::hasChanged();
}
bool SettingsDialog::isDefault()
{
- return currentPage()->name() != i18n("Shortcuts") && m_generalPage->ocrLanguageSelector()->isDefault() && KConfigDialog::isDefault();
+ bool ocrIsDefault = true;
+ if (OcrManager::instance()->isAvailable()) {
+ ocrIsDefault = m_generalPage->ocrLanguageSelector()->isDefault();
+ }
+ return currentPage()->name() != i18n("Shortcuts") && ocrIsDefault && KConfigDialog::isDefault();
}
void SettingsDialog::updateSettings()
@@ -101,7 +109,9 @@ void SettingsDialog::updateSettings()
KConfigDialog::updateSettings();
m_shortcutsPage->saveChanges();
- m_generalPage->ocrLanguageSelector()->saveSettings();
+ if (OcrManager::instance()->isAvailable()) {
+ m_generalPage->ocrLanguageSelector()->saveSettings();
+ }
if (OcrManager *ocrManager = OcrManager::instance()) {
ocrManager->setConfigSyncSuspended(false);
@@ -113,7 +123,9 @@ void SettingsDialog::updateWidgets()
KConfigDialog::updateWidgets();
m_shortcutsPage->resetChanges();
- m_generalPage->ocrLanguageSelector()->updateWidgets();
+ if (OcrManager::instance()->isAvailable()) {
+ m_generalPage->ocrLanguageSelector()->updateWidgets();
+ }
m_generalPage->refreshOcrLanguageSettings();
if (OcrManager *ocrManager = OcrManager::instance()) {
@@ -130,7 +142,9 @@ void SettingsDialog::updateWidgetsDefault()
KConfigDialog::updateWidgetsDefault();
m_shortcutsPage->defaults();
- m_generalPage->ocrLanguageSelector()->applyDefaults();
+ if (OcrManager::instance()->isAvailable()) {
+ m_generalPage->ocrLanguageSelector()->applyDefaults();
+ }
m_generalPage->refreshOcrLanguageSettings(false);
}
--
GitLab
From 174b4a4a10e2c42fa28eb361cd4b6a833af60dc7 Mon Sep 17 00:00:00 2001
From: Jhair Paris <dev@jhairparis.com>
Date: Mon, 10 Nov 2025 22:10:51 -0500
Subject: [PATCH 4/4] Remove Tesseract language pack validation test and
simplify OCR support check
---
CMakeLists.txt | 24 ++----------------------
cmake/tesseract_test.cpp | 40 ----------------------------------------
2 files changed, 2 insertions(+), 62 deletions(-)
delete mode 100644 cmake/tesseract_test.cpp
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ea44e71d4..2adf8a9ac 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -96,28 +96,8 @@ if(PkgConfig_FOUND)
pkg_check_modules(TESSERACT tesseract)
if(TESSERACT_FOUND)
- # Test if Tesseract has usable language packs
- try_run(
- TESSERACT_TEST_RUN_RESULT
- TESSERACT_TEST_COMPILE_RESULT
- ${CMAKE_CURRENT_BINARY_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}/cmake/tesseract_test.cpp
- LINK_LIBRARIES ${TESSERACT_LIBRARIES}
- CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${TESSERACT_INCLUDE_DIRS}"
- COMPILE_OUTPUT_VARIABLE TESSERACT_COMPILE_OUTPUT
- RUN_OUTPUT_VARIABLE TESSERACT_RUN_OUTPUT
- )
-
- if(TESSERACT_TEST_COMPILE_RESULT AND TESSERACT_TEST_RUN_RESULT EQUAL 0)
- message(STATUS "Tesseract OCR support enabled")
- message(STATUS "${TESSERACT_RUN_OUTPUT}")
- set(HAVE_TESSERACT_OCR TRUE)
- else()
- message(WARNING "Tesseract library found but no usable language packs detected")
- message(WARNING "${TESSERACT_RUN_OUTPUT}")
- message(WARNING "OCR functionality will be disabled. Install language data packages (e.g., tesseract-ocr-eng)")
- set(HAVE_TESSERACT_OCR FALSE)
- endif()
+ message(STATUS "Tesseract OCR support enabled")
+ set(HAVE_TESSERACT_OCR TRUE)
else()
message(STATUS "Tesseract not found - OCR functionality disabled")
set(HAVE_TESSERACT_OCR FALSE)
diff --git a/cmake/tesseract_test.cpp b/cmake/tesseract_test.cpp
deleted file mode 100644
index 4ebae9779..000000000
--- a/cmake/tesseract_test.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#include <iostream>
-#include <string>
-#include <tesseract/baseapi.h>
-#include <vector>
-
-int main()
-{
- tesseract::TessBaseAPI api;
-
- if (api.Init(nullptr, nullptr) != 0) {
- std::cerr << "Failed to initialize Tesseract" << std::endl;
- return 1;
- }
-
- std::vector<std::string> languages;
- api.GetAvailableLanguagesAsVector(&languages);
-
- // Filter out 'osd' as it's not a usable language for OCR
- std::vector<std::string> usableLanguages;
- for (const auto &lang : languages) {
- if (lang != "osd") {
- usableLanguages.push_back(lang);
- }
- }
-
- if (usableLanguages.empty()) {
- std::cerr << "No usable Tesseract language packs found. Install language data files (e.g., tesseract-ocr-eng)" << std::endl;
- return 1;
- }
-
- std::cout << "Found " << usableLanguages.size() << " Tesseract language pack(s): ";
- for (size_t i = 0; i < usableLanguages.size(); ++i) {
- std::cout << usableLanguages[i];
- if (i < usableLanguages.size() - 1)
- std::cout << ", ";
- }
- std::cout << std::endl;
-
- return 0;
-}
--
GitLab

View file

@ -8,6 +8,7 @@
./konsole.nix
./kwin.nix
./baloo.nix
./spectacle.nix
];
# Enable the kde partition manager

View file

@ -0,0 +1,24 @@
{...}: {
nixpkgs.overlays = [
(
final: prev: {
kdePackages = prev.kdePackages.overrideScope (
kFinal: kPrev: {
# Needed for OCR
spectacle = kPrev.spectacle.overrideAttrs (old: {
nativeBuildInputs = old.nativeBuildInputs ++ [final.pkg-config];
buildInputs = with final;
old.buildInputs
++ [
tesseract
leptonica
libarchive
curl
];
});
}
);
}
)
];
}