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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 28 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,40 @@ A dead-simple Markdown writing app built with Qt Quick and C++ that automaticall

Install via the Omarchy Package Repository via the `omawrite` package. It's installed by default in new installations of Omarchy (from Quattro forward).

### macOS (Apple Silicon)

Install Qt 6 and build an arm64 application bundle:

```sh
brew install qtbase qtdeclarative qttools
./bin/build
```

To bundle the Qt frameworks and create a local DMG:

```sh
./bin/package-macos-arm64
```

The package is written to `build/omawrite.dmg`. It is ad-hoc signed for local
use; public distribution still requires an Apple Developer ID signature and
notarization.

## Shortcuts

- `Ctrl+S` saves. Unsaved documents use the XDG desktop portal file picker.
- `Ctrl+S` saves. Unsaved documents use the system file picker (the XDG
desktop portal on Linux).
- `Ctrl+Shift+S` saves as.
- `Ctrl+O` opens a Markdown file through the portal picker.
- `Ctrl+O` opens a Markdown file through the system picker.
- `Ctrl+P` opens the system print dialog.
- `Ctrl+N` opens a new Omawrite window.
- `Ctrl+Z`, `Ctrl+Shift+Z`, and `Ctrl+Y` handle undo and redo.
- `Super+F` toggles fullscreen. Qt maps this key as `Meta+F`.
- `Super+F` toggles fullscreen on Linux; macOS uses `Control+Command+F`.
- `Ctrl+F` searches the document. Use `Enter` or `Ctrl+G` for the next match and `Shift+Enter` for the previous match.
- `Ctrl+H` opens find and replace.
- `Ctrl+H` opens find and replace on Linux; macOS uses `Command+Option+F`.
- `Ctrl+B`, `Ctrl+I`, and `Ctrl+K` insert bold, italic, and link Markdown.
- `Ctrl+?` shows the keyboard shortcut reference.
- `Ctrl+?` shows the keyboard shortcut reference. On macOS, Qt maps `Ctrl`
shortcuts to their native `Command` equivalents.

Unsaved drafts are recovered after an abnormal exit. Omawrite also watches open files
and warns before an external change can replace local work.
Expand All @@ -34,7 +55,8 @@ Omawrite at the size it is designed around; larger and smaller sizes scale from
## Requirements

- Qt 6: `qt6-base`, `qt6-declarative`, `qt6-quickcontrols2`
- `xdg-desktop-portal` and a portal backend
- Linux: `xdg-desktop-portal` and a portal backend
- macOS 13 or newer: Xcode Command Line Tools

The iA Writer Mono font is bundled under the SIL Open Font License 1.1; see
`fonts/OFL.txt`. The font is copyright Information Architects Inc. and based on
Expand Down
12 changes: 10 additions & 2 deletions bin/build
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,25 @@ if command -v qmake6 >/dev/null 2>&1; then
QMAKE=qmake6
elif command -v qmake >/dev/null 2>&1; then
QMAKE=qmake
elif command -v brew >/dev/null 2>&1 && [ -x "$(brew --prefix qt)/bin/qmake" ]; then
QMAKE="$(brew --prefix qt)/bin/qmake"
elif command -v brew >/dev/null 2>&1 && [ -x "$(brew --prefix qtbase)/bin/qmake" ]; then
QMAKE="$(brew --prefix qtbase)/bin/qmake"
else
echo "qmake6 or qmake is required to build omawrite." >&2
exit 1
fi

JOBS="$(nproc 2>/dev/null || echo 1)"
JOBS="$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 1)"

mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"

"$QMAKE" "$ROOT/omawrite.pro"
make -j"$JOBS"

echo "Built $BUILD_DIR/omawrite"
if [ -d "$BUILD_DIR/omawrite.app" ]; then
echo "Built $BUILD_DIR/omawrite.app"
else
echo "Built $BUILD_DIR/omawrite"
fi
96 changes: 96 additions & 0 deletions bin/package-macos-arm64
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env sh
set -eu

if [ "$(uname -s)" != "Darwin" ] || [ "$(uname -m)" != "arm64" ]; then
echo "This package script must run on an Apple Silicon Mac." >&2
exit 1
fi

ROOT="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)"
BUILD_DIR="$ROOT/build"
APP="$BUILD_DIR/omawrite.app"

if command -v qmake6 >/dev/null 2>&1; then
QMAKE=qmake6
elif command -v qmake >/dev/null 2>&1; then
QMAKE=qmake
elif command -v brew >/dev/null 2>&1 && [ -x "$(brew --prefix qt)/bin/qmake" ]; then
QMAKE="$(brew --prefix qt)/bin/qmake"
elif command -v brew >/dev/null 2>&1 && [ -x "$(brew --prefix qtbase)/bin/qmake" ]; then
QMAKE="$(brew --prefix qtbase)/bin/qmake"
else
echo "Qt 6 is required. Install it with: brew install qtbase qtdeclarative qttools" >&2
exit 1
fi

