qabc-1.8/0000755000175000017500000000000014167467134010377 5ustar benbenqabc-1.8/EditTabWidget.h0000644000175000017500000000200014167467102013213 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef EDITTABWIDGET_H #define EDITTABWIDGET_H #include "EditWidget.h" #include class EditTabWidget: public QTabWidget { Q_OBJECT public: EditTabWidget(QWidget* parent = nullptr); ~EditTabWidget(); QList *editWidgetList(); EditWidget *currentEditWidget(); int addTab(EditWidget *swidget); void removeTab(int index); void removeTabs(void); void askRemoveTab(int index); protected slots: void onCurrentChanged(int index); private: QList editwidgetlist; EditWidget* currenteditwidget; }; #endif qabc-1.8/ViewWidget.cpp0000644000175000017500000000123214167467102013152 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "ViewWidget.h" ViewWidget::ViewWidget(QWidget* parent) : QWidget(parent) { setLayout(&viewvboxlayout); } ViewWidget::~ViewWidget() { } ViewVBoxLayout *ViewWidget::viewVBoxLayout() { return &viewvboxlayout; } qabc-1.8/AbcMainWindow.h0000644000175000017500000000211414167467102013223 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef ABCMAINWINDOW_H #define ABCMAINWINDOW_H #include "HelpMenu.h" #include "PreferencesMenu.h" #include "ScoreMenu.h" #include "MainHBoxLayout.h" #include #include #include #include #include #include class AbcMainWindow: public QMainWindow { Q_OBJECT public: AbcMainWindow(QWidget* parent = nullptr); ~AbcMainWindow(); MainHBoxLayout *mainHBoxLayout(); ScoreMenu *scoreMenu(); protected: void closeEvent(QCloseEvent *event); private: ScoreMenu scoremenu; PreferencesMenu preferencesmenu; HelpMenu helpmenu; MainHBoxLayout mainhboxlayout; }; #endif qabc-1.8/settings.h0000644000175000017500000000125014167467102012401 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef SETTINGS_H #define SETTINGS_H #include class Settings : public QSettings { Q_OBJECT public: explicit Settings(QObject* parent = nullptr); void check(); void reset(); signals: }; #endif // SETTINGS_H qabc-1.8/RunPushButton.cpp0000644000175000017500000000123414167467102013676 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "RunPushButton.h" RunPushButton::RunPushButton(QWidget* parent) : QPushButton(parent) { setText(tr("&View score")); setIcon(QIcon::fromTheme("document-print-preview")); } RunPushButton::~RunPushButton() { } qabc-1.8/EditWidget.h0000644000175000017500000000157214167467102012601 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef EDITWIDGET_H #define EDITWIDGET_H #include "EditVBoxLayout.h" #include #include class EditWidget: public QWidget { Q_OBJECT public: explicit EditWidget(const QString& fileName, QWidget* parent = nullptr); ~EditWidget(); EditVBoxLayout *editVBoxLayout(); QString *fileName(); void setFileName(const QString& fileName); private: EditVBoxLayout editvboxlayout; QString filename; }; #endif qabc-1.8/PlayPushButton.cpp0000644000175000017500000000174614167467102014047 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "PlayPushButton.h" PlayPushButton::PlayPushButton(QWidget* parent) : QPushButton(parent) { play = true; setText(tr("&Play")); setIcon(QIcon::fromTheme("media-playback-start")); } PlayPushButton::~PlayPushButton() { } void PlayPushButton::flip() { if (play) { setText(tr("Sto&p")); setIcon(QIcon::fromTheme("media-playback-stop")); } else { setText(tr("&Play")); setIcon(QIcon::fromTheme("media-playback-start")); } play = !play; } bool PlayPushButton::isPlay() { return play; } qabc-1.8/COPYING0000644000175000017500000000067114167467102011431 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later qabc-1.8/AbcPlainTextEdit.cpp0000644000175000017500000003332514167467102014230 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "AbcPlainTextEdit.h" #include #include #include #include #include #include #include #include #include #include "config.h" #include "settings.h" AbcPlainTextEdit::AbcPlainTextEdit(QWidget* parent) : QPlainTextEdit(parent), saved(false) { lineNumberArea = new LineNumberArea(this); highlighter = new AbcHighlighter(this->document()); dictModel = modelFromFile(":dict.txt"); gmModel = modelFromFile(":gm.txt"); QCompleter *com = new QCompleter(this); com->setModel(dictModel); com->setModelSorting(QCompleter::CaseInsensitivelySortedModel); com->setCaseSensitivity(Qt::CaseInsensitive); com->setWrapAround(false); setCompleter(com); connect(this, &AbcPlainTextEdit::blockCountChanged, this, &AbcPlainTextEdit::updateLineNumberAreaWidth); connect(this, &AbcPlainTextEdit::updateRequest, this, &AbcPlainTextEdit::updateLineNumberArea); connect(this, &AbcPlainTextEdit::cursorPositionChanged, this, &AbcPlainTextEdit::checkDictionnary); connect(this, &AbcPlainTextEdit::modificationChanged, this, &AbcPlainTextEdit::flagModified); updateLineNumberAreaWidth(0); Settings settings; QVariant enableHighlightCurrentLine = settings.value(EDITOR_HIGHLIGHT); if (enableHighlightCurrentLine.toBool()) { connect(this, &AbcPlainTextEdit::cursorPositionChanged, this, &AbcPlainTextEdit::highlightCurrentLine); highlightCurrentLine(); } } AbcPlainTextEdit::~AbcPlainTextEdit() { delete dictModel; delete gmModel; } void AbcPlainTextEdit::setCompleter(QCompleter *completer) { if (c) c->disconnect(this); c = completer; if (!c) return; c->setWidget(this); c->setCompletionMode(QCompleter::PopupCompletion); c->setCaseSensitivity(Qt::CaseSensitive); c->setFilterMode(Qt::MatchContains); QObject::connect(c, QOverload::of(&QCompleter::activated), this, &AbcPlainTextEdit::insertCompletion); } QCompleter *AbcPlainTextEdit::completer() const { return c; } void AbcPlainTextEdit::flagModified(bool enable) { this->saved = !enable; } bool AbcPlainTextEdit::isSaved() { return this->saved; } void AbcPlainTextEdit::setSaved() { this->saved = true; this->document()->setModified(false); } void AbcPlainTextEdit::insertCompletion(const QString &completion) { if (c->widget() != this) return; QTextCursor tc = textCursor(); #if 0 /* this for startWith mode */ int extra = completion.length() - c->completionPrefix().length(); tc.movePosition(QTextCursor::Left); tc.movePosition(QTextCursor::EndOfWord); tc.insertText(completion.right(extra)); #else /* this for contains mode */ tc.select(QTextCursor::WordUnderCursor); tc.removeSelectedText(); tc.insertText(completion); #endif setTextCursor(tc); } QString AbcPlainTextEdit::textUnderCursor() const { QTextCursor tc = textCursor(); tc.select(QTextCursor::WordUnderCursor); return tc.selectedText(); } QString AbcPlainTextEdit::lineUnderCursor() const { QTextCursor tc = textCursor(); tc.select(QTextCursor::LineUnderCursor); return tc.selectedText(); } void AbcPlainTextEdit::checkDictionnary(void) { QString line = lineUnderCursor(); if (c && (c->model() == dictModel) && (line.startsWith("%%MIDI program") || line.startsWith("%%MIDI bassprog") || line.startsWith("%%MIDI chordprog"))) { c->setModel(gmModel); } else if (c && (c->model() == gmModel)) { c->setModel(dictModel); } } void AbcPlainTextEdit::focusInEvent(QFocusEvent *e) { if (c) c->setWidget(this); QPlainTextEdit::focusInEvent(e); } void AbcPlainTextEdit::keyPressEvent(QKeyEvent *e) { if (c && c->popup()->isVisible()) { // The following keys are forwarded by the completer to the widget switch (e->key()) { case Qt::Key_Enter: case Qt::Key_Return: case Qt::Key_Escape: case Qt::Key_Tab: case Qt::Key_Backtab: e->ignore(); return; // let the completer do default behavior default: break; } } /* Here, the completer popup is not shown yet */ //const bool isShortcut = (e->modifiers().testFlag(Qt::ControlModifier) && e->key() == Qt::Key_E); // CTRL+E const bool isShortcut = e->key() == Qt::Key_Tab && e->modifiers().testFlag(Qt::NoModifier); if (!c || !isShortcut) QPlainTextEdit::keyPressEvent(e); const bool ctrlOrShift = e->modifiers().testFlag(Qt::ControlModifier) || e->modifiers().testFlag(Qt::ShiftModifier); if (!c || (ctrlOrShift && e->text().isEmpty())) return; static QString eow("!%~@#$^&*()_+{}|:\"<>?,./;'[]\\-="); // end of word const bool hasModifier = (e->modifiers() != Qt::NoModifier) && !ctrlOrShift; QString completionPrefix = textUnderCursor(); /* no shortcut pressed, or a modifier-only key is pressed, * or the word typed is too short, or it is a complete word: * then unshow popup if needed and return */ if (!isShortcut && (hasModifier || e->text().isEmpty()|| completionPrefix.length() < 2 || eow.contains(e->text().right(1)))) { c->popup()->hide(); return; } /* here we have a possible case of showing completion popup */ if (completionPrefix != c->completionPrefix()) { c->setCompletionPrefix(completionPrefix); c->popup()->setCurrentIndex(c->completionModel()->index(0, 0)); } QRect cr = cursorRect(); cr.setWidth(c->popup()->sizeHintForColumn(0) + c->popup()->verticalScrollBar()->sizeHint().width()); c->complete(cr); // popup it up! } int AbcPlainTextEdit::lineNumberAreaWidth() { int digits = 1; int max = qMax(1, blockCount()); while (max >= 10) { max /= 10; ++digits; } int space = 3 + fontMetrics().horizontalAdvance(QLatin1Char('9')) * digits; return space; } void AbcPlainTextEdit::updateLineNumberAreaWidth(int /* newBlockCount */) { setViewportMargins(lineNumberAreaWidth(), 0, 0, 0); } void AbcPlainTextEdit::updateLineNumberArea(const QRect &rect, int dy) { if (dy) lineNumberArea->scroll(0, dy); else lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height()); if (rect.contains(viewport()->rect())) updateLineNumberAreaWidth(0); } void AbcPlainTextEdit::resizeEvent(QResizeEvent *e) { QPlainTextEdit::resizeEvent(e); QRect cr = contentsRect(); lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height())); } void AbcPlainTextEdit::highlightCurrentLine() { QList extraSelections; if (!isReadOnly()) { QTextEdit::ExtraSelection selection; QColor lineColor = qApp->palette().color(QPalette::Highlight); selection.format.setBackground(lineColor); selection.format.setProperty(QTextFormat::FullWidthSelection, true); selection.cursor = textCursor(); selection.cursor.clearSelection(); extraSelections.append(selection); } setExtraSelections(extraSelections); } void AbcPlainTextEdit::lineNumberAreaPaintEvent(QPaintEvent *event) { QPainter painter(lineNumberArea); painter.fillRect(event->rect(), Qt::lightGray); QTextBlock block = firstVisibleBlock(); int blockNumber = block.blockNumber(); int top = qRound(blockBoundingGeometry(block).translated(contentOffset()).top()); int bottom = top + qRound(blockBoundingRect(block).height()); while (block.isValid() && top <= event->rect().bottom()) { if (block.isVisible() && bottom >= event->rect().top()) { QString number = QString::number(blockNumber + 1); painter.setPen(Qt::black); painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(), Qt::AlignRight, number); } block = block.next(); top = bottom; bottom = top + qRound(blockBoundingRect(block).height()); ++blockNumber; } } AbcHighlighter::AbcHighlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) { Settings settings; AbcHighlightingRule rule; QColor color = settings.value(EDITOR_BAR_COLOR).toString(); barFormat.setFontWeight(QFont::Bold); barFormat.setForeground(color); rule.pattern = QRegularExpression(QStringLiteral("(::|[:\\|\\[]?\\|[:\\|\\]]?)")); rule.format = barFormat; highlightingRules.append(rule); noteFormat.setFontWeight(QFont::Bold); noteFormat.setForeground(qApp->palette().color(QPalette::Text)); rule.pattern = QRegularExpression(QStringLiteral("[_=^]*[A-HZa-hz][,']*/*[1-9]*")); rule.format = noteFormat; highlightingRules.append(rule); color = settings.value(EDITOR_DECORATION_COLOR).toString(); decorFormat.setFontWeight(QFont::Normal); decorFormat.setForeground(color); rule.pattern = QRegularExpression(QStringLiteral("![^!]*!")); rule.format = decorFormat; highlightingRules.append(rule); color = settings.value(EDITOR_GCHORD_COLOR).toString(); gchordFormat.setFontWeight(QFont::Normal); gchordFormat.setForeground(color); rule.pattern = QRegularExpression(QStringLiteral("\"[A-H][^\"]*\"")); rule.format = gchordFormat; highlightingRules.append(rule); color = settings.value(EDITOR_COMMENT_COLOR).toString(); singleLineCommentFormat.setFontWeight(QFont::Normal); singleLineCommentFormat.setForeground(color); rule.pattern = QRegularExpression(QStringLiteral("%[^\n]*")); rule.format = singleLineCommentFormat; highlightingRules.append(rule); color = settings.value(EDITOR_EXTRAINSTR_COLOR).toString(); extraInstructionFormat.setFontWeight(QFont::Bold); extraInstructionFormat.setForeground(color); rule.pattern = QRegularExpression(QStringLiteral("^%%[^%\n]+")); rule.format = extraInstructionFormat; highlightingRules.append(rule); color = settings.value(EDITOR_LYRIC_COLOR).toString(); lyricFormat.setFontWeight(QFont::Normal); lyricFormat.setForeground(color); rule.pattern = QRegularExpression(QStringLiteral("^w:[^\n]+")); rule.format = lyricFormat; highlightingRules.append(rule); color = settings.value(EDITOR_HEADER_COLOR).toString(); headerFormat.setFontWeight(QFont::Bold); headerFormat.setForeground(color); const QString keywordPatterns[] = { QStringLiteral("^A:[^\n]+"), QStringLiteral("^B:[^\n]+"), QStringLiteral("^C:[^\n]+"), QStringLiteral("^D:[^\n]+"), QStringLiteral("^E:[^\n]+"), QStringLiteral("^F:[^\n]+"), QStringLiteral("^G:[^\n]+"), QStringLiteral("^H:[^\n]+"), QStringLiteral("^I:[^\n]+"), QStringLiteral("^K:[^\n]+"), QStringLiteral("^L:[^\n]+"), QStringLiteral("^M:[^\n]+"), QStringLiteral("^N:[^\n]+"), QStringLiteral("^O:[^\n]+"), QStringLiteral("^P:[^\n]+"), QStringLiteral("^Q:[^\n]+"), QStringLiteral("^R:[^\n]+"), QStringLiteral("^S:[^\n]+"), QStringLiteral("^T:[^\n]+"), QStringLiteral("^V:[^\n]+"), QStringLiteral("^W:|^\n]+"), QStringLiteral("^X:[^\n]+"), QStringLiteral("^Z:[^\n]+") }; for (const QString &pattern : keywordPatterns) { rule.pattern = QRegularExpression(pattern); rule.format = headerFormat; highlightingRules.append(rule); } #if 0 multiLineHeaderFormat.setForeground(Qt::darkMagenta); headerStartExpression = QRegularExpression(QStringLiteral("^X:")); headerEndExpression = QRegularExpression(QStringLiteral("^K:[^\n]+")); #endif } void AbcHighlighter::highlightBlock(const QString &text) { for (const AbcHighlightingRule &rule : qAsConst(highlightingRules)) { QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); while (matchIterator.hasNext()) { QRegularExpressionMatch match = matchIterator.next(); setFormat(match.capturedStart(), match.capturedLength(), rule.format); } } #if 0 setCurrentBlockState(0); int startIndex = 0; if (previousBlockState() != 1) startIndex = text.indexOf(headerStartExpression); while (startIndex >= 0) { QRegularExpressionMatch match = headerEndExpression.match(text, startIndex); int endIndex = match.capturedStart(); int headerLength = 0; if (endIndex == -1) { setCurrentBlockState(1); headerLength = text.length() - startIndex; } else { headerLength = endIndex - startIndex + match.capturedLength(); } setFormat(startIndex, headerLength, multiLineHeaderFormat); startIndex = text.indexOf(headerStartExpression, startIndex + headerLength); } #endif } QAbstractItemModel *AbcPlainTextEdit::modelFromFile(const QString& fileName) { QFile file(fileName); if (!file.open(QFile::ReadOnly)) return new QStringListModel(c); #ifndef QT_NO_CURSOR QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); #endif QStringList words; while (!file.atEnd()) { QByteArray line = file.readLine(); if (!line.isEmpty()) words << QString::fromUtf8(line.trimmed()); } #ifndef QT_NO_CURSOR QGuiApplication::restoreOverrideCursor(); #endif return new QStringListModel(words, c); } qabc-1.8/editorprefdialog.h0000644000175000017500000000215214167467102014066 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef EDITORPREFDIALOG_H #define EDITORPREFDIALOG_H #include #include #include #include #include class EditorPrefDialog : public QDialog { Q_OBJECT public: explicit EditorPrefDialog(QWidget *parent = nullptr); ~EditorPrefDialog(); QColor getColor(QString key); bool getHighlight(); signals: private slots: void onColorButtonClicked(); private: QVBoxLayout* mainLayout; QLabel* highlightLabel; QCheckBox* highlightCheck; QStringList colorLabels; QStringList colorKeys; QList colorButtons; QDialogButtonBox* buttons; }; #endif // EDITORPREFDIALOG_H qabc-1.8/AbcProcess.h0000644000175000017500000000253314167467102012572 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef ABCPROCESS_H #define ABCPROCESS_H #include class AbcProcess : public QProcess { Q_OBJECT public: enum ProcessType {ProcessUnknown, ProcessCompiler, ProcessViewer, ProcessPlayer, ProcessSynth}; explicit AbcProcess(ProcessType which, QObject *parent); ProcessType which(); QByteArray* log(); signals: void finished(int exitCode, QProcess::ExitStatus exitStatus, ProcessType which); void errorOccurred(QProcess::ProcessError error, const QString& program, ProcessType which); void outputText(const QByteArray& text); #if 1 void errorText(const QByteArray& text); #endif protected slots: #if 0 void onOutput(); #else void onStdout(); void onStderr(); #endif void onFinished(int exitCode, QProcess::ExitStatus exitStatus); void onErrorOccured(QProcess::ProcessError error); private: ProcessType type; QByteArray output; }; #endif // ABCPROCESS_H qabc-1.8/ScoreMenu.h0000644000175000017500000000275714167467102012456 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef SCOREMENU_H #define SCOREMENU_H #include #include #include class ScoreMenu: public QMenu { Q_OBJECT public: ScoreMenu(QWidget* parent = nullptr); ~ScoreMenu(); QMessageBox::StandardButton gracefulQuit(); bool loadFile(const QString& fileName); protected: void setRecentFile(const QString& fileName); void updateRecentFileActions(); QString strippedName(const QString &fullFileName); protected slots: void onQuitActionTriggered(); void onOpenActionTriggered(); void onOpenRecentActionTriggered(); void onSaveActionTriggered(); void onSaveAsActionTriggered(); void onCloseActionTriggered(); void onNewActionTriggered(); private: QAction newaction; QAction openaction; enum { MaxRecentFiles = 5 }; QAction *recentFileActs[MaxRecentFiles]; QAction saveaction; QAction saveasaction; QAction closeaction; QAction quitaction; }; #define NEW_TEMPLATE "X:1\nT:Melody...\nC:Piotr Ilitch Tchaïkovski\nM:4/4\nL:1/4\nK:Amin\n!mf!ABcd|e3c|e3A|cAFc|A4|]" #endif qabc-1.8/dict.txt0000644000175000017500000000075514167467102012065 0ustar benbenaccent alto bank barlines bass bassprog beat beatstring breath channel chordname chordprog coda control crescendo diminuendo downbow emphasis fermata ff fff ffff fine gchord gchordoff gchordon grace instrument invertedfermata longphrase lowermordent mediumphrase mf MIDI mordent nobarlines open pitchbend pp ppp pppp pralltriller program ratio repeatbar repeatbar2 roll segno sfz shortphrase snap staves tenuto thumb transpose treble trill turn upbow uppermordent voice voicecolor vskip wedge qabc-1.8/AbcPlainTextEdit.h0000644000175000017500000000573514167467102013701 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef ABCPLAINTEXTEDIT_H #define ABCPLAINTEXTEDIT_H #include #include #include #include class AbcHighlighter : public QSyntaxHighlighter { Q_OBJECT public: AbcHighlighter(QTextDocument *parent = 0); protected: void highlightBlock(const QString &text) override; private: struct AbcHighlightingRule { QRegularExpression pattern; QTextCharFormat format; }; QVector highlightingRules; #if 0 QRegularExpression headerStartExpression; QRegularExpression headerEndExpression; #endif QTextCharFormat headerFormat; QTextCharFormat extraInstructionFormat; QTextCharFormat singleLineCommentFormat; QTextCharFormat noteFormat; QTextCharFormat decorFormat; QTextCharFormat gchordFormat; QTextCharFormat barFormat; QTextCharFormat lyricFormat; #if 0 QTextCharFormat multiLineHeaderFormat; #endif }; class AbcPlainTextEdit: public QPlainTextEdit { Q_OBJECT public: AbcPlainTextEdit(QWidget* parent = nullptr); ~AbcPlainTextEdit(); void lineNumberAreaPaintEvent(QPaintEvent *event); int lineNumberAreaWidth(); void setCompleter(QCompleter *c); QCompleter *completer() const; bool isSaved(); void setSaved(); protected: void resizeEvent(QResizeEvent *event) override; void keyPressEvent(QKeyEvent *e) override; void focusInEvent(QFocusEvent *e) override; void flagModified(bool enable); private slots: void updateLineNumberAreaWidth(int newBlockCount); void highlightCurrentLine(); void checkDictionnary(); void updateLineNumberArea(const QRect &rect, int dy); void insertCompletion(const QString &completion); private: QAbstractItemModel *modelFromFile(const QString &fileName); QAbstractItemModel *dictModel; /* normal dictionnary */ QAbstractItemModel *gmModel; /* General MIDI dictionary */ QWidget *lineNumberArea; AbcHighlighter *highlighter; QString textUnderCursor() const; QString lineUnderCursor() const; QCompleter *c = nullptr; bool saved; }; class LineNumberArea : public QWidget { public: LineNumberArea(AbcPlainTextEdit *editor) : QWidget(editor), abcplaintextedit(editor) {} QSize sizeHint() const override { return QSize(abcplaintextedit->lineNumberAreaWidth(), 0); } protected: void paintEvent(QPaintEvent *event) override { abcplaintextedit->lineNumberAreaPaintEvent(event); } private: AbcPlainTextEdit *abcplaintextedit; }; #endif qabc-1.8/RunPushButton.h0000644000175000017500000000122114167467102013337 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef RUNPUSHBUTTON_H #define RUNPUSHBUTTON_H #include class RunPushButton: public QPushButton { Q_OBJECT public: RunPushButton(QWidget* parent = nullptr); ~RunPushButton(); private: }; #endif qabc-1.8/EditWidget.cpp0000644000175000017500000000174714167467102013140 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "EditWidget.h" #include EditWidget::EditWidget(const QString& fileName, QWidget *parent) : QWidget(parent), editvboxlayout(fileName, this), filename(fileName) { setObjectName("EditWidget:" + fileName); setLayout(&editvboxlayout); } EditWidget::~EditWidget() { } EditVBoxLayout *EditWidget::editVBoxLayout() { return &editvboxlayout; } QString *EditWidget::fileName() { return &filename; } void EditWidget::setFileName(const QString &fileName) { filename = fileName; editVBoxLayout()->setFileName(fileName); } qabc-1.8/AbcTemporaryFile.h0000644000175000017500000000146214167467102013736 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef ABCTEMPORARYFILE_H #define ABCTEMPORARYFILE_H #include class AbcTemporaryFile : public QTemporaryFile { Q_OBJECT public: AbcTemporaryFile(); bool open() { resize(0); return open(QIODevice::WriteOnly|QIODevice::Truncate); }; protected: bool open(OpenMode mode) { return QTemporaryFile::open(mode);}; }; #endif // ABCTEMPORARYFILE_H qabc-1.8/MainHBoxLayout.h0000644000175000017500000000150214167467102013404 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef MAINHBOXLAYOUT_H #define MAINHBOXLAYOUT_H #include "ViewWidget.h" #include "EditTabWidget.h" #include class MainHBoxLayout: public QHBoxLayout { Q_OBJECT public: MainHBoxLayout(QWidget* parent = nullptr); ~MainHBoxLayout(); EditTabWidget *editTabWidget(); ViewWidget *viewWidget(); private: EditTabWidget edittabwidget; ViewWidget viewwidget; }; #endif qabc-1.8/settings.cpp0000644000175000017500000000500214167467102012733 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "settings.h" #include "config.h" Settings::Settings(QObject* parent) : QSettings(SETTINGS_DOMAIN, SETTINGS_APP, parent) { } void Settings::check() { QVariant player = value(PLAYER_KEY); if (!player.isValid()) setValue(PLAYER_KEY, ABC2MIDI); QVariant synth = value(SYNTH_KEY); if (!synth.isValid()) setValue(SYNTH_KEY, FLUIDSYNTH); QVariant compiler = value(COMPILER_KEY); if (!compiler.isValid()) setValue(COMPILER_KEY, ABCM2PS); QVariant viewer = value(VIEWER_KEY); if (viewer.isValid()) setValue(VIEWER_KEY, PSVIEWER); QVariant highlight = value(EDITOR_HIGHLIGHT); if (!highlight.isValid()) setValue(EDITOR_HIGHLIGHT, true); QVariant color = value(EDITOR_BAR_COLOR); if (!color.isValid()) setValue(EDITOR_BAR_COLOR, "red"); color = value(EDITOR_COMMENT_COLOR); if (!color.isValid()) setValue(EDITOR_COMMENT_COLOR, "gray"); color = value(EDITOR_DECORATION_COLOR); if (!color.isValid()) setValue(EDITOR_DECORATION_COLOR, "orange"); color = value(EDITOR_EXTRAINSTR_COLOR); if (!color.isValid()) setValue(EDITOR_EXTRAINSTR_COLOR, "blue"); color = value(EDITOR_GCHORD_COLOR); if (!color.isValid()) setValue(EDITOR_GCHORD_COLOR, "green"); color = value(EDITOR_HEADER_COLOR); if (!color.isValid()) setValue(EDITOR_HEADER_COLOR, "darkcyan"); color = value(EDITOR_LYRIC_COLOR); if (!color.isValid()) setValue(EDITOR_LYRIC_COLOR, "magenta"); sync(); } void Settings::reset() { setValue(PLAYER_KEY, ABC2MIDI); setValue(SYNTH_KEY, FLUIDSYNTH); setValue(COMPILER_KEY, ABCM2PS); setValue(VIEWER_KEY, PSVIEWER); setValue(EDITOR_HIGHLIGHT, true); setValue(EDITOR_BAR_COLOR, "red"); setValue(EDITOR_COMMENT_COLOR, "gray"); setValue(EDITOR_DECORATION_COLOR, "orange"); setValue(EDITOR_EXTRAINSTR_COLOR, "blue"); setValue(EDITOR_GCHORD_COLOR, "green"); setValue(EDITOR_HEADER_COLOR, "darkcyan"); setValue(EDITOR_LYRIC_COLOR, "magenta"); sync(); } qabc-1.8/application-vnd-abc.xml0000644000175000017500000000070214167467102014726 0ustar benben ABC musical score file Fichier de partition musicale ABC qabc-1.8/AbcApplication.cpp0000644000175000017500000000241314167467102013747 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "AbcApplication.h" #include "settings.h" #include #include "config.h" AbcApplication::AbcApplication(int& argc, char **argv) : QApplication(argc, argv) { setOrganizationName(SETTINGS_DOMAIN); setOrganizationDomain("herewe"); setApplicationName(SETTINGS_APP); setApplicationVersion(VERSION " (" REVISION ")"); Settings settings; settings.check(); settings.sync(); } AbcApplication::~AbcApplication() { } void AbcApplication::setMainWindow(AbcMainWindow* w) { abcmainwindow = w; } AbcMainWindow *AbcApplication::mainWindow() { return abcmainwindow; } void AbcApplication::openFileNames(const QStringList &fileNames) { ScoreMenu* menu = mainWindow()->scoreMenu(); for (int i = 0; i < fileNames.length(); i++) { QString fileName = fileNames[i]; menu->loadFile(fileName); } } qabc-1.8/resources.qrc0000644000175000017500000000017514167467102013116 0ustar benben dict.txt gm.txt qabc-1.8/gm.txt0000644000175000017500000000443714167467102011546 0ustar benben0 % Acoustic Grand Piano 1 % Bright Acoustic Piano 2 % Electric Grand Piano 3 % Honky-tonk Piano 4 % Electric Piano 1 5 % Electric Piano 2 6 % Harpsichord 7 % Clavinet 8 % Celesta 9 % Glockenspiel 10 % Music Box 11 % Vibraphone 12 % Marimba 13 % Xylophone 14 % Tubular Bells 15 % Dulcimer 16 % Drawbar Organ 17 % Percussive Organ 18 % Rock Organ 19 % Church Organ 20 % Reed Organ 21 % Accordion 22 % Harmonica 23 % Tango Accordion 24 % Acoustic Guitar (nylon) 25 % Acoustic Guitar (steel) 26 % Electric Guitar (jazz) 27 % Electric Guitar (clean) 28 % Electric Guitar (muted) 29 % Overdriven Guitar 30 % Distortion Guitar 31 % Guitar Harmonics 32 % Acoustic Bass 33 % Electric Bass (finger) 34 % Electric Bass (pick) 35 % Fretless Bass 36 % Slap Bass 1 37 % Slap Bass 2 38 % Synth Bass 1 39 % Synth Bass 2 40 % Violin 41 % Viola 42 % Cello 43 % Contrabass 44 % Tremolo Strings 45 % Pizzicato Strings 46 % Orchestral Harp 47 % Timpani 48 % String Ensemble 1 49 % String Ensemble 2 50 % SynthStrings 1 51 % SynthStrings 2 52 % Choir Aahs 53 % Voice Oohs 54 % Synth Voice 55 % Orchestra Hit 56 % Trumpet 57 % Trombone 58 % Tuba 59 % Muted Trumpet 60 % French Horn 61 % Brass Section 62 % Synth Brass 1 63 % Synth Brass 2 64 % Soprano Sax 65 % Alto Sax 66 % Tenor Sax 67 % Baritone Sax 68 % Oboe 69 % English Horn 70 % Bassoon 71 % Clarinet 72 % Piccolo 73 % Flute 74 % Recorder 75 % Pan Flute 76 % Blown Bottle 77 % Shakuhachi 78 % Whistle 79 % Ocarina 80 % Lead 1 (square) 81 % Lead 2 (sawtooth) 82 % Lead 3 (calliope) 83 % Lead 4 (chiff) 84 % Lead 5 (charang) 85 % Lead 6 (voice) 86 % Lead 7 (fifths) 87 % Lead 8 (bass+lead) 88 % Pad 1 (new age) 89 % Pad 2 (warm) 90 % Pad 3 (polysynth) 91 % Pad 4 (choir) 92 % Pad 5 (bowed) 93 % Pad 6 (metallic) 94 % Pad 7 (halo) 95 % Pad 8 (sweep) 96 % FX 1 (train) 97 % FX 2 (soundtrack) 98 % FX 3 (crystal) 99 % FX 4 (atmosphere) 100 % FX 5 (brightness) 101 % FX 6 (goblins) 102 % FX 7 (echoes) 103 % FX 8 (sci-fi) 104 % Sitar 105 % Banjo 106 % Shamisen 107 % Koto 108 % Kalimba 109 % Bagpipe 110 % Fiddle 111 % Shanai 112 % Tinkle Bell 113 % Agogo 114 % Steel Drums 115 % Woodblock 116 % Tailo Drum 117 % Melodic Drum 118 % Synth Drum 119 % Reverse Cymbal 120 % Guitar Fret Noise 121 % Breath Noise 122 % Seashore 123 % Bird Tweet 124 % Telephone Ring 125 % Helicopter 126 % Applause 127 % Gunshot qabc-1.8/EditTabWidget.cpp0000644000175000017500000000527514167467102013567 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "AbcApplication.h" #include "EditTabWidget.h" #include #include #include EditTabWidget::EditTabWidget(QWidget* parent) : QTabWidget(parent) { setTabsClosable(true); connect(this, &QTabWidget::tabCloseRequested, this, &EditTabWidget::askRemoveTab); connect(this, &QTabWidget::currentChanged, this, &EditTabWidget::onCurrentChanged); } EditTabWidget::~EditTabWidget() { for (int i = editwidgetlist.length() -1; i >= 0; i-- ) { removeTab(i); } } QList *EditTabWidget::editWidgetList() { return &editwidgetlist; } EditWidget *EditTabWidget::currentEditWidget() { return currenteditwidget; } int EditTabWidget::addTab(EditWidget *swidget) { QFileInfo info(*(swidget->fileName())); int ret = QTabWidget::addTab(swidget, info.baseName()); setCurrentWidget(swidget); editwidgetlist.append(swidget); currenteditwidget = swidget; qDebug() << "addTab: " << (*currenteditwidget->fileName()); return ret; } void EditTabWidget::removeTab(int index) { EditWidget *w = editwidgetlist.at(index); w->editVBoxLayout()->cleanup(); editwidgetlist.removeAt(index); QTabWidget::removeTab(index); delete w; } void EditTabWidget::removeTabs() { int len = editWidgetList()->length(); for (int i = len -1; i >= 0; i-- ) { removeTab(i); } } void EditTabWidget::askRemoveTab(int index) { AbcApplication* a = static_cast(qApp); AbcMainWindow* m = a->mainWindow(); EditWidget *w = editwidgetlist.at(index); if (!w->editVBoxLayout()->abcPlainTextEdit()->isSaved() && (QMessageBox::StandardButton::No == QMessageBox::question(m, tr("Really close?"), tr("Current score not saved!\nClose this score anyway?")))) return; removeTab(index); } void EditTabWidget::onCurrentChanged(int index) { EditWidget* swidget = static_cast(currentWidget()); for (int i = 0; i < editwidgetlist.length(); i++) { if (editwidgetlist.at(i) == swidget) { currenteditwidget = editwidgetlist.at(i); qDebug() << "currentTab: " << index << (*currenteditwidget->fileName()) << i; break; } } } qabc-1.8/HelpMenu.h0000644000175000017500000000140514167467102012260 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef HELPMENU_H #define HELPMENU_H #include #include class HelpMenu: public QMenu { Q_OBJECT public: HelpMenu(QWidget* parent = nullptr); ~HelpMenu(); protected slots: void onAboutActionTriggered(); void onAboutQtActionTriggered(); private: QAction aboutaction; QAction aboutqtaction; }; #endif qabc-1.8/ViewVBoxLayout.cpp0000644000175000017500000000147114167467102014010 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "ViewVBoxLayout.h" ViewVBoxLayout::ViewVBoxLayout(QWidget* parent) : QVBoxLayout(parent) { addWidget(&logview); clearbutton.setText(tr("Clear log")); addWidget(&clearbutton); connect(&clearbutton, &QPushButton::clicked, &logview, &QPlainTextEdit::clear); } ViewVBoxLayout::~ViewVBoxLayout() { } LogView *ViewVBoxLayout::logView() { return &logview; } qabc-1.8/orig.png0000644000175000017500000013665714167467102012062 0ustar benbenPNG  IHDRl ƒPgAMA a cHRMz&u0`:pQ< pHYs  tIME xbKGD̿IDAT?sgZE1D]QDZs][5P_;ֵc^1g@.wks44jA?NƉA?*{i`w16uMTTsDܮF[4h0GAejgJs4-g&V p݌U^2ҧsy5h0GX"byvO+""b#i`EZkbS."""؏Sl[_K  JF1XS*&L5U*b khi8To5 (s4hP\"PƋnj\m;#4V.{xDDcbFFb7 zDg"NV"Fi3tVkZ;4] 1Ђ1ILZZj46JDl֢"Fzkwc"bUTpw8sT[KJ':8b4hR.*񹋭A=T0VTĴ:{ID6*/ 8"""vtQɮ1P=B\'ԘWg{CDDD1kP+hV>("l9MOK9""ƹZN*fۦXq:X[GSƊxSu\RDD$Clm ꧂n1hyr"">uY]c?]a.rttI""B}mԺ^X"U@knT.Dwnǂ~ ƋvXŦ@ f1>c$"Z~j,unJVpDH_^ ۸Uj+a%ϋxEG fK'SD|ޙƈͭ"bWѳ>1 r~?}$";Y4D0[Qk!)bHm5-7;͞E]l8Ts)b19=K"hdJZ#vrg5'""F(f`#M:OD| tq">p~{eb,-fx<d%4<#"h}׋*wM"|[YxǎʱEēR3LZOW'ZSD"-jQl jdE\iz}%U-*AVJ7YU}GDhxU+ ~"2] "MM|yXw1VG5Z_W1*DuEeJ/tGYrLo;SD جk"Ub~ -n^ 9X10lb+YA)͵N騝 f>PH] ^c,Dĥ"bW?N__QD]|&˙};,Ns3)ADDDd.qQPJ Wm "&MTE)goxfW3yRģzilze:Ź򽈈/p]Wp)Vʳ&uXXD&ƋecQA7Eo=!^]k1T^""""bxғ^|U"""""YEy6sAXD(X֎veAt{|J_D̥ƖƋꣵ=% +ˢ-V0pA[kdr; 1E563Xg5EDD+vȏm$2s>jkRDDDDDDDntUUVFTOm>Z"[<'&RfO>^nT;PW;u\z{"""{ιz[BN$jY"޴2zR|͞6RMS},"víi(P~f""^i-1sL=)">u3sc7qEDU?kUxMOe -̞E]l U'D|Z{YFA1d/""MLܭgD0=$z W0:l i´-/.)"""""bO*knOoY5&Z7LD<{?DDDsPc%1H)'{Ze@9xM\a/"""\meITki}G"""bmtQ_,X1.E̞ݪJ|(-Zmd#եh51@/kYͺ6K75zw"18)c/""""""""""bvݭ@DjU%>tv)&ފfךͭF1eNxF]ފq ӛz.1Ynv?E%>1[nu~g=m@;7}'""b']`ZN.6HħJW.7V sfOF1FhboVc)R]VWEܣ tsqS AaYPTkDhwK͚yuG?xPQSO?sXYcnc[o!y;jll㜩Ms9DK5Zi'G""""bSMMQ tVm>ω6hh8cI^wlle~I"8vmmck[nk;Nt+=dq"""b̾3DD,F3&nuż'b 45$xŴ >jO]xDgqDϊ}vZXQ/\E߉x%7cnRD,Fs.&ԒffB)+wԥTkRs:PLX)FXmEiִc]?>6YDDDDDDd;Pz6򡈈uZFtVÌb~3\JYܥ.wMU;@āYJYAD3+ ""&b9G#NoBўwmd>?_S%b[AexPiDܦiaE"ښ"*$VQqt׺q[\2;zX ~)el 1~+m#v諴D,aE<ڹc[[foRaSh;XH*h0BNH ;)m[)#Ҷ ovxشZO)bgsSEG5V4YD Wc5uQ"">ϕ"(L )*Jilj7M4_+xܴn+3G[(x[৩JK[EWdA5U0g[֙Imfrk+N1Ic%QP*b#n6DIJXRq j6SDz)7U U) qim."QY !bhDLE1-9=T-Y7emyG*E|1j +"btUP\Oψx UđJ[PJ{@]i[lZ \fE_Q=:b)?Ýo s*,C],̺"3WI{>]ky)b IJDtWbƦUfxGNin݌XD|ensE|R0O;l¯`9Ş4Bh/qvUkrK^5Y$ҾT0rkʙ63蠴ɚ(JQ c׋f>C2Y|361EľX"ffGߴ Nꬸ2jcu#hU[Ȭkc]{;>U%[/ICW4wA&ǪQg'""3I8t{ZO{-A""vKH<"Wb*L'VƉf't0vv^1r~715s׈cCbq3CMut5c{f=w |'""""""mXPA*,duAPߙ """# 1u졛VPJAGzEDDD6^ą2\J[^ĎftcC]_њֱӫJB>41RP#h."W̡"n¾b{66U"""b f%mhWǸ=."""""z-NյSk, ~Z_.nD쭴El(bE3ZKDDDkj@§󒛜dss"D">1VDg~=eh$b{+*VS;n1<-"""?QJg`bַˣ7ADDDD|y駷k)Uոev5Ei)Q;  TtQSt""FŒ5;Q:9Jģ8^,ƶb{ʜ`֞ʔb>W0r Mߋ۩s]cDDDD'g>̊kETab*fo*ZBDDG(+*0Q-+"""""""T8H VJS U"N7'plf!9W-"""""""lYB#UU+H7'ff_xZċ5񴈈f_DŮFT-3u7e_{nrn X"6P궬VaQi'hxZCy8EDDDD0U#"0"& yADT9m#"qhfr """"R7xY1|ߊ'^r^ֲt-o1,XPbv.ڨ[oV":+QqW\ SVlmfښ Zs;P|%{EFѶTʚ"bUA-EDDDDn[FWDt(8Aqjfv!PjVv4RPq.Ҍ!bIDܯLwR|%>P^DʽƩ*6UEK)E\d1j5ȷ"""bJY=jl)RL[)3csPqML*3q.VRD"7=h )>pSkSꕕDDfӻJ*|jܦj#bRnqF&;UE &".7sJĪj"R"Z+f~EafdO&궏VJ{\ܢ#EmFcݠZ+!9""b^Ra_worMj-.TSA"klfqZc_|.Ž[̵Mim`"v.IJ^Dk3:W\b5V]WW^jq2 >25*-69KtW\cJ9E.m }NJ;O|EkFhfKb5v"Wʌwje^T+b=5cvֹ"&+W(W"*mZۈWJqY^JNܪ6b2u;R*J+(S/b3 P.tTkKG9XĥAQcgwi*bTj+""""")mQ%Tk ?rNDkz[sAbO+`qgk(_i̊MvxN]>g*fƉj)zF[e%/+'.וīL)b冉k *嚌{(eaYcDbm;z%&L{dNm= 2Vĝ"r}Yj*5 /EĽҕcEDĞj~.""f~8CEo#""b]+2\Ho-bmEҕgu,,roU4CWJXĴ'*fJ-> \T$zjsh1;h~ |GgHDo7UDĮN;k3Ы""NTo 3O,.bNE)e/ƶ1DELܑ]6-m%TDW ""bnm~)Uf5?"|."K%"^w b:UxNēz\EḒȶb&E^ +͕G<ܚ=q;JaN~)bq-"VvXB6PgC+!""j_KDD*jv7?,,+xBhM+TdjѢbX@SŅRܦ;nTUܢ)]"ZPb9U?Mng[m""E]N'NU\F""wjqRGU[[2E~/ح2EVЕCX"Qn8Vw%ȇz ~ܓEXMbaX63VDX_[EDDDDDD*:—""&\GLj;KȟŊ+*3q\.T%rom56E6'beeרg7ƔWWIb3ku/EDӆJDD;wICk[ucb%VE EHsQPf eVr3(3t6X^Bm*FxƷB nr3VD|n m*S2ͩ-EDďFY5:>3ɽ)Vb"W'Ķ6QDUf%Ѣvr;XPn=l#1uݡffD\[q;66I -59Eč*&7q""nn%񨊚EOVܪ]- b^E~.jVqb)XSU;!^gZk@ܯ܁"oD .Su"~[q-&kK訇õtMtv3XUMǩFvK"iVl" JmD Pfgqrg+uǃU.c,.c4jI8S줣MrYT5X ^i]S""bk]ԛg4#(Qq"[uX1BEř=,XgbrӉ8Tb/"޳"n7V;9ZxUl>>_: x_L4Φq5yMDߴmXJMOOUţz:^\ȹ E*F9Nܮ+{ELQbf+V1DYDLB5//5\#Nw}+*J]|,"ƈ8M&NJgn;XDD,ݯZ*n] U>q"XW;ɺ8E7*%bn%br[E̦"<"""W7XAD5:2~X(OkLn&DDL4@&}՛-}"YMU)6]+be/4il?s*wBr{Q*ʬ#bm'""b UDD<[n?KV2V&UL*iKUc7UouZYK7l"VVl5K+rGt3*ȩ1153|kҗ6"i:Z]DD`&mq"Q1zK9YPċ&UP񱮜'^Uhqr/kɗF*x@Df qmEDE**{•~kEEDDD""ZͥФei,HoD[_xVD,[f _a:9ݥ>/.Zk8GGS."Dzz$and!e"nPR[E0I+ŚQ2K觱 D@CDWn*bw "N'6QsEDL[g8SPO)<)b *"bi8 %nWѵVGI""Ul~)3V12ۉt/D>].>vbfeV{)PX^Ļz8XbH񦩴""nf[\JD5+VTd zˋX[D, rNj[uǥ9]ܫS%bzDDЬfQ=qNu7DPݵU;^D[zhw8Oaz+6xbyt4&W'"P7bfe*w8Vw<-.S,\'.S,z'YjgkrxgEl&B#ptb uMEŗ*\&NWbO*w8^6a8HE쫑Pw1l25K}˭sO;T|hv狈vspeq'F_-;L<ؓbwEkB冉Q - bm6rMD"Qi|k 3z\_5kv?~nS9T,MjRK"Zāʽ +h[cYẸ܂"Tf&l D\smHqDl]("I5| ^Y\#fSxL/U/]DfbˉXO^&-5rYMD=YU:[LDW?4?)GM;\Abi\,҄Zn!WdUk*YHqFkr{VSl ^Ӭi3I::OD 0A|HiETqy "?w*s*vI =./c5F.Ô;M"bz,qk7ĥ:Dxv]*bGܪJbv/[SI%>UQ^WG+l@cc8Z#G*w" D~|Ol4WQlmu,-yZ[]H5yLD=CCA*>+wZD̩D,B"vPKr#{Jħ8Bb)//߱ u4 "F{XďrNo&{[,^gLf .Wf1REc[qz(7Dr}OΚ$nfU{Dch."nhu6LWr"!KoV7:=G xZEN"u=՜"׺g>^ZKJELbl".Wy] :}#6e+Rz;K :_Յ4|%"""b<+"vV3qsď,-f/"tqw( 4ND̫čA=LSUuS !**EDD3txC/5Lj;ki&:b)]&]#(h[ghy&*>h2#ԻQDh[޲Dl?4K&\gDĮj5X6QDFTuM#;Zg*'WoQ Y].~'qb_צ""66$(7T\:I"So7S+v2ۈ{Rlq"UfXV#Lj4+r;\DD4#DEn1L[͊0N\Mb-eWٍѢ{^i6V"\l6oj-q ŧe!fq`Ve.'Gb9u!q"h!QlG(U7Mn [F4/vVh2XZDv{T<*"^M#b"U b""">vkqr% 5{P+r}ϙFGS$SlC+3TEĭ&V#VsP rs[MEY1"<<#qof_iA*s7|)"""""&TD  "VbEu8˝! K*vYN<ܹD(be,G[[Ѥ56ӈ7QbvUox.u[""YeMqzyID,f7RV}'h3Y5[IT\Ѣ2?g(EGˋ6KB/[}SI\:"b=D""fN[7p8DSb&5CDĝ|OD;C4yFJyŞ4eU.^ѕċʝ"PSV PjsT4rS#g˕{EN}E%vyM!*}Mn ??lk~kN*{,CCMj]*v[U\Y+ğuC1L,/lOcwS4r2}M[wX`GR*vsݔ[Pg. ?kGMeFgiri&egq" UWqXUM|<%~ش"~G2M]*NA*M#f zx۴F[Nsmn8Z(I&뵙h uA!#+"YWCEܫ~#<[YDxAXP>h2Fl`L}Mq&++Ŏ1I\? +z#D\c{h{Ɖbs(9{j3T4iجƉh1FDDDXM#8WMm&N -b[XLʝ*ٍ"^8ϋ%59^G"+hKs ">p.jueWq co:mjx4ާ.wb%B=`?k1-SP_"vnZwM{6TtTq@دE>%NP.sNDDD,-Yh'bFv/)wREDDƪz$"Vԕj1M}k*#CTCG*+""""vS鞗El㫨Q|vۉ8PN&gxQWPrlKڙ$Ӯc"b=,q:冋""Fi5I V}ʉgVWY;<#R3*KgyUlE̫"bF6M"bp2!6rOæ"l>Qo8ӖjZ72QCUtbqv>5e}Uid[+Z&+^nI-hK)dܢ"Ri&oCf ҾRDL[lw?Ow,$"6,&XXbZ. +MUڝ!)XJ&ikvVvixTW6h q2X[#D?L4KVp5DUo$$0pkͼ*VUtvhu|-X],qN?8W!q^3ڼ&YAߋL-Vq2iY@T# 5Fܭ+?h)2UDC&Z&bqÜ#F:Z_x""驦'l\lJ9EjjmXFcDDc*_E!ELXA8]ך\{n-KO%2"V\12_ērXK&cJ&>UQ]=M|$bVU.V[U3QD|`=}#}lja#^0cۋ◦ŴIF(3VzCD?y} (׮M]c8FM{-O E?b?O_Oq5Ww\l%7x7suU">4<1A1VLVNrLniT,Ux1S/}>4r8[%EP8D'b?eqqͼ$>66I[El"06zF,&i_8XqEDhML8Ww"{W̧t"*ߧspX]SnD4q qbeODkpڔZŒtPgle^q6^?8Yfb1U7me0,"n]ӈzjz"6T&Z,(Rq?*32ˈ_Wq$ "J$v6VDDsԌk+sxOWZ_&;fcE ԵYħ*0<*"ҦK>TmTT^Վ-˽eS_&tO?gg좇.'Dܫ{RiDܨ`rۉ[Yхwz]fr "33d{G]nc benG{b݌VTk-iֵb*v6=&"nQuGT} b}Uۋ5kŦ4I9 {/%Ԑ3R(GGfT\3*G5D-EwltVdt[ՒłRm)boSuxWW%kmmĽ 7PO/e'?>WPͧl.IuZBQg"U} ~j/{T!VTt)9#J:zRdq鸞mi;ER;M-E^T|*"n^T\c{`1Hڶ8.FVqv;k*NWIi-E]Lנ >5"\; "WD쭵ߊ\G)(ZE$՝!5qE4:iRVWi@N3p-5`%Üp(X8o#|uz m{]UY' i&""7?{UDijVjNN;f K);^'7tXgU kil' T!bo,)+4W짵}fx\sED,7PA:E 7n{FDۜ+u)(ZFM-C]X]9V_^]jjsM7h]bEyCFT0N,&u?ECTq=|Ǫbf8Tk*-e~Vg)NV1[DDDx[)Ł^,E1WhGm-"Q]_wx ͔/F+6XT~/.GO#52+fȭ""8my7j`yUv8%5ΪB-뇢 5kvg\Gk/jNyIێ݌TZhxlq$"VQIM\MWo모OĞͯĻgjzjUj,"$u>QbIQ*XNA^UUCkKlo"6HIշk&g)fhK7ϜhIQb\*XV"*m].bm%K7[?m9OD\MXE.ȳ-d1j%I&3FSv8TswU7k)kgwyҒŽ-UP;bu 1}/b(՘.Nڦ"bG)Q1тuuŧ.YSIJЎ>ZCVEL1GsDq"/M**8LqNCu S\\픵^S{1*zB|AHΓ~S*Dw7CR[|eD즵߉|}4X{,T+"a_W)(^R+>6IDܯhs+xNDDDlDx:J,:x]eYV4Glaj[Ozz:8Q\ݢ:ϋQ0ѻv㝠st5S5Xٟ𼈘]D|1):SS5[诵cP[䏺@C"Fi8Bّbz]D +:'jP]_ժ Z("NU"=XT9]f_%uQMxIs+d׋TӔ,""VXDRoEDěZ]{ UshYk/FcTR"z%nSr!"b뭥_Z""D/۫-CE\j11@AKiU}t0:INuq`Uu0EDDĻz)ÛZ3]ĭD8MK{Ct}`7[TKXp(1 R6d/~&R""1^ jhQ}%""JEDD?-".w+""Q}_fo,c=m)F;ц戸@Gpe=W9&Eğ}EִKAϛ=ϪѶEiYp)Jo)ovJ))W\!+z]DWլ!b]ռ'.>"bRh3i1N3@Ⱥ~j=R/]<rYqQk(XC%ݔ(5QD槠sv򁈈k!WVaq b 6/eݵm(jEoXM5;UUbS%/mi1>0D,f:iôv& %{^Z{PD\c9MexǺjbxK{-*(H?n_(()"NEWD|m9lR"bsmqoDDD܂EE48V;-|"}%?2t}-Snf:6Dg#C:h`k--"SEGXBL[1Q"2 1I5ElEncd_۩q-&묹EEܭ8BKiDg["bED(+"emwkˑ""""loÓEiiH1FAEs>:zY\9w'>Z,9Prx\."WP2YDDDO|d; Gsw'Ths'XESSRY*6v #&ꦵ[lkx|A;4*Z< f@\mFٗ""""""+)lyNQsuvVTyqE \k+Ztq+\`z~b~"vQT&:۾A/e[ݿ57~*>Wvgb75k#`E5n2SWtjEzNDDDDEG"jOD|E Q;PgxZgi]q9OmWpw7_5N1òX'޷M]^DZMm/b_=實YOK׈sՋJ'%kjw @KQvFW õFk+(PV)cYΟl;2P "&d1E2sqY((CmE"6r)j(UM"bmu8S""^} ^ÜgW>30D$Smꫥޮ4Otԕ"NsXO[.s&eoN;,91Xs ~ }f謥oyDAp;<%"I}hgq~>:H!"\ͽ-S͑b:-}_Dt{T,-""yg[wDD"qvvX>2hkTP4@1JxFܨEj<%"Wۺ꧝Ot "o^gK 5."bc3Ul!뫬c1ra::""b5Eg끂}O: 穮qjkmMpn 5v3Sܧ7:(n]PEjmmyQԋz1\YgWBKǜcw+Ѷ:׋FoKm/L2ODD`ELq?:6Ikk1F-E\Y-]mmt04Zf{WTPE;)S&C"CѮbխ*<$_xϊ!6Pq8RE(O }T=:j]vd!l-""&;ƟDD˂;AD:kwzGL l1I;%MPP\ji͝ b>Gį|77iO|g>m`_(\ɵ""b%?qQbc.bj&SvNu"bge= "f1vh^j=`zzNS=l~,Q]|֒^phe`?:GpmbU-ED+hxA_Asn?*((vU93=-8ZkKI"ԩoo3os;UR毃FNqv\q"b%?sED\jm$"M*Fl%N zY;E\-zm,0zi7e?Nnll{JNMgl폮WG.M.ƨQ6BM/Dlq◚0O8 ۈ+b}<%">3^3Għ"I5z󷢈յv(vTW"bIEL[_>+Y"(; """f{"^CSO}u"""SeZ&3m;Plea s,8qnʮlx^{EYLVsg5ibE|&b H}UhKbw """"ZEkX5(WRx:7ŋZD=(bE맢F''h/XJEfxM;%KzUD S짃]'Tb]43oS{}¢fn1Vۆ[7+5uWqm&b 3Z[,hcmEeD1΍A{WP/"""""""k[E]DLb*~-""e[-u C2^#SK񅿘*"v]+(Y̿D ζ  )(9Z쫩m-"""&Y( mGlgJDkEfkuJus|6*ns PQphK[˦vrzAQs"F)X/U9"""""mJYDs?qjkt&&bEDDDğh˱b((Z"" '邂]=EDJ򚈈-V"ԶE5Vv c,҆"im+"b1.pOCUbJ("C:ש.5VIK;f55~j],1\jc_V zuqQ*1HYAS]5ws;UT."""Ms顤4FYgcĎJ )"";i4ѓcew?vl e]e8Dm\_cctԟEu\ py"&V+*UD^t5ED7FYKsF^_ebI s/蠚)X""&8xKjjc1EA8%T<*&hh DA.b Ռjm]g3}Vu"""n~a+9\LΞN0A۶E!1bJSd_owM214/7""-IrEDDDu-^u* [׫,bGtFI"Pv^ua65WqXBs(PDEJpe9Rw_Yb q!M""&UAkˈDW6QTU,+1YrX;s;:+i=+3mYhQo+1D.qeDģ̊ӼdADDtj,"Wz(bO s\j >;*9@\m׉ M1ZVr"I">S=*bSۛkYi qcbE_k!f[AŎ"z)R5fcodgߢcG"c/RDNs'"Wtb*@{M!s_[BrO]`#ʺWD]nD|aݴSQkF(h^_ek_ۭ'b'H J {ikb?%sEDDDD ^ܺfxbڛ'VFb<"ŋ]$nT򩈗ğ(3*MlrXއ""""ћnqTOdWw_yAVyhO"&.uEZɽ"b-E5wEDD4B/%5>pZZMDDD{O{~nnqN2*[,1FSDܣԹܛvTޢ^b<"eK+SDD̲K5WxRXYĥG<%59jdzXi"&k[G$hLX@"Ӗe*""oum`y 1JY{ %Ctjb#VCD<J; /駉f8IQo>rT 0Ӣvs{PVCm#"y""5jU UVcmu s'Eħ{k{PM+vV\%!-#.OMnUۿDDTQ$ "Q0--3γ.K8SDD,+9\Ǯ_+GJ!II;%5QoIM 3xܮv6Z4!a1- P߬"Zx.%NK?qEԛ"""fV1Vjܬɮ6Ed'(|_ -fK]ʖ7+Y,]#""QEDcYwTBs7XAUkaZ;X-<))GDde/(%WrNYFS˛"vl("""q3ڛ.QCUEr &t [Vs:]>}""b,Xq֖hl#qkE 5/\.b_DPK4zWWOӔ+_ϔXՋ8O{XZSG8@juLKo9Wt38[YLѪ"PgEL3XAb^_KjpMwk"(g:DsT 񱂢ESwg|eDDܫǖ~kojb)ESrE\;an7/f:]ipE8+vh| "wpoA9kƈ86)) )F@DDCDPZyɑ]#F5cs?swdüUmbKU*𹈸N1ՖSzך~"m3Y<ʜ{Eܡ)!~U<+},JuwU="M+Rhm`fkWUu˺(>1NK^:YAٚPkD14[(kUTe{O= hg`M3+8" ""&ZP;;(nuq @_&O;W_V;EVTtfa5v szSqJS'"btPשּׁ跾rZT*NRk bg u6Nt}-^NԘ$qZ8[Q}F[Q eD%48]\1M9Cܩڣ"^Phoꦡ|*1* tqUCh.["b+-) \DDd-cuԴ^n]i ZDx&Jn++ZV񈲅N+[}V4=FCmS̰DS5^O(G\y5%S3qA"Ӓ!\."՟Eey\Qpquqz1ʪiuS Qv/2U9+M6P'"jMpY-מQ'"ܮ^7Fk>TZeu+VVTmT{Ull8[n}3YnQkWrn`|.՜D TtX^UheNJi4d1ùbm3+BmZc~i#(f!nUSb#uP7nT RW&'}9ׇ"""X%'"P-"XEQ`1"JS,#tZ]ɂohoY\n6Ro b>TuC-Y\fU0JVhe1DWzOYj/j-;.[7#Bo""GC"b(FDĶz=]&G1Պ '[ޱ""b5%;gs}!״(%;StUxDK6լ}}:JD줵/P;Zqƪ6e;^ƿ¾:G|au|;Ҋ4CDMIU3LDܩ NS\g'WJ.*ٗ"")MZ+v^k%)%-֒CħODAkV^R51]{MYGlbma1z)ZXZkYУb^*q2FN|*ƛ&&YRт+"b-)(Ym׊?X8ZTcTz8AK.j"qlv&^t 7YvQq9w4φj\{>8EQ3MqYnet+(ZčFQ]:к JvqYv2ĩ*mJz"vђ,bSġH-XMD &Ε2 "TiMpUz41MSjmmw;j=p+YՑY#%']YZk'q{DIAmΚ1b)3Qefզl?dGcx_~jSEU"nm)"~9׉8Rx-n""blczjhCD{[NA[U{hݼ#@%|-Smf]|hZTZv5zFP[OIID^.j榋8AEDKIwmsuqt5?Zb em?bJvqbV1XCJZvyk誱"TV;oYRPO+;XO<*[Q%bK DDin+mms vDU|?4O*1}(jɾb 1 ʺ+k^7J.q t/E\ 3-; !'k qΧ񬛵խbh;[PI/>.iڵbOeI ZNxPK.imc*63'3tPT1ŒfSh(2XDD_4XăVNjS1Q_%ۋ8qK:zD+*9K|eˊ\KhnVW@lj̶"SE^QS}]"N5[DDlFOxKAɂV6' "R61 gYZO -RW0ZRS:/,?̙jCĉJ՘|3ANEDj-Q&狟]_ϔ2J<ʜ-ּ7թzVYˎ1PSk 62D9OK Jg >6@bM''3ڛ!""R3-A禈3N"3g:XKNgjE4'"iMKĢ2YDe]&PuUPtay """[:YAW+b֫q= v΅ՙJv1Qsb iIDDew1RSN+&(hhiks=!.MWV"VuEDDnnX~6="֪q _M"b/b_-['"b-XEKn5V0L\hSm#"c>/Ui]=-,Uzǘgl%""bmO<)e?VeUtZpGxDę/bc"גįuqVs{mcEWcLjv.)9U7V}XDDĆe<(""FZu)6DǦU4+buc,X/Kh^_i^b_] b ' %\b(hDD~9-mP{tu59̹L?ŧ{5CDız2롇GDDܩij_ED_i"Լ"1Fby_+xSD\hn]lg%7pfvzqr"">^C 1XW^,$kœƊ8\ӎi"U'9on^PQm߿OLKNQg!e J9R.""Ҝu0MDmd_vJNRgAs ""b{PDD__یr^fq\%גg[Wĵx}VpDDߩ5]|!j ]%]""&M[P'"" fn觀ߋ] }L1Q]&boժ,z'R N]z"@hi qxDcG8c~b;=ED;ZDLД_.n a E]l/`nNDDܫ)]|$[BƋL[,5CQ'ω'UH|,."~~d*?qʆxN7@Dܭ[ Ega#b9eϷ&T'sjEm8D6qD|fs۟peF:XZ_c裿L@ŭ"a CpG:KD/tE'""sOTFē. YGz(VDDsR5k9V Ԝ?+*^h]o?JYWC+4ojM1I!"BhQ}O"";֯lun1ݚbS3-^ m~̳"Y8G""WEL63Z.b{$FqTT""E5sZq (Yj;@Db5ݷbv*U;SenLD~^;HDDܠZ|%-kX^C)PPvTK_jJwQR""4">^k@Y;׊^KGCg]CM.6]8u"EܪβN].""R"Zq`fKJz<+XwCj[?X jh}m,\;%*Vu+]bw iW[x2A̖2ܑ]/'"kn8WĶ߯}e]|,""vUK ׈56Xiil ESCLjý):JEj>x_DLg1^w%ۚ$"buT# )l`VԉRz:%.>4U'"us[":sk$MYdKqVEе"!vRv5N,dfBėrCXW.bU,.y‡"^E^r^&S4Kq EGw/-bgGߘE<%݌|_Mkږff:53hl=$bI =nFDDDĻ`5eWNw lkQ2Ilӌ5JH?'TU"M:mETyO;JQV5{]|,"M%=!"FYY9zkI"zilG #5An:|Z犈O4'"Ϫl[G٢-""bkl![c[IX[b#;squ0Zq4NvxM D-k/tQǴC{$f\ϋ-)"""""~iK$" p;Mk])"&QeeDt̩*f"YUvƶX+zPDډQvxL;ezU\h_ϻҽe /""""ִՊ ߺzdQt02!'""޴˰Zs:ٹO%)'譱 3I{]G"boVR qzk"":YDDDD9%Ѭ^klc8߾*E[\_U1u=48DQbzqjL*Ela^WTuzYR[m%bq-2;W{ whG CEڢEDD`Wm'(9ХU|JQwlf!7J' [wl&8C|"^Q*-*QCߊ;ԨXXę*b5GZ7Tq_h<%]iv*Sl]M7UWt2CDDL2JDq:M+b\ܧl+'(f]쨏58Gk-`rx<%q* +,t%HQ'=*zRx[?""""v4xIDD mͧ"jo͕&"v[)ZgSs"umF5=Ns4~znyڝ"e-%E,bs(YJ#:(Z6PDDCfStTqIi=L< SQiq߈XԬqv /"b5n*811ޛxMb%RCU1 )mg"~Eܪ`YZJfZCuWxKc#EliwQ*7f{D V5VX_si[ .~GpOE33 ~/nVGXV4CDDpFiyWlmi-K{vɬw̪\ZԽ@DܫeCD R^gltn ~2S}cDcq1Tcg; ^C͝"p{zPA&t[.#5Vpi&sji zWKDYZ7ED}1Qo5[N*bswXDsYw"&Z+vSqt6w(הY/%_XADDB~+LSZݠT5{vY=fO:[)؈();9& } ߊx*B-"+jij`9&򭈈z!by9F V0}1cTxFĕ~ ML%ME\cwX5q{Zg:S"""""޷ JEeq5¦LӲ@[?}EjRSx${XcͼeEoZvEaCcU m 5^/ 1ѮNѾgՈ6jB%] õSTm̨EDD*vw-qZ$cgVQPoS_lf#buo[+9ڛKc[bjM& @+#""Z-ꬡZ\dq=ͨ Ov[xY;FD<`\.iPěZjl]1A[}6q7.2vQ0.">gSQk%E8݌g"""D?DLʊI0n:j2[&hg xYfK ]. o534T@ߘTPYgW2J;C8H[(XY un{SNm6/iކ"""Sn*"""Pa`1ſEDl>9VbWAZh#Rj3̨"5mo z{q*4;#j4S'"AjTxR0;hb{W"Mz-4xP[uV8qfܟDDDDED8ۍF&:]b%J`yzNcC6ZcFZÌRĪqZU}fNqWlvƊuv q&g"bKm6(gnT#ռ'^ь;JDDDO""F:ߩ^zyq ZYt>ϸͱps_}">֌8DD;ӲչX\dkŇ{D(1$WxMI"""b*b}SDl` q:y\DDDD7%"Ō;IDDD:Oiii8 VVMPCEX1^ķV݉;}ۭ'DlF.EtSwĦZ&jc1IuQ޲֊ZhJKZ[v;ˉ>kBjD tەMV4o1D{3<*H1VMq}*b/ZJ'׼o7cq.^Rc=Lwbڎ_hh)|)z 1Q'/EDDDDӵíF`}x"nEA7+"*S+ ZTgk̉&JDDDDDDDDDDıvqy|#"b_ "N43Ϛ%qJ+`^1چ"vRDDDDzLDDDDDi).4DD\j9})(RTp꭪.""k<.7+^yPEDDTx8PDD5TeV6WGn{ ;c1\~=7D+tRq/"U:s}$"t=,i)Ko[Z/cy^DdhhQE|u8="F{[Lp5XnQ Si*8ZDDDT[̆1QCR#"(DzzJ}Jt^֚b/\p(bT4oD,nFw`jl}/GKWxq,-"^;o'#2LDD|*ꈃDg8~"LM CԊAMe+;PxUO?EӹHm/")>冉gLݝZHNlG{ZDDǰj>#""s+UCy8bΕW@H*TPuϩP+>%犈xL3?+D5bE5v8YFĕoYM,睮Vd}0}n_9NU!:xV|eeV-"NvO=fa:OQG eVEڷ>3*lxVKB[Kg=4UOD|w2"15غjTCW`b23In-:+XPBɶ"9Dsl kx@? 7CT8VGEn77NBjҽr,m"֬q8@Cf~3My1{P%;vX^x^kuJEKf*5Wii!# ܬ'q2L͜raj=X_Ce"&kNCMs/mjN[Q{/Tz(UFwEg8[ymwU(*7Z̯wUSj:f2ϊ4(33q8ꢽxEC+rcqSDFyYZU"qm.Yo^xvvqQN5kT.T_D!iܿDLZݬ]E2-L$"bl/EDDķ96:8BDDDDD+d+l.E[MUD,进]nDοDNS4ŗ"ŒiFuTx!QFS mO"""飽:D v\$""""""6^Ĺ򍦊v+P[9v1\D V-uՊҌ!SLrXE|"?Euj"b+3Mݎ[eSe-̸kcnG(W2Ee>5 KQ)XɻR`7(),޷4aED<`?\ܤrOeӯKD{\Wƈ1zKDĢ:jBjjJ:5Q!q9B GS\k!Er,n, z\DD<ז"'PE]|)I߫-hVӲ͈ V:}%[h%%xI2E;1V̎ tJ"NT(aw?5󺈈(GDDL8B:jD{AHuZc8޴Sަ<QK)Zlu(8Ll7;=Dw诩PDDD\̯a͌nbM""Z졛""#bY%'鵑 5VU{7L0m݌SjzEpoeq[[̺ZUb,};[ZxNx JT[c"Pf"&^C':!"b> nW6=}%L&""&ݯZb8Z*uw:sa1bIm)""z%Jz)SDܡD[DD7;nihY顿fvrJ[xXũ]B~QšJZ W*GXܯ5GDD8M2DĞ/61r_ua^8̣VG `_Ee8En:AD U=",e1Z쬭L7+0(*U&JevX+*L1Jʜ "TQ7-&L?k9N8Wc|_78^,%"[91T3|.vsD\7Zf{J:!"2_DD(:"UMi-=c5iH_F1JK1Jk d;P"4k]#i"3NDLRNv~w(hb)jnkW?5WG+y<-"":hhGq D"֊ND2ֹRyN9vvqc==l-zX1ʶʔ4":P@LR`aEDkNb!+i3)k+}jS+j}k5u4^DD|abc@+E u}|n2ur)=GCc!+WE| "տi>fduS41"ܤ_eSgKTt-Lf[_r/,c/(_Zϧ"V ՙGL)[cTƺ;YIHQhS#Mq_%M#,b#5t8h28ch:D~ } "Hs,.':L|b'J Jvq:!bM$LjVB;%ǚ,;kMCE暸VcmD횚Curunr0-4t8K}_j◤k""""hecKۚZHvlq砃:M)bK?VVWfUUh~NQ;n3 한&&$NK*1Ն k8Eq;:(Ko(VVxPom'w-lQ_EDKj^Uzߚ9[xX7(jX$vhoyLnbD;Iq_&qy.FxQn;Dię讠T7xo~m[iejZ 1CMeZ^-U*Ж"@iM(V)Yx9^z,DDD̯:""Kš,jN4Z3+LC7_*,TFt2BT{:):U|fkEfw*BDDScGx :i boݱ~3 5s][FQWBw'[ڃ &qHb y]&kit e4M4+BJ3M00tuDK[XEQyfg7oa*""*v(""nt5c Vu*zlwŃ:+#իi}&M~c7UW&;־2/yWDDEَXOٍ"2˹?f,v%8 b> "b&J3 r)9^pjnE""lsj>lТanZ,7NswE{ݍ=JZ|VDDDEَ""b״m4xq fED4:U{Zks=4莾f^:BDDTN RU-|BW;PlRVh7GX-"^9/wT#;!(БF%""*vd3DD,O,b<^-N"o;n(b5kp|L0A/5__EDTX!"bT/TWiUb~*"lC41ɫ7ȹxvڽPeE?ozX! EDTu$gtcDLז+<,1MWv&kiP1j0WDDEYRQqK*"_WhguK%v6uߖ>)StW5mEDTu<[-"""~`Whwy) 折c֦UkֈngX$"L֠( 8!ꥄcRҬkQ򘈊kog}6֋xɡ ֋Xi+]m[V=JQQ}ȏ&"""""""o'EqfxTGS8/uJ~*PU(7xCDDDDē!1ڑbkի.fAInJ5lwBkl׸r[}SrXdg,vSMlp}i\cjm(++q4ˁ"bÔԹE * 5Xm%ţnvq~`\^)ƹBPخgX~3, +ZmݵvL7W{% n^Z)WҮVXgf!Ba"zjD>5 Fg, ۍ_9~"hkvR RӠj8Q8QDsԛ.+ؚNNծ.7CBa+PP揢>֕bN mj$Ҭ+?$l.7Z mvKMsC ߭mϫ:/(CDnpKL"b-})vVUr˖:,W(l3쭤PϋhrJZǎRsx^_5T5\gh2TM $X Mplulh9ə"8NCE ĥU񆉎7L&lr4X(xǙ).3I1":9z:ǭK̳%tEXtdate:create2020-01-16T19:10:25+00:00@X%tEXtdate:modify2020-01-16T19:10:25+00:005IENDB`qabc-1.8/PreferencesMenu.h0000644000175000017500000000207414167467102013634 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef PREFERENCESMENU_H #define PREFERENCESMENU_H #include #include #include class PreferencesMenu: public QMenu { Q_OBJECT public: PreferencesMenu(QWidget* parent = nullptr); ~PreferencesMenu(); protected slots: void onCompilerActionTriggered(); void onPlayerActionTriggered(); void onSynthActionTriggered(); void onResetActionTriggered(); void onViewerActionTriggered(); void onEditorActionTriggered(); private: QAction compileraction; QAction playeraction; QAction synthaction; QAction resetaction; QAction vieweraction; QAction editoraction; }; #endif qabc-1.8/AbcApplication.h0000644000175000017500000000153714167467102013422 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef ABCAPPLICATION_H #define ABCAPPLICATION_H #include "AbcMainWindow.h" #include "AbcProcess.h" #include class AbcApplication: public QApplication { Q_OBJECT public: AbcApplication(int& argc, char **argv); ~AbcApplication(); void setMainWindow(AbcMainWindow* w); AbcMainWindow *mainWindow(); void openFileNames(const QStringList& fileNames); private: AbcMainWindow *abcmainwindow; }; #endif qabc-1.8/PlayPushButton.h0000644000175000017500000000131414167467102013503 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef PLAYPUSHBUTTON_H #define PLAYPUSHBUTTON_H #include class PlayPushButton: public QPushButton { Q_OBJECT public: PlayPushButton(QWidget* parent = nullptr); ~PlayPushButton(); void flip(); bool isPlay(); private: bool play; }; #endif qabc-1.8/.tmp/0000755000175000017500000000000014167467102011250 5ustar benbenqabc-1.8/ViewWidget.h0000644000175000017500000000134014167467102012617 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef VIEWWIDGET_H #define VIEWWIDGET_H #include "ViewVBoxLayout.h" #include class ViewWidget: public QWidget { Q_OBJECT public: ViewWidget(QWidget* parent = nullptr); ~ViewWidget(); ViewVBoxLayout *viewVBoxLayout(); private: ViewVBoxLayout viewvboxlayout; }; #endif qabc-1.8/MainHBoxLayout.cpp0000644000175000017500000000154714167467103013751 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "MainHBoxLayout.h" MainHBoxLayout::MainHBoxLayout(QWidget* parent) : QHBoxLayout(parent) { addWidget(&edittabwidget); addWidget(&viewwidget); setStretchFactor(&edittabwidget, 2); setStretchFactor(&viewwidget, 1); } MainHBoxLayout::~MainHBoxLayout() { } EditTabWidget *MainHBoxLayout::editTabWidget() { return &edittabwidget; } ViewWidget *MainHBoxLayout::viewWidget() { return &viewwidget; } qabc-1.8/config.h.in0000644000175000017500000000207314167467103012420 0ustar benben#ifndef CONFIG_H #define CONFIG_H #define TARGET \"$$TARGET\" #define PREFIX \"$$PREFIX\" #define VERSION \"$$VERSION\" #define DATADIR \"$$DATADIR\" #define REVISION \"$$REVISION\" #define SETTINGS_DOMAIN \"Herewe\" #define SETTINGS_APP \"QAbc\" #define COMPILER_KEY \"ABC/compiler\" #define ABCM2PS \"/usr/bin/abcm2ps -i -O=\" #define PLAYER_KEY \"ABC/player\" #define ABC2MIDI \"/usr/bin/abc2midi\" #define SYNTH_KEY \"ABC/synth\" #define FLUIDSYNTH \"/usr/bin/fluidsynth --no-shell --audio-driver=alsa /usr/share/sounds/sf2/FluidR3_GM.sf2\" #define VIEWER_KEY \"ABC/viewer\" #define PSVIEWER \"/usr/bin/evince\" #define EDITOR_HIGHLIGHT \"ABC/editor/highlight\" #define EDITOR_BAR_COLOR \"ABC/editor/bar_color\" #define EDITOR_COMMENT_COLOR \"ABC/editor/comment_color\" #define EDITOR_DECORATION_COLOR \"ABC/editor/decoration_color\" #define EDITOR_EXTRAINSTR_COLOR \"ABC/editor/extrainstr_color\" #define EDITOR_GCHORD_COLOR \"ABC/editor/gchord_color\" #define EDITOR_HEADER_COLOR \"ABC/editor/header_color\" #define EDITOR_LYRIC_COLOR \"ABC/editor/lyric_color\" #endif qabc-1.8/editorprefdialog.cpp0000644000175000017500000000763514167467103014435 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "editorprefdialog.h" #include #include #include #include "config.h" #include "settings.h" EditorPrefDialog::EditorPrefDialog(QWidget *parent) : QDialog(parent) { Settings settings; setWindowTitle(tr("Editor settings")); setMinimumSize(400, 320); mainLayout = new QVBoxLayout; bool highlight = settings.value(EDITOR_HIGHLIGHT).toBool(); highlightLabel = new QLabel(tr("Highlight current line")); highlightCheck = new QCheckBox; highlightCheck->setChecked(highlight); highlightLabel->setBuddy(highlightCheck); QHBoxLayout* hbox = new QHBoxLayout; hbox->addWidget(highlightLabel); hbox->addWidget(highlightCheck); mainLayout->addLayout(hbox); /* WARNING: labels, keys, buttons in the same order */ colorLabels << tr("Header color") \ << tr("Comment color") \ << tr("Extra instruction color") \ << tr("Measure bar color") \ << tr("Decoration color") \ << tr("Guitar chord color") \ << tr("Lyric color"); colorKeys << EDITOR_HEADER_COLOR \ << EDITOR_COMMENT_COLOR \ << EDITOR_EXTRAINSTR_COLOR \ << EDITOR_BAR_COLOR \ << EDITOR_DECORATION_COLOR \ << EDITOR_GCHORD_COLOR \ << EDITOR_LYRIC_COLOR; for (int i = 0; i < colorKeys.length(); i++) { QColor color = settings.value(colorKeys.at(i)).toString(); QHBoxLayout* hbox = new QHBoxLayout; QLabel* label = new QLabel(colorLabels.at(i)); QPushButton* butt = new QPushButton; QPalette pal = butt->palette(); pal.setColor(QPalette::Button, color); pal.setColor(QPalette::ButtonText, color); label->setBuddy(butt); butt->setText(QVariant(color).toString()); butt->setStyleSheet("color: " + QVariant(color).toString() + ";"); butt->setPalette(pal); butt->setAutoFillBackground(true); butt->update(); colorButtons.append(butt); connect(butt, &QPushButton::clicked, this, &EditorPrefDialog::onColorButtonClicked); hbox->addWidget(label); hbox->addWidget(butt); mainLayout->addLayout(hbox); } buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); mainLayout->addWidget(buttons); setLayout(mainLayout); } EditorPrefDialog::~EditorPrefDialog() { delete mainLayout; } QColor EditorPrefDialog::getColor(QString key) { int i = colorKeys.indexOf(key); QPushButton* butt = colorButtons.at(i); QPalette pal = butt->palette(); QColor color = pal.color(QPalette::Button); return color; } bool EditorPrefDialog::getHighlight() { return highlightCheck->isChecked(); } void EditorPrefDialog::onColorButtonClicked() { QPushButton* butt = static_cast(sender()); QPalette pal = butt->palette(); QColor color = pal.color(QPalette::Button); QColor choose = QColorDialog::getColor(color, this); if (!choose.isValid()) return; pal.setColor(QPalette::Button, choose); pal.setColor(QPalette::ButtonText, choose); butt->setAutoFillBackground(true); butt->setStyleSheet("color: " + QVariant(choose).toString() + ";"); butt->setPalette(pal); butt->setText(QVariant(choose).toString()); butt->update(); } qabc-1.8/main.cpp0000644000175000017500000000411714167467103012026 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "config.h" #include "AbcApplication.h" #include "AbcMainWindow.h" #include #include #include #include int main(int argc, char** argv) { Q_INIT_RESOURCE(resources); AbcApplication abcapplication(argc, argv); QString locale = QLocale::system().name(); QTranslator qtTranslator; #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) if (qtTranslator.load(QLocale::system(), u"qtbase"_qs, u"_"_qs, QLibraryInfo::path(QLibraryInfo::TranslationsPath))) #else if (qtTranslator.load("qt_" + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) #endif abcapplication.installTranslator(&qtTranslator); QTranslator qabcTranslator; if (qabcTranslator.load(TARGET "_" + locale, "locale")) abcapplication.installTranslator(&qabcTranslator); else if (qabcTranslator.load(TARGET "_" + locale, DATADIR "/" TARGET "/locale")) abcapplication.installTranslator(&qabcTranslator); QCommandLineParser parser; parser.setApplicationDescription("ABC music notation minimal GUI."); parser.addHelpOption(); parser.addVersionOption(); parser.addPositionalArgument("score", QCoreApplication::translate("main", "ABC score file to work on.")); parser.process(abcapplication); AbcMainWindow w; abcapplication.setMainWindow(&w); QString iconpath = QString(DATADIR "/pixmaps/" TARGET ".png"); if (QFileInfo::exists(iconpath)) abcapplication.setWindowIcon(QIcon(iconpath)); const QStringList args = parser.positionalArguments(); if (args.length() > 0) abcapplication.openFileNames(args); return abcapplication.exec(); } qabc-1.8/qabc.yaml0000644000175000017500000000142714167467103012171 0ustar benben--- AbcApplication: AbcMainWindow: ScoreMenu: NewAction: OpenAction: SaveAction: SaveasAction: CloseAction: QuitAction: PreferencesMenu: EditorAction: CompilerAction: ViewerAction: PlayerAction: HelpMenu: AboutAction: AboutqtAction: CentralWidget: MainHBoxLayout: EditTabWidget: EditWidget: EditVBoxLayout: AbcPlainTextEdit: PlayPushButton: RunPushButton: ViewWidget: ViewVBoxLayout: LogWidget: qabc-1.8/EditVBoxLayout.cpp0000644000175000017500000003673714167467103014001 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "EditVBoxLayout.h" #include "AbcApplication.h" #include "PreferencesMenu.h" #include "settings.h" #include #include #include #include EditVBoxLayout::EditVBoxLayout(const QString& fileName, QWidget* parent) : QVBoxLayout(parent), abcplaintextedit(parent), playpushbutton(parent), runpushbutton(parent), hboxlayout(parent), xspinbox(parent), xlabel(parent), fileName(fileName) { setObjectName("EditVBoxLayout:" + fileName); tempFile.setFileTemplate(QDir::tempPath() + QDir::separator() + "qabc-XXXXXX.abc"); xspinbox.setMinimum(1); xlabel.setText(tr("X:")); xlabel.setAlignment(Qt::AlignRight|Qt::AlignVCenter); xlabel.setBuddy(&xspinbox); hboxlayout.addWidget(&xlabel); hboxlayout.addWidget(&xspinbox); hboxlayout.addWidget(&playpushbutton); hboxlayout.addWidget(&runpushbutton); addWidget(&abcplaintextedit); addLayout(&hboxlayout); connect(&xspinbox, SIGNAL(valueChanged(int)), this, SLOT(onXChanged(int))); connect(&abcplaintextedit, &QPlainTextEdit::selectionChanged, this, &EditVBoxLayout::onSelectionChanged); connect(&playpushbutton, SIGNAL(clicked()), this, SLOT(onPlayClicked())); connect(&runpushbutton, &QPushButton::clicked, this, &EditVBoxLayout::onRunClicked); connect(this, &EditVBoxLayout::doExportMIDI, this, &EditVBoxLayout::exportMIDI); connect(this, &EditVBoxLayout::playerFinished, this, &EditVBoxLayout::onPlayFinished); connect(this, &EditVBoxLayout::synthFinished, this, &EditVBoxLayout::onSynthFinished); connect(this, &EditVBoxLayout::compilerFinished, this, &EditVBoxLayout::onCompileFinished); connect(this, &EditVBoxLayout::viewerFinished, this, &EditVBoxLayout::onViewFinished); } EditVBoxLayout::~EditVBoxLayout() { #if 1 /* kill slots could not to be called, so cleanup manually */ QString temp(tempFile.fileName()); temp.replace(QRegularExpression("\\.abc$"), QString::number(xspinbox.value()) + ".mid"); if (QFileInfo::exists(temp)) QDir().remove(temp); temp = tempFile.fileName(); temp.replace(QRegularExpression("\\.abc$"), ".ps"); if (QFileInfo::exists(temp)) QDir().remove(temp); #endif } int EditVBoxLayout::xOfCursor(const QTextCursor& c) { int index = c.selectionStart(); QString all = abcPlainTextEdit()->toPlainText(); int x = 1; int i = 0; QStringList lines = all.split('\n'); /* find last X: before selectionIndex */ for (int l = 0; l < lines.count() && i < index; l++) { i += lines.at(l).count() +1; /* count \n */ if (lines.at(l).startsWith("X:")) { x = lines.at(l).right(1).toInt(); } } return x; } void EditVBoxLayout::onSelectionChanged() { QTextCursor c = abcPlainTextEdit()->textCursor(); if (c.hasSelection()) { selection = c.selectedText(); selectionIndex = c.selectionStart(); } else { selection.clear(); selectionIndex = c.selectionStart(); /* set X spinbox */ int x = xOfCursor(c); xspinbox.setValue(x); } } void EditVBoxLayout::exportMIDI() { QString tosave; if (selection.isEmpty()) { tosave = abcPlainTextEdit()->toPlainText(); } else { QString all = abcPlainTextEdit()->toPlainText(); int i = 0, xl = 0; QStringList lines = all.split('\n'); /* find last X: before selectionIndex */ for (int l = 0; l < lines.count() && i < selectionIndex; l++) { i += lines.at(l).count() +1; /* count \n */ if (lines.at(l).startsWith("X:")) { xspinbox.setValue(lines.at(l).right(1).toInt()); xl = l; /* don't break on first X: continue until selectionIndex */ } } /* construct headers */ for (int j = xl; j < lines.count(); j++) { if (lines.at(j).contains(QRegularExpression("^((%[^\n]*)|([A-Z]:[^\n]+))$"))) { if (lines.at(j).startsWith("%%")) /* ignore MIDI instruction, use basic Piano */ continue; tosave += lines.at(j) + "\n"; } else break; } /* when coming from QTextCursor::selectedText(), LF is replaced by U+2029! */ tosave += selection.replace(QChar::ParagraphSeparator, "\n"); } /* open tempfile to init a name */ tempFile.open(); tempFile.write(tosave.toUtf8()); tempFile.close(); #if 0 int cont; if (filename.isEmpty()) { cont = 1; /* continue to playback */ } else { cont = 0; /* will not play, it's just an export */ } #endif Settings settings; QVariant player = settings.value(PLAYER_KEY); QString program = player.toString(); QStringList argv = program.split(" "); program = argv.at(0); argv.removeAt(0); argv << tempFile.fileName(); argv << QString::number(xspinbox.value()); QFileInfo info(tempFile.fileName()); QDir dir = info.absoluteDir(); spawnPlayer(program, argv, dir); } void EditVBoxLayout::onErrorOccurred(QProcess::ProcessError error, const QString& program, AbcProcess::ProcessType which) { AbcApplication* a = static_cast(qApp); AbcMainWindow* w = a->mainWindow(); LogView* lv = w->mainHBoxLayout()->viewWidget()->viewVBoxLayout()->logView(); switch (error) { case QProcess::FailedToStart: lv->appendHtml("" + tr("Failed to start program: ") + program + "
" + tr("Please check settings.") + "
"); break; default: break; } switch (which) { case AbcProcess::ProcessPlayer: case AbcProcess::ProcessSynth: playpushbutton.flip(); xspinbox.setEnabled(true); break; case AbcProcess::ProcessCompiler: runpushbutton.setEnabled(true); break; case AbcProcess::ProcessViewer: runpushbutton.setText(tr("&View score")); runpushbutton.setEnabled(true); break; default: break; } } AbcPlainTextEdit *EditVBoxLayout::abcPlainTextEdit() { return &abcplaintextedit; } PlayPushButton *EditVBoxLayout::playPushButton() { return &playpushbutton; } RunPushButton *EditVBoxLayout::runPushButton() { return &runpushbutton; } void EditVBoxLayout::setFileName(const QString &fn) { fileName = fn; } void EditVBoxLayout::cleanup() { /* early kill in case we quit the app brutally */ for (int i = 0; i < processlist.length(); i++) processlist.at(i)->kill(); } void EditVBoxLayout::onXChanged(int value) { qDebug() << value; } void EditVBoxLayout::spawnCompiler(const QString &prog, const QStringList& args, const QDir &wrk) { AbcApplication* a = static_cast(qApp); AbcMainWindow* w = a->mainWindow(); w->mainHBoxLayout()->viewWidget()->viewVBoxLayout()->logView()->clear(); return spawnProgram(prog, args, AbcProcess::ProcessCompiler, wrk); } void EditVBoxLayout::spawnViewer(const QString &prog, const QStringList &args, const QDir &wrk) { return spawnProgram(prog, args, AbcProcess::ProcessViewer, wrk); } void EditVBoxLayout::spawnPlayer(const QString& prog, const QStringList &args, const QDir &wrk) { AbcApplication* a = static_cast(qApp); AbcMainWindow *w = a->mainWindow(); w->mainHBoxLayout()->viewWidget()->viewVBoxLayout()->logView()->clear(); return spawnProgram(prog, args, AbcProcess::ProcessPlayer, wrk); } void EditVBoxLayout::spawnSynth(const QString &prog, const QStringList& args, const QDir& wrk) { return spawnProgram(prog, args, AbcProcess::ProcessSynth, wrk); } void EditVBoxLayout::spawnProgram(const QString& prog, const QStringList& args, AbcProcess::ProcessType which, const QDir& wrk) { AbcProcess *process = new AbcProcess(which, this); process->setWorkingDirectory(wrk.absolutePath()); connect(process, QOverload::of(&AbcProcess::errorOccurred), this, &EditVBoxLayout::onErrorOccurred); connect(process, QOverload::of(&AbcProcess::finished), this, &EditVBoxLayout::onProgramFinished); connect(process, &AbcProcess::outputText, this, &EditVBoxLayout::onProgramOutputText); #if 1 connect(process, &AbcProcess::errorText, this, &EditVBoxLayout::onProgramErrorText); #endif processlist.append(process); qDebug() << prog << args; process->start(prog, args); } void EditVBoxLayout::onProgramFinished(int exitCode, QProcess::ExitStatus exitStatus, AbcProcess::ProcessType which) { qDebug() << exitCode << exitStatus; switch (which) { case AbcProcess::ProcessPlayer: emit playerFinished(exitCode); break; case AbcProcess::ProcessCompiler: emit compilerFinished(exitCode); break; case AbcProcess::ProcessSynth: emit synthFinished(exitCode); break; case AbcProcess::ProcessViewer: emit viewerFinished(exitCode); break; case AbcProcess::ProcessUnknown: default: break; } /* delete garbage */ for (int i = 0; i < processlist.length(); i++) { AbcProcess* proc = processlist.at(i); //qDebug() << proc->state(); if (proc->state() == QProcess::NotRunning && proc->exitCode() == exitCode && proc->exitStatus() == exitStatus && proc->which() == which) { disconnect(proc, QOverload::of(&AbcProcess::finished), this, &EditVBoxLayout::onProgramFinished); delete proc; processlist.removeAt(i); } } } void EditVBoxLayout::onProgramOutputText(const QByteArray &text) { AbcApplication* a = static_cast(qApp); AbcMainWindow* w = a->mainWindow(); LogView* lv = w->mainHBoxLayout()->viewWidget()->viewVBoxLayout()->logView(); lv->appendHtml("" + QString::fromUtf8(text).replace("\n", "
") + "
"); } void EditVBoxLayout::onProgramErrorText(const QByteArray &text) { //onProgramOutputText(text); AbcApplication* a = static_cast(qApp); AbcMainWindow* w = a->mainWindow(); LogView* lv = w->mainHBoxLayout()->viewWidget()->viewVBoxLayout()->logView(); lv->appendHtml("" + QString::fromUtf8(text).replace("\n", "
") + "
"); } void EditVBoxLayout::killSynth() { for (int i = 0; i < processlist.length(); i++) { AbcProcess* proc = processlist.at(i); if (proc->state() == QProcess::Running && proc->which() == AbcProcess::ProcessSynth) { #if 0 QString str = QString::fromUtf8(*proc->log()); AbcApplication* a = static_cast(qApp); AbcMainWindow* w = a->mainWindow(); LogView* lv = w->mainHBoxLayout()->viewWidget()->viewVBoxLayout()->logView(); lv->appendPlainText(str); #endif disconnect(proc, QOverload::of(&AbcProcess::finished), this, &EditVBoxLayout::onProgramFinished); delete proc; processlist.removeAt(i); } } } bool EditVBoxLayout::checkViewer() { for (int i = 0; i < processlist.length(); i++) { AbcProcess* proc = processlist.at(i); if (proc->which() == AbcProcess::ProcessViewer) return true; } return false; } void EditVBoxLayout::onPlayClicked() { AbcApplication *a = static_cast(qApp); if (playpushbutton.isPlay()) { a->mainWindow()->statusBar()->showMessage(tr("Generating MIDI for playing.")); playpushbutton.flip(); xspinbox.setEnabled(false); emit doExportMIDI(); } else { a->mainWindow()->statusBar()->showMessage(tr("Stopping synthesis.")); killSynth(); onSynthFinished(0); } } void EditVBoxLayout::onPlayFinished(int exitCode) { qDebug() << "play" << exitCode; AbcApplication *a = static_cast(qApp); if (exitCode) { a->mainWindow()->statusBar()->showMessage(tr("Error during MIDI generation.")); playpushbutton.flip(); xspinbox.setEnabled(true); return; } a->mainWindow()->statusBar()->showMessage(tr("MIDI generation finished.")); Settings settings; QVariant synth = settings.value(SYNTH_KEY); QString program = synth.toString(); QStringList argv = program.split(" "); program = argv.at(0); argv.removeAt(0); QString temp(tempFile.fileName()); argv << (temp.replace(QRegularExpression("\\.abc$"), QString::number(xspinbox.value()) + ".mid")); QFileInfo info(temp); QDir dir = info.absoluteDir(); a->mainWindow()->statusBar()->showMessage(tr("Starting synthesis...")); spawnSynth(program, argv, dir); } void EditVBoxLayout::onSynthFinished(int exitCode) { qDebug() << "synth" << exitCode; AbcApplication *a = static_cast(qApp); a->mainWindow()->statusBar()->showMessage(tr("Synthesis finished.")); int x = xspinbox.value(); QString mid (tempFile.fileName()); mid.replace(QRegularExpression("\\.abc$"), QString::number(x) + ".mid"); QFile::remove(mid); if (!playPushButton()->isPlay()) { playpushbutton.flip(); xspinbox.setEnabled(true); } } void EditVBoxLayout::onRunClicked() { runpushbutton.setEnabled(false); AbcApplication *a = static_cast(qApp); a->mainWindow()->statusBar()->showMessage(tr("Generating score...")); QString tosave = abcPlainTextEdit()->toPlainText(); tempFile.open(); tempFile.write(tosave.toUtf8()); tempFile.close(); Settings settings; QVariant compiler = settings.value(COMPILER_KEY); QString program = compiler.toString(); QStringList argv = program.split(" "); program = argv.at(0); argv.removeAt(0); argv << tempFile.fileName(); QFileInfo info(tempFile.fileName()); QDir dir = info.absoluteDir(); spawnCompiler(program, argv, dir); } void EditVBoxLayout::onCompileFinished(int exitCode) { qDebug() << "compile" << exitCode; runpushbutton.setText(tr("Refresh &view")); runpushbutton.setEnabled(true); AbcApplication *a = static_cast(qApp); if (exitCode < 0 || exitCode > 1) { /* sometimes, abcm2ps returns 1 even on 'success' */ a->mainWindow()->statusBar()->showMessage(tr("Error during score generation.")); return; } a->mainWindow()->statusBar()->showMessage(tr("Score generated.")); if (checkViewer()) return; Settings settings; QVariant synth = settings.value(VIEWER_KEY); QString program = synth.toString(); QStringList argv = program.split(" "); program = argv.at(0); argv.removeAt(0); QString temp(tempFile.fileName()); argv << (temp.replace(QRegularExpression("\\.abc$"), ".ps")); QFileInfo info(temp); QDir dir = info.absoluteDir(); a->mainWindow()->statusBar()->showMessage(tr("Starting viewer...")); spawnViewer(program, argv, dir); } void EditVBoxLayout::onViewFinished(int exitCode) { qDebug() << "viewer" << exitCode; AbcApplication *a = static_cast(qApp); a->mainWindow()->statusBar()->showMessage(tr("Viewer closed.")); Settings settings; QString ps (tempFile.fileName()); ps.replace(QRegularExpression("\\.abc$"), ".ps"); QFile::remove(ps); runpushbutton.setText(tr("&View score")); } qabc-1.8/ViewVBoxLayout.h0000644000175000017500000000142414167467103013454 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef VIEWVBOXLAYOUT_H #define VIEWVBOXLAYOUT_H #include "RunPushButton.h" #include "LogView.h" #include class ViewVBoxLayout: public QVBoxLayout { Q_OBJECT public: ViewVBoxLayout(QWidget* parent = nullptr); ~ViewVBoxLayout(); LogView *logView(); private: LogView logview; QPushButton clearbutton; }; #endif qabc-1.8/HelpMenu.cpp0000644000175000017500000000262014167467103012614 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "AbcApplication.h" #include "HelpMenu.h" #include "config.h" #include HelpMenu::HelpMenu(QWidget* parent) : QMenu(parent) { setTitle(tr("Help")); aboutaction.setText(tr("About")); addAction(&aboutaction); aboutqtaction.setText(tr("About Qt")); addAction(&aboutqtaction); connect(&aboutaction, SIGNAL(triggered()), this, SLOT(onAboutActionTriggered())); connect(&aboutqtaction, SIGNAL(triggered()), this, SLOT(onAboutQtActionTriggered())); } HelpMenu::~HelpMenu() { } void HelpMenu::onAboutActionTriggered() { AbcApplication* a = static_cast(qApp); QMessageBox::about(a->mainWindow(), tr("ABC score editor"), tr("\nQAbc version ") + VERSION + " (" + REVISION + ")\n" +tr( "Copyright © 2020 Benoît Rouits ")); } void HelpMenu::onAboutQtActionTriggered() { AbcApplication* a = static_cast(qApp); QMessageBox::aboutQt(a->mainWindow(), tr("ABC score editor")); } qabc-1.8/LICENSE0000644000175000017500000010451514167467103011406 0ustar benben GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 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 . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . qabc-1.8/PreferencesMenu.cpp0000644000175000017500000001251314167467103014167 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "PreferencesMenu.h" #include "AbcApplication.h" #include "editorprefdialog.h" #include "settings.h" #include #include PreferencesMenu::PreferencesMenu(QWidget* parent) : QMenu(parent) { setTitle(tr("Preferences")); playeraction.setText(tr("MIDI Generator")); addAction(&playeraction); synthaction.setText(tr("MIDI Synthesizer")); addAction(&synthaction); compileraction.setText(tr("Score generator")); addAction(&compileraction); vieweraction.setText(tr("Score viewer")); addAction(&vieweraction); editoraction.setText(tr("Editor settings")); addAction(&editoraction); resetaction.setText(tr("Reset to defaults")); addAction(&resetaction); connect(&compileraction, &QAction::triggered, this, &PreferencesMenu::onCompilerActionTriggered); connect(&playeraction, &QAction::triggered, this, &PreferencesMenu::onPlayerActionTriggered); connect(&synthaction, &QAction::triggered, this, &PreferencesMenu::onSynthActionTriggered); connect(&resetaction, &QAction::triggered, this, &PreferencesMenu::onResetActionTriggered); connect(&vieweraction, &QAction::triggered, this, &PreferencesMenu::onViewerActionTriggered); connect(&editoraction, &QAction::triggered, this, &PreferencesMenu::onEditorActionTriggered); } PreferencesMenu::~PreferencesMenu() { } void PreferencesMenu::onCompilerActionTriggered() { AbcApplication* a = static_cast(qApp); Settings settings; QVariant compiler = settings.value(COMPILER_KEY); bool ok; QString command; if (!compiler.isNull()) command = QInputDialog::getText(a->mainWindow(), tr("Compiler preference"), tr("Compiler:"), QLineEdit::Normal, compiler.toString(), &ok); else command = QInputDialog::getText(a->mainWindow(), tr("Compiler preference"), tr("Compiler:"), QLineEdit::Normal, ABCM2PS, &ok); if (!ok) return; settings.setValue(COMPILER_KEY, command); settings.sync(); } void PreferencesMenu::onPlayerActionTriggered() { AbcApplication* a = static_cast(qApp); Settings settings; QVariant player = settings.value(PLAYER_KEY); bool ok; QString command; if (!player.isNull()) command = QInputDialog::getText(a->mainWindow(), tr("Player preference"), tr("Player:"), QLineEdit::Normal, player.toString(), &ok); else command = QInputDialog::getText(a->mainWindow(), tr("Player preference"), tr("Player:"), QLineEdit::Normal, ABC2MIDI, &ok); if (!ok) return; settings.setValue(PLAYER_KEY, command); settings.sync(); } void PreferencesMenu::onSynthActionTriggered() { AbcApplication* a = static_cast(qApp); Settings settings; QVariant synth = settings.value(SYNTH_KEY); bool ok; QString command; if (!synth.isNull()) command = QInputDialog::getText(a->mainWindow(), tr("Synth preference"), tr("Synth:"), QLineEdit::Normal, synth.toString(), &ok); else command = QInputDialog::getText(a->mainWindow(), tr("Synth preference"), tr("Synth:"), QLineEdit::Normal, FLUIDSYNTH, &ok); if (!ok) return; settings.setValue(SYNTH_KEY, command); settings.sync(); } void PreferencesMenu::onViewerActionTriggered() { AbcApplication* a = static_cast(qApp); Settings settings; QVariant viewer = settings.value(VIEWER_KEY); bool ok; QString command; if (!viewer.isNull()) command = QInputDialog::getText(a->mainWindow(), tr("PS viewer preference"), tr("PS Viewer:"), QLineEdit::Normal, viewer.toString(), &ok); else command = QInputDialog::getText(a->mainWindow(), tr("PS viewer preference"), tr("PS Viewer:"), QLineEdit::Normal, PSVIEWER, &ok); if (!ok) return; settings.setValue(VIEWER_KEY, command); settings.sync(); } void PreferencesMenu::onEditorActionTriggered() { AbcApplication* a = static_cast(qApp); EditorPrefDialog* dialog = new EditorPrefDialog(a->mainWindow()); if (QDialog::Accepted == dialog->exec()) { Settings settings; settings.setValue(EDITOR_HIGHLIGHT, dialog->getHighlight()); settings.setValue(EDITOR_BAR_COLOR, dialog->getColor(EDITOR_BAR_COLOR)); settings.setValue(EDITOR_COMMENT_COLOR, dialog->getColor(EDITOR_COMMENT_COLOR)); settings.setValue(EDITOR_DECORATION_COLOR, dialog->getColor(EDITOR_DECORATION_COLOR)); settings.setValue(EDITOR_EXTRAINSTR_COLOR, dialog->getColor(EDITOR_EXTRAINSTR_COLOR)); settings.setValue(EDITOR_GCHORD_COLOR, dialog->getColor(EDITOR_GCHORD_COLOR)); settings.setValue(EDITOR_HEADER_COLOR, dialog->getColor(EDITOR_HEADER_COLOR)); settings.setValue(EDITOR_LYRIC_COLOR, dialog->getColor(EDITOR_LYRIC_COLOR)); settings.sync(); } delete dialog; } void PreferencesMenu::onResetActionTriggered() { Settings settings; settings.reset(); settings.sync(); } qabc-1.8/EditVBoxLayout.h0000644000175000017500000000536314167467103013435 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef EDITVBOXLAYOUT_H #define EDITVBOXLAYOUT_H #include "RunPushButton.h" #include "PlayPushButton.h" #include "AbcPlainTextEdit.h" #include "AbcProcess.h" #include "AbcTemporaryFile.h" #include #include #include #include class EditVBoxLayout: public QVBoxLayout { Q_OBJECT public: explicit EditVBoxLayout(const QString& fileName, QWidget* parent = nullptr); ~EditVBoxLayout(); AbcPlainTextEdit *abcPlainTextEdit(); PlayPushButton *playPushButton(); RunPushButton *runPushButton(); void setFileName(const QString& fn); void cleanup(); void spawnCompiler(const QString &prog, const QStringList &args, const QDir& wrk); void spawnViewer(const QString &prog, const QStringList &args, const QDir& wrk); void spawnPlayer(const QString &prog, const QStringList& args, const QDir& wrk); void spawnSynth(const QString &prog, const QStringList &args, const QDir& wrk); signals: void compilerFinished(int exitCode); void viewerFinished(int exitCode); void playerFinished(int exitCode); void synthFinished(int exitCode); void doExportMIDI(); protected: void spawnProgram(const QString& prog, const QStringList &args, AbcProcess::ProcessType which, const QDir &wrk); void killSynth(); bool checkViewer(); int xOfCursor(const QTextCursor& c); protected slots: void onXChanged(int value); void onPlayClicked(); /* midi */ void onRunClicked(); /* ps */ void onSelectionChanged(); void exportMIDI(); void onErrorOccurred(QProcess::ProcessError error, const QString& program, AbcProcess::ProcessType); void onProgramFinished(int exitCode, QProcess::ExitStatus exitStatus, AbcProcess::ProcessType); void onProgramOutputText(const QByteArray& text); void onProgramErrorText(const QByteArray& text); void onPlayFinished(int exitCode); void onSynthFinished(int exitCode); void onCompileFinished(int exitCode); void onViewFinished(int exitCode); private: AbcPlainTextEdit abcplaintextedit; PlayPushButton playpushbutton; /* midi */ RunPushButton runpushbutton; /* ps */ QHBoxLayout hboxlayout; QSpinBox xspinbox; QLabel xlabel; QString fileName; AbcTemporaryFile tempFile; QList processlist; QString selection; int selectionIndex; }; #endif qabc-1.8/qabc.png0000644000175000017500000007415414167467103012022 0ustar benbenPNG  IHDRtڙM(@zTXtRaw profile type exifxڭkv:u@@ ϵz='%_VUwZx/_|Nvw*O9_w oo_?w\E }}>&<_|.ɁoEp~7>R{8_V_b.L*_'Xyg-x;ExW†A?6y[~~ޟ2. >89~ey{>{swh~%r{xagˣ-_b*]Ù׸:>p*O˾?XV(| ah?{b 5sPb3>bZϭy?|4x.o__'uIo^Ł[ y&?*'ln]\'KsuG++[g' >&UB(޳Xyw蜀O)Lsp%ZSkm-5x}'=z?6q4(ufgϬ-b+zV]m#k;{wϮ}?éԂ^WNR>2'IgƉsE'@:9UJL:7N#iurչW9'8Nm ;KF״8.|εޗv ^ڽ`FwY;hmg,gUs_+>SOBmoݥ ut_fc!wZ})b?2׸!Dž 5R+Eu{WeQspKWCZY,cx,0Ӈ;'nl-(ͽvCP w@H<ҷv=Kjs՗:s_yJ^3Og!ػy޿Vܜ3YIrf{ (|E6+"#g,={ǻc=N6r-Au?_sYp:;W9g3|gj1r8\lUgNZq^@V)|ꅕ쐙뜜}WE"V PM_% xGV*^BN~w~a?}³+ԂwiͱȞv+IX& )R3[ͪ래W_\~JH]z`Gh\:|Hmv7*VxMF=&p=ͫ0g g$~&$ q'[o/KxP Bsg$x{ӓ!:—3G7'Qv2a~ ޑO,"YH.YK@ⳳmQMAP~rʗfrC4v+/wPβrG' BP^ S\)Rс+uy&G|`%7δ1|S+k"Iw<-pǏ*o;=jB=ōe}*G1S{U9m5<1=@c=Fw`S.i5َ]B]yeLW\x S=S{ tOk4s4%́o9{ue?9=RJ흽 xф,ymsK`[V 8Mw, IҟU @(b-*-U܋n.;e 5beJAb 3 } smt}FԹ6:ry82{ ت+` u!טg|nźcޱHí h#:2N ߲.i+MQ%kcB!Y^&z8}ZCގõ=l5>m%@cν¼#;8`2RΓsrhd`t 1(xYO! 3p9uD'|Ǎ:>G ;uxlvݔ3Xzvnq̈<թ8P^G6G |XY%nC_0Zp@ë[6ŋ` U ĄU4Ë]Ņݱ2i=<:;@ kt=`O\I<`rB}0ll,Na>#JPVvwd\0π_[!H+Ɠb+ ū{7ܸ.@f3=rh6(QF c%9 .u9Lv ա(~Jƒ#B4P1~y96V`'ӹoa7,oqZޘacÔ[@o+9!2m_0>A9:7m.q.b^=.q4pq66 ~w8'tWf0D9x3cr X4 (mT(w#K\+U$ĄeU6J`@(P5!q&>1_GM=C޼(Z|[pm`tkha)^7eDѾэrQ,+ʚq=667p^~^90,!akxt@b&#]RPndq<+= !?߈g3K+akc_DN% k,f]wgB p!ԸS)-yi &i?ˬSF{,U*~qV /SMA;|t-$S5qxCX6/b/Ki&Pr`3ó9 Na"oI3WfdhB7XhNsw~fآ(\ Aw6]‘_pE>Ŏ߸pֺaG=[ "aU{qCqx?6ϦDЩK68lAߣ ?WpŝW)/aڷ6&Br\lEA NXyX!&nV݆\bM>ME&UKWU<(D? "U IS`1l"YqUՂEdFIa6kaqU8 Xd~`4 Pې1++d`]m!;M7`M!^7|"DHZWJr.yrhAx>-*ϕ c%Plmד+Q-!bSD:l䑹^. *īd~peɊst"jJhb]tFR ,z){ TJ@?;]JqO$XH$}ڶ;Hؖ]+(U1c@\rkpB9.xaΠ%$;1 ż[('vDÁ㑠xU^&&9 (sƣѰų"

