Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ option(MUE_COMPILE_USE_SYSTEM_FREETYPE "Try use system freetype" OFF)
option(MUE_COMPILE_USE_SYSTEM_HARFBUZZ "Try use system harfbuzz" OFF)
option(MUE_COMPILE_USE_SYSTEM_OPUS "Try use system opus" OFF)
option(MUE_COMPILE_USE_SYSTEM_OPUSENC "Try use system libopusenc" OFF)
option(MUE_COMPILE_USE_SYSTEM_HUNSPELL "Use system hunspell for spellchecking" ON)

# === Debug ===
option(MUE_ENABLE_LOAD_QML_FROM_SOURCE "Load qml files from source (not resource)" OFF)
Expand Down
1 change: 1 addition & 0 deletions src/appshell/view/appmenumodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ MenuItem* AppMenuModel::makeToolsMenu()
*/
makeSeparator(),
makeMenuItem("copy-lyrics-to-clipboard"),
makeMenuItem("check-lyrics-spelling"),
makeMenuItem("del-empty-measures"),
};

Expand Down
21 changes: 21 additions & 0 deletions src/notation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ set(MODULE_QML_IMPORT ${CMAKE_CURRENT_LIST_DIR}/qml)
include(${CMAKE_CURRENT_LIST_DIR}/view/widgets/widgets.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/view/styledialog/styledialog.cmake)

# Hunspell spellcheck support
include(${CMAKE_CURRENT_LIST_DIR}/cmake/SetupHunspell.cmake)
if (HUNSPELL_FOUND)
set(MODULE_DEF ${MODULE_DEF} -DMUE_BUILD_NOTATION_HUNSPELL)
set(MODULE_INCLUDE ${MODULE_INCLUDE} ${HUNSPELL_INCLUDE_DIRS})
endif()