case "$QMAKE" in
/*) ;;
*) QMAKE="$(command -v "$QMAKE")" ;;
esac
QT_BIN="$(dirname -- "$QMAKE")"
if [ -x "$QT_BIN/macdeployqt" ]; then
MACDEPLOYQT="$QT_BIN/macdeployqt"
elif command -v macdeployqt >/dev/null 2>&1; then
MACDEPLOYQT="$(command -v macdeployqt)"
elif command -v brew >/dev/null 2>&1 && [ -x "$(brew --prefix qttools)/bin/macdeployqt" ]; then
MACDEPLOYQT="$(brew --prefix qttools)/bin/macdeployqt"
else
MACDEPLOYQT=""
fi
if [ ! -x "$MACDEPLOYQT" ]; then
echo "macdeployqt was not found. Install it with: brew install qttools" >&2
exit 1
fi

JOBS="$(sysctl -n hw.logicalcpu 2>/dev/null || echo 1)"
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"

# Never carry frameworks or plugins over from a previous Qt toolchain.
rm -rf "$APP"
"$QMAKE" "$ROOT/omawrite.pro" CONFIG+=release QMAKE_APPLE_DEVICE_ARCHS=arm64
make clean
make -j"$JOBS"

BINARY="$APP/Contents/MacOS/omawrite"
if [ ! -x "$BINARY" ]; then
echo "The expected application bundle was not produced: $APP" >&2
exit 1
fi

ARCHS="$(lipo -archs "$BINARY")"
if [ "$ARCHS" != "arm64" ]; then
echo "Expected an arm64-only application, but found: $ARCHS" >&2
exit 1
fi

QT_LIBS="$("$QMAKE" -query QT_INSTALL_LIBS)"

# macdeployqt does not always search the SDK's top-level library directory
# when Qt is installed as split packages (as Homebrew does). Supplying qmake's
# reported library directory also works with the official Qt SDK.
rm -f "$BUILD_DIR/omawrite.dmg"
if [ -d "$QT_LIBS" ]; then
"$MACDEPLOYQT" "$APP" -qmldir="$ROOT/src" -libpath="$QT_LIBS" \
-appstore-compliant -always-overwrite
else
"$MACDEPLOYQT" "$APP" -qmldir="$ROOT/src" -appstore-compliant \
-always-overwrite
fi

# The official SDK ships a Mimer SQL plugin that links to a proprietary client
# library outside Qt. Omawrite does not use it; retaining SQLite is sufficient
# for any Qt Quick local-storage dependency.
rm -f "$APP/Contents/PlugIns/sqldrivers/libqsqlmimer.dylib"
codesign --force --deep --sign - "$APP"
codesign --verify --deep --strict "$APP"

DMG_STAGE="$(mktemp -d "$BUILD_DIR/.omawrite-dmg.XXXXXX")"
trap 'rm -rf "$DMG_STAGE"' EXIT
ditto "$APP" "$DMG_STAGE/Omawrite.app"
ln -s /Applications "$DMG_STAGE/Applications"
hdiutil create -quiet -fs HFS+ -volname Omawrite -srcfolder "$DMG_STAGE" \
-format UDZO "$BUILD_DIR/omawrite.dmg"
hdiutil verify "$BUILD_DIR/omawrite.dmg" >/dev/null

echo "Packaged $BUILD_DIR/omawrite.dmg"
11 changes: 9 additions & 2 deletions bin/test
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,19 @@ BUILD_DIR="$ROOT/build-tests"

if command -v qmake6 >/dev/null 2>&1; then
QMAKE=qmake6
else
elif command -v qmake >/dev/null 2>&1; then
QMAKE=qmake
elif command -v brew >/dev/null 2>&1 && [ -x "$(brew --prefix qt)/bin/qmake" ]; then
QMAKE="$(brew --prefix qt)/bin/qmake"
elif command -v brew >/dev/null 2>&1 && [ -x "$(brew --prefix qtbase)/bin/qmake" ]; then
QMAKE="$(brew --prefix qtbase)/bin/qmake"
else
echo "qmake6 or qmake is required to test omawrite." >&2
exit 1
fi

mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
"$QMAKE" "$ROOT/tests/tests.pro"
make -j"$(nproc 2>/dev/null || echo 1)"
make -j"$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 1)"
QT_QPA_PLATFORM=offscreen ./tst_omawrite
12 changes: 11 additions & 1 deletion omawrite.pro
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
QT += core gui widgets printsupport qml quick quickcontrols2 quickdialogs2 dbus
QT += core gui widgets printsupport qml quick quickcontrols2 quickdialogs2

# The XDG desktop portal integration is Linux-only. macOS and Windows use
# QStyleHints for native light/dark mode detection instead.
linux: QT += dbus

CONFIG += c++17 release
TARGET = omawrite
TEMPLATE = app
VERSION = 0.1.0

macx {
ICON = pkgbuild/omawrite.icns
QMAKE_INFO_PLIST = pkgbuild/Info.plist
}

HEADERS += \
src/backend.h \
Expand Down
70 changes: 70 additions & 0 deletions pkgbuild/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Omawrite</string>
<key>CFBundleExecutable</key>
<string>omawrite</string>
<key>CFBundleIconFile</key>
<string>omawrite.icns</string>
<key>CFBundleIdentifier</key>
<string>io.omacom.omawrite</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Omawrite</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.productivity</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>UTImportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.plain-text</string>
</array>
<key>UTTypeDescription</key>
<string>Markdown document</string>
<key>UTTypeIdentifier</key>
<string>net.daringfireball.markdown</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>md</string>
<string>markdown</string>
</array>
<key>public.mime-type</key>
<string>text/markdown</string>
</dict>
</dict>
</array>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>Markdown document</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>net.daringfireball.markdown</string>
</array>
</dict>
</array>
</dict>
</plist>
Binary file added pkgbuild/omawrite.icns
Binary file not shown.
Loading