0VI:NꍫV*gF:;a ǖۖ獒xב-3zNJ{<-1T89.~9ؓo򴗹W9 9bai8h+ QK| 1JᄊG<x.įCh_>"a8&8`;7¾8.9r*&tLJ*1`Ye=y?2X4-%ty* \R.4zYbL9'6ʕ2'7w&  T!BƘvpAYg7c]f|l8K5=_@(P<_1+vk(|(_*J0ࠀiEA3b_+VO(J7zn{+: ĥD>"H}D7'ѽ"U (G(LDo~3=({''~es'_vR4 @'x,*U2OMILh%y)ʱ|l/h}? 0! 0TF}ފWmn~?U患\-9qHTU ]bTZ爐Q^-dAqlS1gnH Mw)#Rӓ ~a ] 0R./{! *qz,@Y> KϊR{'dSW0VP+  o*>"m*"fT  l=U %*@>d@KuO~znFŭzG=ZO Y~4&pZI󭌫W)Wx +fyj*Qdz\勒Vbrf+>I*4V HTHV|BNq>\9uU"$n6f*&nH!+R9%]2Vɽ2e+0,Sh%'G-Ǝ}EU ڑ٪* Ι'n!jOEo`8) ]qJšAUbYtaEbZM^EX(S9U,#t.sB؆7ʷ8h.(˯rOEu@ݙˊbT(*9j`Uq񈴬?bK&((H |R:,FbeA{)XGӊ~8 М[/?qw9x\m9nE,[-7oćbCA|J*FY~8j1$5Ӕ>N?R +Nv ª((E ?VKIjkrc+6X@\I ܲN hip аXapP%fTd~VE1E/!JkGe^R_ ~Ulf]t|• uXcʫ*뷮wJ"|@ XvxTdAk%ͼ:OҀRyl BRnl9GIɠhDMjo0{"yO, cT8scϕt9g eT+㐖=, Eyaj\F Nzgp^ F#wژ7~MqU-wgr;?rb1IeGRϭ.!U6b`O'gyByn@t<W v[~^u:'V% 9,!Y^6WSne&<+{*ŗNJ~'T\HUP1YeU8(F}7TOgu_ ƽbB5T!)!xV u7y)/d` r{P>+Rn(RR 5*$V8P9"lꍘIPmaSS순*jq}kQAc,Z~"x^`$B`J5)(h֦#0}jL5NJ U%:S ~D9S{+Nm ܏jS9**p*~C'=$u"YB`rƻu:LA.L RN 5Rs|Սf[9]Qk$sv#z7>7' ,ʂ0Kx(Z4I ؋Â/ Z-kvKJj5e@8Z0P>Ų E;Xo7,[?0)ph:}vj[5 28*ip"I-0+sYYq*D@ƪ x٤c8a)VѵWc7IdZZz{mf5g*TcZYV\0_lR M$<֞19}{cF|u ~NG2 O ˯#WhXtxnMѩ|'9)/9O۸N0ʴ%HTR8׭+[x*4 fĦfjU,|Gy?f:%Xޮlj-^_[$i&/gvqo\_]Uՠ5KEe':W +8μ^muuKF۾O_e)"X u [n?҈f`JFa"K|-` t_` 64U۩2YA΢p'a˯8N+ *ڬ1GQrKOJ*Fz9Y } WP/<䌯(SŁ8դ&5 ֨ !]P^ uѱAܤh $$хIu%bUYN*cS>ו_]/.v f¾YK%p@?"zjPf!'\0N@UԇVެ(eZN>l[XT7(Lc}.:2B;x"8e+jQ* 38I .#8?|RPBdGe@eb ARtB/J)P8J HQWi o%J]@)E8<`S~$h(xXBWTn5Eo*@_ʿAw<M6⧚ACܿPh@5$[sޠԼ<{Sqca,͌OfT;rUX4+TU\U rG2NqYՎjxƩ "G&]B;+/#qUi2jVz:Q)QU@LU8DQ8Ý Qj+Mxh;J^w1in吺^, ~q ~dV6!}jZZS6%d"pJGt/PX~l7tyF*l>ِ[w(v YE!xXWihv* UD~%-@Tln4\wIMj޳^*VSt QuaVդFGU.kӆlb[ڰ*yzl͕fׂ(?*ܟ',e  tmh 1e7aqZr z"XO0+HTNXīa[>$}:Lj4Wʚ.vjȇSa_[^TZoիKΉ[6q{c* _>X8XA,s_zGHᓭ#{.7 A/^MYp=U>n|rNM# ^Cbk1͗ƙ YKg!{}rcDGteh#*"`Lj[ dMew&gW\k51V9?h8COA` }bVER'J{+!ˆQgԓvN( mvi]'zRԧ^>A,Q7kTQi0[.'a_ uYG26U뚁e?*VH곋|TէΉ)gB1RzXD{E~%!-uoUZ駒O:T ]ܪ`^.Gjlm\TxO ThR:54 y7[QbV-MRd1@p}<Ƙpj/9ܛS=lTzZWu:\'Ow"rh> =5LĶVYH0}4I(ܚJ^Y: sխiDy a5SKI1[mv5%6=:KP]9Xn#%q>P55ZO^ fU,ՈZ5_(s(ڝȦ{> φ3SѭÔ,wtESԱXycxe|Rfw haKK'fxe4UfyF粄h"tq ZOR$؄Iu- t_ZYL&ŵ* ͤ&YZd)ѤdLd ĎkKs8 E?Kk|f~:Upj)zgh&Q6H(@YFV8RE.j xFk4 jsq^au= 1[|ZƚO^Kjie|jZGQ ެeBQ9LJS0* zqL.Xg5 Fi IQžݯvdì# dV:UȤKl̛}b 8 ьk5 Q}fa_@S˄qY\y36 5c[ުBB&T>Nu?u!ow{%UKt\T6ucT;m= 9TWmc,b5kp:UX쭐6ը{ChbWq紨&.+"y5*Zl4S3$Iir?-y4xѦ]y)oB dQwjljG+ƹ>F(u|CT/ %oj:cj85ocDff|ZY͂ 'ʦn!d<%> nWLaѰܢGjS-'I/p'G*Ha]up?'T=_ar_;@#14M`hwQ) KYP|+.wxS7p lM"M94B[PBN5Ys`+)}EuJ(>'!hHUΞqF˗,/5 Q:jt$e&3#CQs-a_f ac7/7sS}]+>h!j p MF V@q糝Omxj)Ka4Y}\<'xTw<W;`3|h&Ɗ_JS[Ϊ-.o|n*g>@ᧆ)lU ؠf{I1֦9W7*+5AɎGՁg=^FPBvn+BR޺4FETt8,@J|Z7lϰn F 3)jӨ9vF2q+ w&t M@ׯcVMhጡ;m~b"Vk͠ɡ[ӣӬMK,F 9a6Tw5@ 7E)䗞i]$),%5vj$]@"*{ J;5bEX,DoVn#޶τGx~G&n;8`ۚ *n"(hTLToK 7kVvN1. 斔H!IJqnXT8Q5B TZn*,ynFݴjIMn՘:[?BIrs*1oDeeruD͡QO=½~,t*9cmm8lag~^S+Vjn&Ыx2v ҄o=}y{}= >7O3#IS^Sp2"8e~dьj0GtM6DRWI7j,j\8LWB|Q<6b`Vm0oDk24o\T A|G%fC++ vp9oƥ6p~f,f]KgJ0Fqlc(;(Uj5hkTK-~T!qZ;kR^P8- [c !6GxӨyx.ر~zpdʨ/E]ƹq2k6[ "{n\mQmUV6W oxS{}R h*?>{Y᷄N6F'O3&em(_6AyӧjyjFiRjǡZΦjDuݪO.m4Ls#񚈾{dL$*"ﺙ`1X 'Zq3g^+^UcFg⇲`#EWT2|@܋Dbќ<>[Ȩ!\ԡ57wa/,QӳDFlg6R@StXTS$$vUI sS|ezgY;շ'NcCTҰQKSy&hƃ`= ʝ*KV "*b `yrM#k*VQLV"4Z!Nfڜݺ=:%D(ykS! WL.p[;$ې,j) qio0Cp K GMN垥ß9B7rcCT[UB@A֩r<u%#Ԙ<,ylrkJL_%kE4_#!hVlg 6nvx͡mecWuϪ #K# %c}>+܌6j*PQPG-g*̡3.*]eN c'HVi'F,yP2^-yQE5{|9I#ދa"*+bx"IUN4Յܾ7z)4eYX#`6mXE:uـ1M%?G2;6l婹5E-u> IJ^I*}u?~|i_Y8=g"\ةfhZ(ֳT _Fie)M_n ~/wrsV%eTVo9WERŌYU][n_Vm;US4}X4੺oկx+osa)^Y͞꼰5},#5Bqh!4'nzzࠞh>opI3j A&reArpGOKAo\qS5&6h7QeydP25A^;*N>uO=}9>Ynx[+O/z@J!+4&qp53.[ `DWYRB3R6 >i:jj j:kW5 =k2ܡVg=z"d C9*!p&!$uJڦ:F؄wvz>R[ao+gz]玭&/U#smn9)0]>hv43o3!c48enu:7:@2V=l.k[Sy"8]+گ1bz_twAfì4JDCޘ8bA"gaeqS0tM$xɕO'j"SڹA2Ae{Þ =AGul׭1oݚ$B<-6׫ּ=RQ-\%Kc.˩Xzry=hBfǗ V)ٞ$lG'?F,&0o1#MֶXm2uDUF: ƟD7g㾏 zR =%¾ibZz(SPZ$_|1_<038 589u|"XQ NΊw}} iS>2M TZB~ #prYMH'%SYf/5V) dyWyj1WZ$gI3rW\pIjI!.k߻@[KzWW*޵X'JJJD%,ck}qld[Iq]r!>!I7[k]1>I5|LX?%Mts]pd#X@5~M9]Xd2?zgn~.DҾ= o!. 199,q T[#@I'˱ȏrݡtK]~Qr+)fJ:ְ{h IOKZ;_bc%Mp~L IIEPrcN#mAr?u$j㉍i%yKXNsFj;GIH:Xlk~({%M>ݓ%Hj{W\"@WҍI=2>IȅaZV~MK$ĪPRRG,񋼜/}B=:w'5k\FϖwxG$/"kAt'/**ꜙId&}y9*n $IEZĿЏQOz͖4Q' iY^N+*[6eVrhɞQI< Z-i17QR}>4X{7Ӎe|翤?4{39Q sOɻ}M,X6.!IKK3 h}Z{yN;n:,55u$ i\Xzƾwq=T\awI?IJ&YkũFJ}J}XЙ.37ƴjI ŝ5$Cq}8'Hj-pcqvco<͑5lF[mJ~؇:I:dgaG<ν"ؗ?2fłk 5jTIwH)cI?YI=bN sW$chTR~QpQ6Pm%=PNҫy9ٟW3$(VIӱ}]RSZZVTT|DztF)CaN~!cAȩVj 4++"&8UG#/'{Qw2f|Jъz J9 77V҄셕;\kO^/R%)))o/)ϻXg5@Rҿv±.ߒby9ٿ5lF^NMU\}/^T; o$n}#rU}Ik+** !At ^p=aZ&&.1UucXYR#V4[7IO&MckIP~7-p PZ0:3cTtA6/h-717 )_AIMnzp _ϰT"&Xqy]ҢbgK,r$]d cBopPv60/'xOtʑVRRNa1ٞ3]m>yrIGiywq(.l8t*پu;7r#+떩"Xvm^5P24}ϵMo|IL/Sa~c;o&My=rz?|z107q$=h}B;@_e9Z;ɗڌzQha2>kT^^yrren3ZAY@V#7R U7UD1y1H|||k'{aorJ|l}@4^]mDj PqHʶ8D}JY-J3"~)P6V>4~*>82׵x6ᬮ"IYMh0(Aꐹi \PZ~: 4<_)i.(F,~&. 2 ?&2q途LcƘ♐eaf͚K$Պn[ ! ЉAw/TRRr(oar,t Pi6ER>%3qGx\I+Z?TI 8pgJ*wѢG񬡤-q2jʞ HAR7 g?6==}(72*Iv@`Mo%}xa+1z~-9Qvcӎs.>&3-$Lǃ8À:vlC5U<7L)Ǭ7ca%k32CIaqp֦`J*4A.9] |y}7wcb;\泪vp[öX;%$BjtWZnb^LZ;Z{iZŀ—huBC(i1X,D5 U(ſ1/% - e V!qOټ.׏p[2_Mj'U 4Al釵 9# D3jAm(^@fel/&gq`ƲRSSKꋽ*6C&: 6 tw<Ɯc=s%li  6e0-ϒXRrzvHғxﻟR= ΀F&P*2By9r}i_q@c"Iq-FbsIKl:ӏh4:XI|Lriib||WZ;-T9Ь%.,,,`d}{`jNn.!?\gYYY=ֳԗՠ޶KBpcEE QcI|DGX^l}̓;SH[M@~\R1R&c0ZBl&c2I!Q"e! V~@}R! e^=ؖ ᾛ# IRn~A;i8_AEEEM| o&vARVV6$zV F17'chD^\GRYR= 2JtF^;YNUދ+m,}|&3LD(T@d'M{Ƀ!wA]$b9GEpG†zX(K[O:3ggOZ Q" _gی1rc]'asVeeeOzt\ss-$mHIIh4!vDZ_f -jn :RPՄ쐅ccάדBsI!r:@ m;Iul_ ol=f΃&I3֍W_O R"> RdRy{^ 4cQ}] oEv9)M__n_ZKN ieZȴC/9"$~RnkȜ iSu!,i%m4cs1Qs4y'퉫'7W뺯UQoFHIkJ170|VbB g}`u9\cLh4^KIAɩeJz"<rO6\NIrKIz95o~p&U#QST"tZ"%\N{8ȩHU8<(ibU=G;rH"rZK\7!y= >*7 cdd(im>7S|<+е8ֺZ.PcU6m˧0Cbuta/sdH~1~cL 9s|c\ƘNӎFʩJx+!$vZH,vuվRth5x>mtY_\+,S!훖-J }q)9V?8=n;^%NTZi?<~mWAr*a!x_='!eQTTTkgMwP-~$z>Ejľ !IJ|i>c~YYY=}@\\wl3oͱrJen4O,Mz[MF&9>6'Ik<[7uF_sOġ 94,Ièvu^~/޺ %V)--7r`e{)\I*--=ZR}cU^`C1rbˍ\x<>Zrջ+#?Šϧcr 6d?#{  AO4m+Ž*,,L)@"DE>["n"dp$=;@ιcNK9\]@yh {}*Xo@ePUdj}[NORw?eӖ76@Z~"iaVVYƘs}PHeT⏫.W5!icL/< ޞx~ s3ru{Zk߫ʵȦoG_42\Jr1”|D\(4=7Jn(J`a+S]ڎYr֙lA1&d0q9 is+ MKK{kCbX]5rƺ%} ~BKBri~FH_ҡr:ӹCZC3 g٩.Lb2^`K9 i8pxɹvwA5h;`7־rD."Ш '1'eƘ~XI[SSSj2%~M~ 555srj=JX-t߱51}{شAG(O>y,͑ uvע&{`/ŷp͵~}HL *thqqq_kdIm1Ƙ$RVVvFUZ[v.:9k\z٨>\d/\@#^I,X%}T%/ĵOEAIUg9IPv՚[1B!8c̅YYY'}SH#UXDJ11hY{%ǪCdw;kvI7(mDž6֧ 7ܾyekov':%%%Vgs `o/H0q>*!v@vE:teq8EnC Ps-~7Qq"i11Fc̕X|)7*ZlOb[k'XkR{=,S[,}X/¥31[+gaW91XƘ*/aygԅw{; Cmx1rz r?cc.MyKQ,t!V⎡?1Ʒ9OkPg9K;)mÀrZSckxp=՘Y%g5:/WB"\Xp8jC m(p4$ m{&g..//k-C_Uz;rdOx1xJjjp{毵ħ(5G U+;Qιݒ7N Nh+IcAVr4IRj5Z[<Elm\w{=(=XXrvr}l~l_cIey9oJz` <܂4% ' Xo#mAmQ/Ej_#G(7D f $byBgx7x yM- &M8{{싩=b^*tW5"9y9_a3P?䞇@O .yYKp26Bϻ`Ez 1_J-fc[tJcGfXk'Yk]_+..kyX*MPyI(H6T'(Kuĵmll>KzV2 X]S/`^uoDvK0Y(Nc\tWףMJsbȬLcKI1ɣK=I &b15~h`(+\*9N!CO }yF z!ԇ)ua[sC]IƘ0*q{3r޸ϸM(ý|&Kyn{911=Ҙ7Z3oDZ12 ؙ| &Lڋ=}@9XR 2㦯/@m^lM[tۄ}"fPIDAT UhɨQ:$#s8U\}p[o\l%6:X ۟YF؝l%-'DZ4=hw+g3$n<_ Zk-RlJ2۱ dR@1Y] ?aEztDQp~L8P6WʛWpQi/~i9_6ajYYY="@ tH8ǘ@,dTe7&PwK!!ropYP;q_AH437jfȳf7FpEs%10?cQ}$lW(`'D7-?"!XyIFB&IOOF&#~ ;^]:rfx w dO.|6v{T;&Qո$g)g$5\+-^"]Ȅn ty G5pVRMA:!gɼ*\nDڗp% +,,*oB~">~Ykդ63s xs Z`6Jr3<@ׂ2%3 K*Eg+(xL,Ҏ9Ėw$u"Bm-)iO pT|S  ;m% 9|ލ?Y >h2v=Z{ # ۯ4QCM6;RHAijPVVvRRH$]񺴴Lu9.TRes{\N1hc?h[ ĕ![T7$UѹWWq!V8W"೴R>S6~ĒZѠ=;hNǠGl"M2)U sZ4ŏO!U=1eK0\fiʱH$r}K_n~1?J,dyw"&pc{hQ3qՠJR,Z{2'*>6WֱsJ{[z)tc72W&<"M4OW0˾-}P K*ђBRy9`qn:SOnm;Y苳@kxvn'E'֥n/P*ڬȤw3\sL"Vxsgh mO~Y#gP(3m/xi+SʼYN^*x5 ʕx f7Ào#\#)#++cLwv1`nx>rzsjF=MҭYYY13X륒֬ib ҍFOJj_pG+r=𽬬(/6 s= IJ8T8PRR9,ߑcg0H 1|̿4jA>}֛t^Dw_?x]rJR,+c 9.7Yw?,s..q;pȤwfxPX$_pvIwJg9SeyZZҖyaʺy1. CrzZ(r VmF٩GQQQY7x܃_`48ϒ$Ke9K25K)Jl;ق=++((辻CcTϷiCu. mg ,iS?_NUIS:o9Dt=1sL] .i2f㝥w@4<+&HDG.ݹ=vgh9aw[:8\҂4V{/_[R D˃Ksin1s*ݭ53/.Ƶq1V2UAHvp4J+71Zk. ɩo^\ A\KT#Jfn'tq|@׃4(iVլ‹EfSR,|LN_V]Ҫ[9X& f0[-5Hm;5ʄz1Y9g1QIՇ1fGY]y*0gPU("񽞣Bo_ӄ4m=WB>CwSx6HXĵ,;Bm;reee ?~#|h88(NLi0YY?rxQ 6DCʁk@E+t+7yp^q\~Z{ Qd1f~4H}Į+` 3pŸ%]RE흼4&S΂řzc_Yf~T*aŸ= =iuW&s3UƘ!xpVPxq٠Įڀ+Kȳ>A t,5Ɗj*Vh |6sK^3Z# %$=T;׸ɤ1輵# V?7jF}ga|eX$/Xky7k. `D[-oE;7 ;cثi @q9"%@S&r3iKs;LNw)V/8*2~}Z#^I@r^U1 2eZ;)D;IZ{ɞ(Bǹ}pB+vA;_Tm+)O?emq{osk /jJ^a\^N:`/A3 ctspii6+^J y^Ę5PkrJp/I0/''V.+q5 شc;xPjՀ#jOQF?%x2S^NɶXM$v5E-v׸wDV2ۃrm-Isw{L%K{ga?spoqGv$茓m.'*לIJKL}d.J'Jn18d 93>htPߒ҉:J9>isWK-ѩ'AS5ƜD0 z rs $f}(ڀ'/QO"yB> l0KzJ{1.q]jGWH@⽽H SQ"Ћ`ne0/Z1rqG+ƯqW b u RGлNM6텸{ܮD $̶E@8ԁK}mO3yN@O9MKEp.;t%Vabc34q/m>s*ޮPnMF6HLOTb)n9c/TPnny=^8T2AmC{@#30=KAq7Z#XDZ 3`Y7]VNkrM_Y\DZZ 9EZ rZ9 hk8~>϶fIENDB`qabc-1.8/qabc.desktop0000644000175000017500000000061314167467103012674 0ustar benben[Desktop Entry] Encoding=UTF-8 Name=QAbc Name[fr]=QAbc GenericName=ABC music notation minimal graphical interface GenericName[fr]=Interface graphique minimale de notation musicale ABC Keywords=music;score;notation;tune;gig;jam Keywords[fr]=musique;partition;notation;morceau;concert;jam Exec=qabc %f Icon=qabc Terminal=false Type=Application Categories=AudioVideo; MimeType=application/vnd.abc; qabc-1.8/ScoreMenu.cpp0000644000175000017500000002044514167467103013004 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "ScoreMenu.h" #include "AbcApplication.h" #include "AbcPlainTextEdit.h" #include "EditTabWidget.h" #include "EditWidget.h" #include "settings.h" #include #include #include #include #include ScoreMenu::ScoreMenu(QWidget* parent) : QMenu(parent) { setTitle(tr("Score")); newaction.setShortcut(QKeySequence(QKeySequence::New)); newaction.setText(tr("New")); addAction(&newaction); openaction.setShortcut(QKeySequence(QKeySequence::Open)); openaction.setText(tr("Open")); addAction(&openaction); for (int i = 0; i < MaxRecentFiles; ++i) { recentFileActs[i] = new QAction(this); recentFileActs[i]->setVisible(false); connect(recentFileActs[i], &QAction::triggered, this, &ScoreMenu::onOpenRecentActionTriggered); } QMenu* sub = addMenu(tr("Recently opened")); for (int i = 0; i < MaxRecentFiles; ++i) sub->addAction(recentFileActs[i]); updateRecentFileActions(); saveaction.setShortcut(QKeySequence(QKeySequence::Save)); saveaction.setText(tr("Save")); addAction(&saveaction); saveasaction.setText(tr("Save as")); addAction(&saveasaction); closeaction.setShortcut(QKeySequence(QKeySequence::Close)); closeaction.setText(tr("Close")); addAction(&closeaction); quitaction.setShortcut(QKeySequence(QKeySequence::Quit)); quitaction.setText(tr("Quit")); addAction(&quitaction); connect(&quitaction, SIGNAL(triggered()), this, SLOT(onQuitActionTriggered())); connect(&openaction, SIGNAL(triggered()), this, SLOT(onOpenActionTriggered())); connect(&saveaction, SIGNAL(triggered()), this, SLOT(onSaveActionTriggered())); connect(&saveasaction, SIGNAL(triggered()), this, SLOT(onSaveAsActionTriggered())); connect(&closeaction, SIGNAL(triggered()), this, SLOT(onCloseActionTriggered())); connect(&newaction, SIGNAL(triggered()), this, SLOT(onNewActionTriggered())); } ScoreMenu::~ScoreMenu() { } QMessageBox::StandardButton ScoreMenu::gracefulQuit() { AbcApplication* a = static_cast(qApp); EditTabWidget* tabs = a->mainWindow()->mainHBoxLayout()->editTabWidget(); int unsaved= 0; for (int i = 0; i < tabs->editWidgetList()->length(); i++) { if (!tabs->editWidgetList()->at(i)->editVBoxLayout()->abcPlainTextEdit()->isSaved()) unsaved++; } if (unsaved && QMessageBox::StandardButton::No == QMessageBox::question(a->mainWindow(), tr("Really quit?"), QString::number(unsaved) + tr(" score(s) not saved.\nDo you want to quit anyway?"))) return QMessageBox::StandardButton::No; return QMessageBox::StandardButton::Yes; } void ScoreMenu::onQuitActionTriggered() { AbcApplication* a = static_cast(qApp); EditTabWidget* tabs = a->mainWindow()->mainHBoxLayout()->editTabWidget(); if (QMessageBox::StandardButton::Yes == gracefulQuit()) { tabs->removeTabs(); a->quit(); } } void ScoreMenu::onOpenActionTriggered() { QString home = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); QString fileName = QFileDialog::getOpenFileName(this, tr("Open ABC Score"), home, tr("ABC score (*.abc)")); /* user cancelled */ if (fileName.isEmpty()) return; loadFile(fileName); } QString ScoreMenu::strippedName(const QString& fullFileName) { return QFileInfo(fullFileName).fileName(); } void ScoreMenu::updateRecentFileActions() { Settings settings; QStringList files = settings.value("recentFileList").toStringList(); int numRecentFiles = qMin(files.size(), (int)MaxRecentFiles); for (int i = 0; i < numRecentFiles; ++i) { QString text = tr("&%1 %2").arg(i + 1).arg(strippedName(files[i])); recentFileActs[i]->setText(text); recentFileActs[i]->setData(files[i]); recentFileActs[i]->setVisible(true); } for (int j = numRecentFiles; j < MaxRecentFiles; ++j) recentFileActs[j]->setVisible(false); } void ScoreMenu::setRecentFile(const QString& fileName) { Settings settings; QStringList files = settings.value("recentFileList").toStringList(); files.removeAll(fileName); files.prepend(fileName); while (files.size() > MaxRecentFiles) files.removeLast(); settings.setValue("recentFileList", files); updateRecentFileActions(); } bool ScoreMenu::loadFile(const QString& fileName) { AbcApplication* a = static_cast(qApp); AbcMainWindow* w = a->mainWindow(); QFile file(fileName); if (file.open(QFile::ReadOnly | QFile::Text)) { EditTabWidget *edittabs = w->mainHBoxLayout()->editTabWidget(); EditWidget* widget = new EditWidget(fileName, edittabs); AbcPlainTextEdit *edit = widget->editVBoxLayout()->abcPlainTextEdit(); edit->setPlainText(file.readAll()); file.close(); edit->setSaved(); edittabs->addTab(widget); setRecentFile(fileName); return true; } return false; } void ScoreMenu::onOpenRecentActionTriggered() { QAction *action = qobject_cast(sender()); if (action) loadFile(action->data().toString()); } void ScoreMenu::onSaveActionTriggered() { AbcApplication* a = static_cast(qApp); AbcMainWindow* w = a->mainWindow(); EditTabWidget *edittabs = w->mainHBoxLayout()->editTabWidget(); int cur = edittabs->currentIndex(); if (cur < 0) return; QString fileName = (*edittabs->currentEditWidget()->fileName()); if (fileName.isEmpty()) { QMessageBox::warning(this, tr("Warning"), tr("Could not save an untitled ABC score!")); return; } QFile file(fileName); if (file.open(QFile::WriteOnly | QFile::Text)) { AbcApplication* a = static_cast(qApp); EditTabWidget *edittabs = a->mainWindow()->mainHBoxLayout()->editTabWidget(); EditWidget* widget = static_cast(edittabs->currentWidget()); AbcPlainTextEdit *edit = widget->editVBoxLayout()->abcPlainTextEdit(); QString tosave = edit->toPlainText(); file.write(tosave.toUtf8()); file.close(); w->statusBar()->showMessage(tr("Score saved.")); } else { QMessageBox::warning(this, tr("Warning"), tr("Could not save ABC score!")); } } void ScoreMenu::onSaveAsActionTriggered() { AbcApplication* a = static_cast(qApp); AbcMainWindow* w = a->mainWindow(); EditTabWidget *edittabs = w->mainHBoxLayout()->editTabWidget(); int cur = edittabs->currentIndex(); if (cur < 0) return; QString home = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); QString fileName = QFileDialog::getSaveFileName(this, tr("Save ABC score"), home, tr("ABC score (*.abc)")); if (fileName.isEmpty()) return; /* cancelled */ QFileInfo info(fileName); edittabs->setTabText(edittabs->currentIndex(), info.baseName()); edittabs->currentEditWidget()->setFileName(fileName); return onSaveActionTriggered(); } void ScoreMenu::onCloseActionTriggered() { AbcApplication* a = static_cast(qApp); AbcMainWindow* w = a->mainWindow(); EditTabWidget *edittabs = w->mainHBoxLayout()->editTabWidget(); //qDebug() << edittabs->currentIndex(); int cur = edittabs->currentIndex(); if (cur >= 0) edittabs->removeTab(cur); } void ScoreMenu::onNewActionTriggered() { AbcApplication* a = static_cast(qApp); AbcMainWindow* w = a->mainWindow(); EditTabWidget *edittabs = w->mainHBoxLayout()->editTabWidget(); QString empty; EditWidget* swidget = new EditWidget(empty, nullptr); swidget->editVBoxLayout()->abcPlainTextEdit()->setPlainText(NEW_TEMPLATE); edittabs->addTab(swidget); } qabc-1.8/LogView.h0000644000175000017500000000120314167467103012114 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #ifndef PDFWIDGET_H #define PDFWIDGET_H #include class LogView: public QPlainTextEdit { Q_OBJECT public: LogView(QWidget* parent = nullptr); ~LogView(); private: }; #endif qabc-1.8/qabc.pro0000644000175000017500000000353114167467103012025 0ustar benbenQT += core widgets gui TEMPLATE = app TARGET = qabc RESOURCES += resources.qrc DISTFILES += dict.txt gm.txt SOURCES = ScoreMenu.cpp PreferencesMenu.cpp HelpMenu.cpp AbcPlainTextEdit.cpp PlayPushButton.cpp EditVBoxLayout.cpp EditWidget.cpp EditTabWidget.cpp RunPushButton.cpp ViewVBoxLayout.cpp ViewWidget.cpp MainHBoxLayout.cpp AbcMainWindow.cpp AbcApplication.cpp main.cpp \ AbcProcess.cpp \ AbcTemporaryFile.cpp \ LogView.cpp \ editorprefdialog.cpp \ settings.cpp HEADERS = ScoreMenu.h PreferencesMenu.h HelpMenu.h AbcPlainTextEdit.h PlayPushButton.h EditVBoxLayout.h EditWidget.h EditTabWidget.h RunPushButton.h ViewVBoxLayout.h ViewWidget.h MainHBoxLayout.h AbcMainWindow.h AbcApplication.h \ AbcProcess.h \ AbcTemporaryFile.h \ LogView.h \ editorprefdialog.h \ settings.h VERSION = 1.8 REVISION = $$system(git describe --long --tags 2>/dev/null || echo "stable") CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG_OUTPUT isEmpty(PREFIX): PREFIX = /usr/local isEmpty(BINDIR): BINDIR = $$PREFIX/bin isEmpty(DATADIR): DATADIR = $$PREFIX/share config.input = config.h.in config.output = config.h QMAKE_SUBSTITUTES += config isEmpty(QMAKE_LRELEASE):QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease TRANSLATIONS += $${TARGET}_en.ts $${TARGET}_fr.ts LOCALE_DIR = locale updateqm.input = TRANSLATIONS updateqm.output = $$LOCALE_DIR/${QMAKE_FILE_BASE}.qm updateqm.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN} -qm $$LOCALE_DIR/${QMAKE_FILE_BASE}.qm updateqm.CONFIG += no_link target_predeps QMAKE_EXTRA_COMPILERS += updateqm target.path = $$BINDIR translations.path = $$DATADIR/$$TARGET translations.files = $$LOCALE_DIR desktop.path = $$DATADIR/applications desktop.files = $${TARGET}.desktop icon.path = $$DATADIR/pixmaps icon.files = $${TARGET}.png mime.path = $$DATADIR/mime/packages mime.files = application-vnd-abc.xml INSTALLS += target translations desktop icon mime qabc-1.8/AbcTemporaryFile.cpp0000644000175000017500000000100214167467103014260 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "AbcTemporaryFile.h" AbcTemporaryFile::AbcTemporaryFile() { } qabc-1.8/AbcMainWindow.cpp0000644000175000017500000000233614167467103013565 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "AbcMainWindow.h" AbcMainWindow::AbcMainWindow(QWidget* parent) : QMainWindow(parent) { setWindowTitle(tr("QAbc")); menuBar()->addMenu(&scoremenu); menuBar()->addMenu(&preferencesmenu); menuBar()->addMenu(&helpmenu); setCentralWidget(new QWidget(this)); centralWidget()->setLayout(&mainhboxlayout); statusBar()->showMessage(tr("Idle")); setMinimumWidth(800); setMinimumHeight(480); show(); } AbcMainWindow::~AbcMainWindow() { } MainHBoxLayout *AbcMainWindow::mainHBoxLayout() { return &mainhboxlayout; } ScoreMenu *AbcMainWindow::scoreMenu() { return &scoremenu; } void AbcMainWindow::closeEvent(QCloseEvent *event) { if (QMessageBox::StandardButton::Yes == scoremenu.gracefulQuit()) { event->accept(); } else { event->ignore(); } } qabc-1.8/qabc_en.ts0000644000175000017500000003450214167467103012337 0ustar benben AbcMainWindow QAbc Idle EditTabWidget Really close? Current score not saved! Close this score anyway? EditVBoxLayout X: Failed to start program: Please check settings. Generating MIDI for playing. Stopping synthesis. Error during MIDI generation. MIDI generation finished. Starting synthesis... Synthesis finished. Generating score... Refresh &view Error during score generation. Score generated. Starting viewer... Viewer closed. &View score EditorPrefDialog Editor settings Highlight current line Header color Comment color Extra instruction color Measure bar color Decoration color Guitar chord color Lyric color HelpMenu Help About About Qt ABC score editor Abc score editor Copyright © 2020 Benoît Rouits <brouits@free.fr> QAbc version PlayPushButton &Play Play Sto&p PreferencesMenu Preferences MIDI Generator MIDI Synthesizer Score generator Score viewer Viewer Editor settings Reset to defaults Compiler preference Compiler: PS viewer preference PS Viewer: Player preference Player: Synth preference Synth: RunPushButton &View score Generate score ScoreMenu Score New Open Save Save as Close Quit Really quit? score(s) not saved. Do you want to quit anyway? Open ABC Score ABC score (*.abc) Warning Could not save an untitled ABC score! Score saved. Save ABC score Could not save ABC score! ViewVBoxLayout Clear log main ABC score file to work on. qabc-1.8/README.md0000644000175000017500000000161614167467103011656 0ustar benben# QAbc ABC music notation minimal GUI. ## Dependencies QAbc uses third-party softwares to generate MIDI, AUDIO, and PostScript files. Without them, QAbc would be very poor (only a little fancy text editor). So, please install them: - abc2midi (CLI) - fluidsynth (CLI) - abcm2ps (CLI) - Qt 5.x (LIB) ## Screenshot http://brouits.free.fr/images/qabc-shot.png ## Building Just a matter of: ``` $ cd qabc $ qmake -config release $ make # make install (as root) ``` ## Starting Launch `qabc`, type some ABC music in the editor, press `Play` button: you're done! ## Bugs Lots of! ## Colophon This project is (was), as of version 0.1, a one-night project because I wanted to be more comfortable with ABC notation and I could not find a GUI software that could run on my laptop. ## Icon Icon is derived from johnny_automatic (from the Lulu Alphabet, 1867). https://openclipart.org/detail/6264/harp-and-branch qabc-1.8/AbcProcess.cpp0000644000175000017500000000342414167467103013126 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "AbcProcess.h" #include AbcProcess::AbcProcess(ProcessType which, QObject *parent) : QProcess(parent) { type = which; setProcessChannelMode(SeparateChannels); connect(this, QOverload::of(&QProcess::finished), this, &AbcProcess::onFinished); connect(this, &QProcess::errorOccurred, this, &AbcProcess::onErrorOccured); #if 0 connect(this, &QProcess::readyRead, this, &AbcProcess::onOutput); #else connect(this, &QProcess::readyReadStandardOutput, this, &AbcProcess::onStdout); connect(this, &QProcess::readyReadStandardError, this, &AbcProcess::onStderr); #endif } AbcProcess::ProcessType AbcProcess::which() { return type; } QByteArray *AbcProcess::log() { return &output; } #if 0 void AbcProcess::onOutput() { output = readAll(); qDebug() << output; emit outputText(output); } #else void AbcProcess::onStdout() { emit outputText(readAllStandardOutput()); /* while(canReadLine()) { emit outputText(readLine()); } */ } void AbcProcess::onStderr() { emit errorText(readAllStandardError()); } #endif void AbcProcess::onFinished(int exitCode, QProcess::ExitStatus exitStatus) { emit finished(exitCode, exitStatus, type); } void AbcProcess::onErrorOccured(QProcess::ProcessError error) { emit errorOccurred(error, program(), which()); } qabc-1.8/qabc_fr.ts0000644000175000017500000003532214167467103012345 0ustar benben AbcMainWindow QAbc QAbc Idle Rien à faire EditTabWidget Really close? Fermer vraiment ? Current score not saved! Close this score anyway? La partition courante n'est pas enregistrée ! Fermer cette partition quand-même ? EditVBoxLayout X: X: Failed to start program: Impossible de démarrer le programme : Please check settings. Veuillez vérifier les paramètres. Generating MIDI for playing. Génération du MIDI pour jouer. Stopping synthesis. Arrêt de la synthèse. Error during MIDI generation. Erreur pendant la génération du MIDI. MIDI generation finished. Génération du MIDI terminée. Starting synthesis... Démarrage de la synthèse... Synthesis finished. Synthèse terminée. Generating score... Génération de la partition... Refresh &view Rafraîchir la &vue Error during score generation. Erreur pendant la génération de la partition. Score generated. Patition générée. Starting viewer... Démarrage du visualiseur... Viewer closed. Visualiseur fermé. &View score &Voir la partition EditorPrefDialog Editor settings Paramètres de l'éditeur Highlight current line Ligne courante en surbrillance Header color Couleur d'en-tête Comment color Couleur de commentaire Extra instruction color Couleur d' instruction Measure bar color Couleur de barre de mesure Decoration color Couleur de décoration Guitar chord color Couleur d' accord de guitare Lyric color Couleur de parole HelpMenu Help Aide About À propos About Qt À propos de Qt ABC score editor Abc score editor Éditeur de partition ABC Copyright © 2020 Benoît Rouits <brouits@free.fr> Copyright © 2020 Benoît Rouits <brouit@free.fr> QAbc version QAbc version PlayPushButton &Play Play Joue&r Sto&p A&rrêter PreferencesMenu Preferences Préférences MIDI Generator Générateur MIDI MIDI Synthesizer Synthétiseur MIDI Score generator Générateur de partition Score viewer Viewer Visualiseur de partition Editor settings Paramètres de l'éditeur Reset to defaults Remettre à zéro Compiler preference Préférence du compilateur Compiler: Compilateur : PS viewer preference Préférence du visualiseur PS PS Viewer: Visualiseur PS : Player preference Préférence du joueur Player: Joueur : Synth preference Préférence du synthétiseur Synth: Synthétiseur : RunPushButton &View score Generate score &Voir la partition ScoreMenu Score Partition New Nouvelle Open Ouvrir Save Enregistrer Save as Enregistrer sous Close Fermer Quit Quitter Really quit? Quitter vraiment ? score(s) not saved. Do you want to quit anyway? partition(s) non enregistrée(s). Voulez-vous quitter quand-même ? Open ABC Score Ouvrir une partition ABC ABC score (*.abc) Partition ABC (*.abc) Warning Attention Could not save an untitled ABC score! Impossible d'enregistrer une partition ABC sans titre ! Score saved. Partition enregistrée. Save ABC score Enregistrer la partition ABC Could not save ABC score! Impossible d'enregistrer la partition ABC ! ViewVBoxLayout Clear log Nettoyer le log main ABC score file to work on. Partition ABC sur laquelle travailler. qabc-1.8/LogView.cpp0000644000175000017500000000110214167467103012445 0ustar benben// This source code is part of QAbc, a minimal ABC music notation editor. // QAbc is Copyright © 2021 Benoît Rouits . // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // SPDX-License-Identifier: GPL-3.0-or-later #include "LogView.h" LogView::LogView(QWidget* parent) : QPlainTextEdit(parent) { setReadOnly(true); } LogView::~LogView() { }