if (MUE_BUILD_ENGRAVING_PLAYBACK)
set(NOTATION_PLAYBACK_SRC_FILES
${CMAKE_CURRENT_LIST_DIR}/internal/notationplayback.cpp
Expand Down Expand Up @@ -64,6 +71,8 @@ set(MODULE_SRC
${CMAKE_CURRENT_LIST_DIR}/inotationparts.h
${CMAKE_CURRENT_LIST_DIR}/iinstrumentsrepository.h
${CMAKE_CURRENT_LIST_DIR}/iselectinstrumentscenario.h
${CMAKE_CURRENT_LIST_DIR}/ispellchecker.h
${CMAKE_CURRENT_LIST_DIR}/ilyricsspellcheckservice.h

${CMAKE_CURRENT_LIST_DIR}/internal/notationuiactions.cpp
${CMAKE_CURRENT_LIST_DIR}/internal/notationuiactions.h
Expand Down Expand Up @@ -123,6 +132,11 @@ set(MODULE_SRC
${CMAKE_CURRENT_LIST_DIR}/internal/instrumentsrepository.h
${CMAKE_CURRENT_LIST_DIR}/internal/mscoreerrorscontroller.cpp
${CMAKE_CURRENT_LIST_DIR}/internal/mscoreerrorscontroller.h
${CMAKE_CURRENT_LIST_DIR}/internal/hunspellspellchecker.cpp
${CMAKE_CURRENT_LIST_DIR}/internal/hunspellspellchecker.h
${CMAKE_CURRENT_LIST_DIR}/internal/stubspellchecker.h
${CMAKE_CURRENT_LIST_DIR}/internal/lyricsspellcheckservice.cpp
${CMAKE_CURRENT_LIST_DIR}/internal/lyricsspellcheckservice.h

${CMAKE_CURRENT_LIST_DIR}/view/abstractnotationpaintview.cpp
${CMAKE_CURRENT_LIST_DIR}/view/abstractnotationpaintview.h
Expand Down Expand Up @@ -196,6 +210,9 @@ set(MODULE_SRC
${CMAKE_CURRENT_LIST_DIR}/view/editgridsizedialogmodel.cpp
${CMAKE_CURRENT_LIST_DIR}/view/editgridsizedialogmodel.h

${CMAKE_CURRENT_LIST_DIR}/view/lyricsspellingissuesmodel.cpp
${CMAKE_CURRENT_LIST_DIR}/view/lyricsspellingissuesmodel.h

${CMAKE_CURRENT_LIST_DIR}/view/editpercussionshortcutmodel.cpp
${CMAKE_CURRENT_LIST_DIR}/view/editpercussionshortcutmodel.h

Expand Down Expand Up @@ -245,6 +262,10 @@ set(MODULE_LINK
Qt::Widgets
)

if (HUNSPELL_FOUND)
set(MODULE_LINK ${MODULE_LINK} ${HUNSPELL_LIBRARIES})
endif()

if (MUE_BUILD_NOTATION_TESTS)
add_subdirectory(tests)
endif()
Expand Down
56 changes: 56 additions & 0 deletions src/notation/cmake/SetupHunspell.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# SPDX-License-Identifier: GPL-3.0-only
# MuseScore-Studio-CLA-applies
#
# MuseScore Studio
# Music Composition & Notation
#
# Copyright (C) 2024 MuseScore Limited
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

set(HUNSPELL_FOUND OFF)

if (MUE_COMPILE_USE_SYSTEM_HUNSPELL)
# Try find_library first for reliable full path resolution
find_path(HUNSPELL_INCLUDE_DIR hunspell/hunspell.hxx
PATHS /usr/include /usr/local/include /opt/homebrew/include
)
find_library(HUNSPELL_LIBRARY NAMES hunspell hunspell-1.7 hunspell-1.6
PATHS /usr/lib /usr/local/lib /opt/homebrew/lib
)
if (HUNSPELL_INCLUDE_DIR AND HUNSPELL_LIBRARY)
set(HUNSPELL_FOUND ON)
set(HUNSPELL_INCLUDE_DIRS ${HUNSPELL_INCLUDE_DIR})
set(HUNSPELL_LIBRARIES ${HUNSPELL_LIBRARY})
message(STATUS "Found hunspell: ${HUNSPELL_LIBRARY}")
endif()

# Fallback to pkg-config if find_library didn't work
if (NOT HUNSPELL_FOUND)
find_package(PkgConfig QUIET)
if (PkgConfig_FOUND)
pkg_check_modules(HUNSPELL_PKG hunspell)
if (HUNSPELL_PKG_FOUND)
# Use LINK_LIBRARIES which contains full paths
set(HUNSPELL_FOUND ON)
set(HUNSPELL_INCLUDE_DIRS ${HUNSPELL_PKG_INCLUDE_DIRS})
set(HUNSPELL_LIBRARIES ${HUNSPELL_PKG_LINK_LIBRARIES})
message(STATUS "Found hunspell via pkg-config: ${HUNSPELL_PKG_VERSION}")
endif()
endif()
endif()

if (NOT HUNSPELL_FOUND)
message(STATUS "Hunspell not found - lyrics spellcheck will be disabled")
endif()
endif()
68 changes: 68 additions & 0 deletions src/notation/ilyricsspellcheckservice.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-Studio-CLA-applies
*
* MuseScore Studio
* Music Composition & Notation
*
* Copyright (C) 2024 MuseScore Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef MU_NOTATION_ILYRICSSPELLCHECKSERVICE_H
#define MU_NOTATION_ILYRICSSPELLCHECKSERVICE_H

#include <QString>
#include <QList>

#include "modularity/imoduleinterface.h"
#include "notation/inotation.h"

namespace mu::engraving {
class Lyrics;
}

namespace mu::notation {
struct LyricsSpellCheckIssue {
QString word;
int occurrenceCount = 0;
QString firstLocation;
mu::engraving::Lyrics* firstLyrics = nullptr;
QList<mu::engraving::Lyrics*> allOccurrences;
};

struct LyricsSpellCheckResult {
bool spellCheckerAvailable = false;
QString language;
QString errorMessage;
QList<LyricsSpellCheckIssue> issues;
int totalLyricsChecked = 0;
int totalWordsChecked = 0;
};

class ILyricsSpellCheckService : MODULE_EXPORT_INTERFACE
{
INTERFACE_ID(ILyricsSpellCheckService)

public:
virtual ~ILyricsSpellCheckService() = default;

virtual LyricsSpellCheckResult checkLyrics(INotationPtr notation) = 0;
virtual bool isAvailable() const = 0;
virtual QStringList availableLanguages() const = 0;
virtual QString currentLanguage() const = 0;
virtual bool setLanguage(const QString& langCode) = 0;
};
}

#endif // MU_NOTATION_ILYRICSSPELLCHECKSERVICE_H
Loading
Loading