Commit 5a6f0f6d authored by jhammen's avatar jhammen
Browse files

initial import

parents
*.pro.user
version.h
This diff is collapsed.
# bipscript-ide
\ No newline at end of file
#-------------------------------------------------
#
# Project created by QtCreator 2018-12-23T14:57:28
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = bipscript-ide
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += c++11
QMAKE_CXXFLAGS += -std=c++11
SOURCES += \
main.cpp \
mainwindow.cpp \
editorwidget.cpp \
scriptrun.cpp \
outputwidget.cpp \
projectlist.cpp \
projectsdialog.cpp \
synhighlighter.cpp
HEADERS += \
mainwindow.h \
editorwidget.h \
scriptrun.h \
outputwidget.h \
style.h \
projectlist.h \
foldertreeitem.h \
namedfile.h \
projectsdialog.h \
position.h \
synhighlighter.h \
version.h
unix {
INCLUDEPATH += $$PWD/jack
HEADERS += \
jack/audiotimerservice.h
SOURCES += \
jack/audioengine.cpp \
jack/audiotimerservice.cpp
LIBS += -ljack
}
FORMS += \
mainwindow.ui \
outputwidget.ui \
projectsdialog.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /usr/bin/
!isEmpty(target.path): INSTALLS += target
/*
* This file is part of Bipscript-IDE.
*
* Bipscript-IDE 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.
*
* Bipscript-IDE 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 Bipscript-IDE. If not, see <http://www.gnu.org/licenses/>.
*/
#include "editorwidget.h"
#include "synhighlighter.h"
#include <Qt>
#include <QApplication>
#include <QTextStream>
#include <QMessageBox>
#include <QPainter>
#include <QTextBlock>
EditorWidget::EditorWidget(NamedFile &file)
: mfile(file),
undoable(false),
redoable(false)
{
setLineWrapMode(QPlainTextEdit::NoWrap);
// font
QFont font;
font.setFamily("monospace");
font.setStyleHint(QFont::Monospace);
font.setFixedPitch(true);
font.setPointSize(12);
QFontMetrics metrics(font);
// TODO: tab width configurable
setTabStopWidth(metrics.width('0') * 4);
setFont(font);
connect(this, SIGNAL(undoAvailable(bool)),
this, SLOT(setUndoable(bool)));
connect(this, SIGNAL(redoAvailable(bool)),
this, SLOT(setRedoable(bool)));
connect(this, SIGNAL(updateRequest(QRect,int)),
this, SLOT(updateInfoStrip(QRect,int)));
connect(document(), SIGNAL(modificationChanged(bool)),
this, SLOT(contentsModified(bool)));
// info-strip for line numbers + markers
infoStrip = new InfoStrip(this);
setViewportMargins(infoStrip->stripWidth(), 0, 0, 0);
// syntax highlighter
new SynHighlighter(document());
}
bool EditorWidget::load()
{
QFile file(mfile.path);
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("Bipscript IDE"), tr("Error opening %1:\n%2")
.arg(mfile.path), file.errorString());
return false;
}
QTextStream in(&file);
QApplication::setOverrideCursor(Qt::WaitCursor);
setPlainText(in.readAll());
QApplication::restoreOverrideCursor();
return true;
}
bool EditorWidget::save()
{
QFile file(mfile.path);
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, tr("Bipscript IDE"), tr("Error saving %1:\n%2.")
.arg(mfile.path), file.errorString());
return false;
}
QTextStream out(&file);
QApplication::setOverrideCursor(Qt::WaitCursor);
out << toPlainText();
QApplication::restoreOverrideCursor();
document()->setModified(false);
return true;
}
void EditorWidget::focusLine(int line, int column)
{
QTextCursor cursor = textCursor();
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, line - 1);
if(column >= document()->findBlock(line).length()) {
cursor.movePosition(QTextCursor::EndOfLine);
} else {
cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, column - 1);
}
setTextCursor(cursor);
setFocus();
}
void EditorWidget::commentSelection()
{
Selection sel = currentSelection();
// uncomment if all lines currently commented
bool comment = false;
for(int i = sel.start; i <= sel.end; i++) {
if(!document()->findBlockByNumber(i).text().startsWith("//")) {
comment = true;
}
}
if(comment) {
prefixLines(sel, "//");
} else {
chopLines(sel, 2);
}
}
void EditorWidget::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_Tab) {
Selection sel = currentSelection();
if(sel.multiline) {
prefixLines(currentSelection(), "\t");
} else {
QPlainTextEdit::keyPressEvent(event);
}
} else if(event->key() == Qt::Key_Backtab) {
Selection sel = currentSelection();
bool tab = true;
for(int i = sel.start; i <= sel.end; i++) {
if(!document()->findBlockByNumber(i).text().startsWith("\t")) {
tab = false;
}
}
if(tab) {
chopLines(currentSelection(), 1);
}
} else {
QPlainTextEdit::keyPressEvent(event);
}
}
Selection EditorWidget::currentSelection()
{
Selection ret;
QTextCursor cursor = textCursor();
QTextBlock startBlock = document()->findBlock(cursor.selectionStart());
ret.start = startBlock.blockNumber();
QTextBlock endBlock = document()->findBlock(cursor.selectionEnd());
ret.end = endBlock.blockNumber();
ret.multiline = false;
if(ret.start != ret.end) {
ret.multiline = true;
// don't include line below selection
if(cursor.selectionEnd() == endBlock.position()) {
ret.end--;
}
}
return ret;
}
void EditorWidget::prefixLines(Selection sel, QString prefix)
{
QTextCursor editCursor(document());
editCursor.beginEditBlock();
for(int i = sel.start; i <= sel.end; i++) {
QTextBlock block = document()->findBlockByNumber(i);
editCursor.setPosition(block.position());
editCursor.insertText(prefix);
}
editCursor.endEditBlock();
// select to beginning of first line
QTextCursor cursor = textCursor();
QTextBlock startBlock = document()->findBlockByNumber(sel.start);
int startPos = startBlock.position();
int endPos = std::max(cursor.position(), cursor.anchor());
cursor.setPosition(startPos);
cursor.setPosition(endPos, QTextCursor::KeepAnchor);
setTextCursor(cursor);
}
void EditorWidget::chopLines(Selection sel, int amount)
{
QTextCursor editCursor(document());
editCursor.beginEditBlock();
for(int i = sel.start; i <= sel.end; i++) {
QTextBlock block = document()->findBlockByNumber(i);
editCursor.setPosition(block.position());
editCursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, amount);
editCursor.removeSelectedText();
}
editCursor.endEditBlock();
}
BlockInfo EditorWidget::topBlock()
{
BlockInfo ret;
QTextBlock block = firstVisibleBlock();
ret.index = block.blockNumber();
ret.top = static_cast<int>(blockBoundingGeometry(block).translated(contentOffset()).top());
return ret;
}
void EditorWidget::resizeEvent(QResizeEvent *e)
{
QPlainTextEdit::resizeEvent(e);
QRect rect = contentsRect();
infoStrip->setGeometry(rect.left(), rect.top(), infoStrip->stripWidth(), rect.height());
}
void EditorWidget::updateInfoStrip(const QRect &rect, int dy)
{
if (dy > 0) {
infoStrip->scroll(0, dy);
} else {
infoStrip->update(0, rect.y(), infoStrip->width(), rect.height());
}
}
void InfoStrip::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
int lineHeight = fontMetrics().height();
BlockInfo blockInfo = editor.topBlock();
int line = blockInfo.index + 1;
int top = blockInfo.top;
QSet<int> &errorLines = editor.allErrors();
while (top < event->rect().bottom() && line <= editor.blockCount()) {
QRect lineRect(paddingSide, top, width() - paddingSide * 2, lineHeight);
// markers
painter.setPen(Qt::red);
if(errorLines.contains(line)) { painter.drawRect(lineRect); }
// line number
QString number = QString::number(line++);
painter.setPen(Qt::black);
painter.drawText(lineRect, Qt::AlignRight, number);
top += fontMetrics().height();
}
}
/*
* This file is part of Bipscript-IDE.
*
* Bipscript-IDE 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.
*
* Bipscript-IDE 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 Bipscript-IDE. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EDITORWIDGET_H
#define EDITORWIDGET_H
#include "namedfile.h"
#include <QPlainTextEdit>
class InfoStrip;
struct BlockInfo
{
int index;
int top;
};
struct Selection
{
int start;
int end;
bool multiline;
};
class EditorWidget : public QPlainTextEdit
{
Q_OBJECT
NamedFile mfile;
bool undoable;
bool redoable;
InfoStrip *infoStrip;
QSet<int> errorLines;
Selection currentSelection();
void chopLines(Selection sel, int amount);
void prefixLines(Selection sel, QString prefix);
public:
EditorWidget(NamedFile &file);
const QString &path() { return mfile.path; }
const QString &name() { return mfile.name; }
bool isDirty() { return document()->isModified(); }
bool isUndoAvailable() { return undoable; }
bool isRedoAvailable() { return redoable; }
bool hasSelection() { return textCursor().hasSelection(); }
bool load();
bool save();
void focusLine(int line, int column = 0);
void commentSelection();
void moveFile(NamedFile &file) { mfile = file; }
// error markers
void addError(int line) { errorLines.insert(line); }
QSet<int> &allErrors() { return errorLines; }
// for info strip
BlockInfo topBlock();
void keyPressEvent(QKeyEvent *e) override;
public slots:
void setUndoable(bool b) { undoable = b; }
void setRedoable(bool b) { redoable = b; }
protected:
void resizeEvent(QResizeEvent *e) override;
private slots:
void updateInfoStrip(const QRect &rect, int dy);
void contentsModified(bool) { errorLines.clear(); }
};
class InfoStrip : public QWidget
{
int paddingSide = 5;
EditorWidget &editor;
protected:
void paintEvent(QPaintEvent *event) override;
public:
InfoStrip(EditorWidget *parent) :
QWidget(parent),
editor(*parent) {}
QSize sizeHint() const override {
return QSize(stripWidth(), 0);
}
int stripWidth() const {
return fontMetrics().width(QLatin1String("999")) + paddingSide * 2;
}
};
#endif // EDITORWIDGET_H
/*
* This file is part of Bipscript-IDE.
*
* Bipscript-IDE 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.
*
* Bipscript-IDE 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 Bipscript-IDE. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FOLDERTREEITEM_H
#define FOLDERTREEITEM_H
#include "namedfile.h"
#include <QTreeWidgetItem>
class FolderTreeItem : public QTreeWidgetItem
{
NamedFile mfile;
public:
FolderTreeItem(QTreeWidgetItem *parent, QString name, QString path) :
QTreeWidgetItem(parent, QStringList(name), QTreeWidgetItem::UserType),
mfile(name, path)
{}
NamedFile &file() { return mfile; }
};
#endif // FOLDERTREEITEM_H
icon.png

9.78 KB

/*
* This file is part of Bipscript-IDE.
*
* Bipscript-IDE 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.
*
* Bipscript-IDE 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 Bipscript-IDE. If not, see <http://www.gnu.org/licenses/>.
*/
#include "audioengine.h"
void jackInfoShutdownCallback(void *ae)
{
static_cast<AudioEngine*>(ae)->onShutdown();
}
AudioEngine::AudioEngine()
{
thread.start();
QObject::connect(&thread, SIGNAL (finished()), &thread, SLOT (deleteLater()));
}
AudioConfiguration AudioEngine::connect()
{
jack_options_t options = JackNullOption;
jack_status_t status;
client = jack_client_open ("Bipscript IDE", options, &status, nullptr);
jack_on_shutdown(client, &jackInfoShutdownCallback, this);
AudioConfiguration ret;
ret.framesPerSecond = jack_get_sample_rate(client);
return ret;
}
void AudioEngine::disconnect()
{
jack_client_close(client);
}
void AudioEngine::transportStart()
{
jack_transport_start(client);
}
void AudioEngine::transportStop()
{
jack_transport_stop(client);
}
void AudioEngine::reposition(uint frame)
{
jack_transport_locate(client, frame);
}
AudioTimerService *AudioEngine::timerService()
{
timer = new AudioTimerService(client);
timer->moveToThread(&thread);
timer->start();
return timer;
}
/*
* This file is part of Bipscript-IDE.
*
* Bipscript-IDE 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.
*
* Bipscript-IDE 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 Bipscript-IDE. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AUDIOENGINE_H
#define AUDIOENGINE_H
#include "audiotimerservice.h"
#include <jack/jack.h>
#include <QThread>
struct AudioConfiguration
{
unsigned int framesPerSecond;
};
class AudioEngine
{
jack_client_t *client;
QThread thread;
AudioTimerService *timer;
AudioEngine();
public:
static AudioEngine &instance() {
static AudioEngine * instance = nullptr;
if (instance == nullptr) {
instance = new AudioEngine();
}
return *instance;
}
AudioConfiguration connect();
void disconnect();
void transportStart();
void transportStop();
void reposition(uint frame);
void onShutdown() { if(timer) { timer->stop();} }
AudioTimerService *timerService();
};
#endif // AUDIOENGINE_H
/*
* This file is part of Bipscript-IDE.
*
* Bipscript-IDE 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.
*
* Bipscript-IDE 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 Bipscript-IDE. If not, see <http://www.gnu.org/licenses/>.
*/
#include "audiotimerservice.h"
#include <unistd.h>
#include <QDebug>
AudioTimerService::AudioTimerService(jack_client_t *c)
: cancelled(false),
mrolling(false),
client(c)
{
QObject::connect(this, SIGNAL(startTrigger()), this, SLOT(process()));