Merge pull request #204 from UberWriter/ui

UI updates, specially to the headerbar:

- Fix margin on the recent files popover
- Add the full path of the current file to the headerbar as subtitle and tooltip
- Rework the autohiding mechanism; now the headerbar fades away when typing, only to reappear when the cursor moves to the top portion of the window
- Now the content of the texview goes visually bellow the headerbar
- Rework the layout of the headerbar: now we have dedicated dropdowns for "save as/export" actions, and a new preview layout switcher
- Add theme selector to the appmenu
master
somas95 2020-03-12 01:59:26 +01:00 committed by GitHub
commit e38520c35d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 7417 additions and 1661 deletions

24
.gitignore vendored
View File

@ -1,26 +1,10 @@
build/lib.linux-x86_64-2.7
*.pyc
__pycache__/
_build/*
build/
_build/
debian/uberwriter/DEBIAN
debian/uberwriter/opt
debian/uberwriter/usr
flatpak/*
!flatpak/uberwriter.json
!flatpak/de.wolfvollprecht.UberWriter.*
!flatpak/flatpak_texlive.json
!flatpak/texlive_install.sh
!flatpak/python3-enchant.json
!flatpak/python3-packages.json
*.py~
data/ui/shortcut_handlers
*.ui~
*.*~
.vscode/
.idea/
*.glade~
dist/uberwriter-2.0b0-py3.7.egg
builddir/*
dist/
uberwriter.egg-info
build-aux/flatpak/.flatpak-builder/*
build-aux/*
flatpak/*

View File

@ -1,10 +1,10 @@
{
"app-id": "de.wolfvollprecht.UberWriter",
"runtime": "org.gnome.Platform",
"runtime-version": "3.34",
"sdk": "org.gnome.Sdk",
"command": "uberwriter",
"finish-args": [
"app-id" : "de.wolfvollprecht.UberWriter",
"runtime" : "org.gnome.Platform",
"runtime-version" : "3.34",
"sdk" : "org.gnome.Sdk",
"command" : "uberwriter",
"finish-args" : [
"--socket=x11",
"--socket=wayland",
"--share=ipc",
@ -13,94 +13,108 @@
"--env=PATH=/app/bin:/usr/bin:/app/extensions/TexLive/2019/bin/x86_64-linux/",
"--metadata=X-DConf=migrate-path=/de/wolfvollprecht/UberWriter/"
],
"add-extensions": {
"de.wolfvollprecht.UberWriter.Plugin": {
"directory": "extensions",
"version": "stable",
"subdirectories": true,
"no-autodownload": true,
"autodelete": true
}
"add-extensions" : {
"de.wolfvollprecht.UberWriter.Plugin" : {
"directory" : "extensions",
"version" : "stable",
"subdirectories" : true,
"no-autodownload" : true,
"autodelete" : true
}
},
"modules": [{
"name":"gspell",
"sources":[{
"type":"archive",
"url":"https://download.gnome.org/sources/gspell/1.8/gspell-1.8.1.tar.xz",
"sha256":"819a1d23c7603000e73f5e738bdd284342e0cd345fb0c7650999c31ec741bbe5"
}]
},
{
"name": "pandoc",
"only-arches": [
"x86_64"
],
"buildsystem": "simple",
"build-commands": [
"cp bin/pandoc /app/bin/pandoc",
"cp bin/pandoc-citeproc /app/bin/pandoc-citeproc"
],
"sources": [{
"type": "archive",
"url": "https://github.com/jgm/pandoc/releases/download/2.2/pandoc-2.2-linux.tar.gz",
"sha256": "06ecd882e42ef9b7390b1c82e1e71b3ea48679181289b9b810a8797825bed8ed"
}]
},
{
"name": "pipdeps",
"buildsystem": "simple",
"build-commands": [
"pip3 install --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} regex pypandoc"
],
"sources": [{
"type": "file",
"url": "https://files.pythonhosted.org/packages/5d/c1/45947333669b31bc6b4933308dd07c2aa2fedcec0a95b14eedae993bd449/wheel-0.31.0.tar.gz",
"sha256": "1ae8153bed701cb062913b72429bcf854ba824f973735427681882a688cb55ce"
"modules" : [
{
"name" : "gspell",
"sources" : [
{
"type" : "archive",
"url" : "https://download.gnome.org/sources/gspell/1.8/gspell-1.8.1.tar.xz",
"sha256" : "819a1d23c7603000e73f5e738bdd284342e0cd345fb0c7650999c31ec741bbe5"
}
]
},
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/ae/e8/2340d46ecadb1692a1e455f13f75e596d4eab3d11a57446f08259dee8f02/pip-10.0.1.tar.gz",
"sha256": "f2bd08e0cd1b06e10218feaf6fef299f473ba706582eb3bd9d52203fdbd7ee68"
},
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/71/81/00184643e5a10a456b4118fc12c96780823adb8ed974eb2289f29703b29b/pypandoc-1.4.tar.gz",
"sha256": "e914e6d5f84a76764887e4d909b09d63308725f0cbb5293872c2c92f07c11a5b"
"name" : "pandoc",
"only-arches" : [
"x86_64"
],
"buildsystem" : "simple",
"build-commands" : [
"cp bin/pandoc /app/bin/pandoc",
"cp bin/pandoc-citeproc /app/bin/pandoc-citeproc"
],
"sources" : [
{
"type" : "archive",
"url" : "https://github.com/jgm/pandoc/releases/download/2.2/pandoc-2.2-linux.tar.gz",
"sha256" : "06ecd882e42ef9b7390b1c82e1e71b3ea48679181289b9b810a8797825bed8ed"
}
]
},
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/a2/51/c39562cfed3272592c60cfd229e5464d715b78537e332eac2b695422dc49/regex-2018.02.21.tar.gz",
"sha256": "b44624a38d07d3c954c84ad302c29f7930f4bf01443beef5589e9157b14e2a29"
"name" : "pipdeps",
"buildsystem" : "simple",
"build-commands" : [
"pip3 install --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} regex pypandoc"
],
"sources" : [
{
"type" : "file",
"url" : "https://files.pythonhosted.org/packages/5d/c1/45947333669b31bc6b4933308dd07c2aa2fedcec0a95b14eedae993bd449/wheel-0.31.0.tar.gz",
"sha256" : "1ae8153bed701cb062913b72429bcf854ba824f973735427681882a688cb55ce"
},
{
"type" : "file",
"url" : "https://files.pythonhosted.org/packages/ae/e8/2340d46ecadb1692a1e455f13f75e596d4eab3d11a57446f08259dee8f02/pip-10.0.1.tar.gz",
"sha256" : "f2bd08e0cd1b06e10218feaf6fef299f473ba706582eb3bd9d52203fdbd7ee68"
},
{
"type" : "file",
"url" : "https://files.pythonhosted.org/packages/71/81/00184643e5a10a456b4118fc12c96780823adb8ed974eb2289f29703b29b/pypandoc-1.4.tar.gz",
"sha256" : "e914e6d5f84a76764887e4d909b09d63308725f0cbb5293872c2c92f07c11a5b"
},
{
"type" : "file",
"url" : "https://files.pythonhosted.org/packages/a2/51/c39562cfed3272592c60cfd229e5464d715b78537e332eac2b695422dc49/regex-2018.02.21.tar.gz",
"sha256" : "b44624a38d07d3c954c84ad302c29f7930f4bf01443beef5589e9157b14e2a29"
},
{
"type" : "file",
"url" : "https://files.pythonhosted.org/packages/9e/54/04d88a59efa33fefb88133ceb638cdf754319030c28aadc5a379d82140ed/pyenchant-2.0.0.tar.gz",
"sha256" : "fc31cda72ace001da8fe5d42f11c26e514a91fa8c70468739216ddd8de64e2a0"
}
]
},
{
"type": "file",
"url": "https://files.pythonhosted.org/packages/9e/54/04d88a59efa33fefb88133ceb638cdf754319030c28aadc5a379d82140ed/pyenchant-2.0.0.tar.gz",
"sha256": "fc31cda72ace001da8fe5d42f11c26e514a91fa8c70468739216ddd8de64e2a0"
}]
},
{
"name": "fonts",
"buildsystem": "simple",
"build-commands": [
"mkdir -p /app/share/fonts/",
"cp ttf/* /app/share/fonts/"
],
"sources": [{
"type": "git",
"url": "https://github.com/mozilla/Fira",
"tag": "4.202"
}]
},
{
"name": "uberwriter",
"buildsystem": "meson",
"sources": [{
"type" : "dir",
"path" : "../../"
}],
"post-install": [
"install -d /app/extensions"
]
}
]
"name" : "fonts",
"buildsystem" : "simple",
"build-commands" : [
"mkdir -p /app/share/fonts/",
"cp ttf/* /app/share/fonts/"
],
"sources" : [
{
"type" : "git",
"url" : "https://github.com/mozilla/Fira",
"tag" : "4.202"
}
]
},
{
"name" : "uberwriter",
"buildsystem" : "meson",
"config-opts" : [
"-Dprofile=development"
],
"sources" : [
{
"type" : "dir",
"path" : "../../"
}
],
"post-install" : [
"install -d /app/extensions"
]
}
]
}

View File

@ -3,7 +3,7 @@
<id>@app-id@</id>
<launchable type="desktop-id">@app-id@.desktop</launchable>
<name>UberWriter</name>
<summary>An elegant, free distraction GTK+ markdown editor</summary>
<summary>An elegant, distraction-free GTK+ markdown editor</summary>
<description>
<p>Uberwriter is a GTK+ based distraction free Markdown editor, mainly developed by Wolf Vollprecht and Manuel Genovés. It uses pandoc as backend for markdown parsing and offers a very clean and sleek user interface.</p>
<p>You can install the recommended TexLive extension with the command:</p>

View File

@ -18,17 +18,9 @@
</enum>
<schema path="/de/wolfvollprecht/UberWriter/" id="de.wolfvollprecht.UberWriter">
<key name='dark-mode-auto' type='b'>
<default>true</default>
<summary>Set dark mode automatically</summary>
<description>
Whether dark mode depends on the system theme, or is set to what the user specifies.
</description>
</key>
<key name='dark-mode' type='b'>
<default>false</default>
<summary>Force dark mode</summary>
<summary>Use dark mode</summary>
<description>
Enable or disable the dark mode.
</description>
@ -40,14 +32,6 @@
Enable or disable spellchecking.
</description>
</key>
<key name='gradient-overlay' type='b'>
<default>false</default>
<summary>Draw scroll gradient</summary>
<description>
Show a gradient overlay over the text at the top anf bottom of the window.
It can cause performance problems to some users.
</description>
</key>
<key name='sync-scroll' type='b'>
<default>true</default>
<summary>Synchronize editor/preview scrolling</summary>
@ -62,11 +46,11 @@
Input format to use when previewing and exporting using Pandoc.
</description>
</key>
<key name='poll-motion' type='b'>
<key name='autohide-headerbar' type='b'>
<default>true</default>
<summary>Allow Uberwriter to poll cursor motion</summary>
<summary>Autohide Headerbar</summary>
<description>
Hide the header and status bars if the cursor is not moving.
Hide the header and status bars when typing.
</description>
</key>
<key name='open-file-path' type='s'>

View File

@ -0,0 +1,211 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128px" height="128px" viewBox="0 0 128 128" version="1.1">
<defs>
<linearGradient id="linear0" gradientUnits="userSpaceOnUse" x1="11.999994" y1="254" x2="116" y2="254" gradientTransform="matrix(1.076923,0,0,1.066667,-4.428073,-187.428352)">
<stop offset="0" style="stop-color:rgb(60.392159%,60.000002%,58.823532%);stop-opacity:1;"/>
<stop offset="0.0384616" style="stop-color:rgb(75.294119%,74.901962%,73.725492%);stop-opacity:1;"/>
<stop offset="0.0769231" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
<stop offset="0.923077" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
<stop offset="0.961538" style="stop-color:rgb(75.294119%,74.901962%,73.725492%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(60.392159%,60.000002%,58.823532%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear1" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,233.495007,20.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear2" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,309.495007,64.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear3" gradientUnits="userSpaceOnUse" x1="17" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,257.495007,64.504974)">
<stop offset="0" style="stop-color:rgb(68.235296%,67.843139%,67.058825%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(80.784315%,80.000001%,78.431374%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear4" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,253.495007,20.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear5" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,273.495007,20.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear6" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,293.495007,20.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear7" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,313.495007,20.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear8" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,243.495007,42.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear9" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,263.495007,42.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear10" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,283.495007,42.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear11" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,313.495007,42.504974)">
<stop offset="0" style="stop-color:rgb(90.196079%,38.039216%,0%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(100%,47.058824%,0%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear12" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,237.495007,64.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear13" gradientUnits="userSpaceOnUse" x1="11.999994" y1="254" x2="116" y2="254" gradientTransform="matrix(1.076923,0,0,1.066667,-4.428073,-187.428352)">
<stop offset="0" style="stop-color:rgb(60.392159%,60.000002%,58.823532%);stop-opacity:1;"/>
<stop offset="0.0384616" style="stop-color:rgb(75.294119%,74.901962%,73.725492%);stop-opacity:1;"/>
<stop offset="0.0769231" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
<stop offset="0.923077" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
<stop offset="0.961538" style="stop-color:rgb(75.294119%,74.901962%,73.725492%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(60.392159%,60.000002%,58.823532%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear14" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,233.495007,20.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear15" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,309.495007,64.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear16" gradientUnits="userSpaceOnUse" x1="17" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,257.495007,64.504974)">
<stop offset="0" style="stop-color:rgb(68.235296%,67.843139%,67.058825%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(80.784315%,80.000001%,78.431374%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear17" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,253.495007,20.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear18" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,273.495007,20.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear19" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,293.495007,20.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear20" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,313.495007,20.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear21" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,243.495007,42.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear22" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,263.495007,42.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear23" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,283.495007,42.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear24" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,313.495007,42.504974)">
<stop offset="0" style="stop-color:rgb(90.196079%,38.039216%,0%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(100%,47.058824%,0%);stop-opacity:1;"/>
</linearGradient>
<linearGradient id="linear25" gradientUnits="userSpaceOnUse" x1="19" y1="209" x2="31" y2="209" gradientTransform="matrix(0.000000000000000061,1,-1,0.000000000000000061,237.495007,64.504974)">
<stop offset="0" style="stop-color:rgb(36.862746%,36.078432%,39.215687%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(46.666667%,46.27451%,48.235294%);stop-opacity:1;"/>
</linearGradient>
<clipPath id="clip2">
<rect x="0" y="0" width="128" height="128"/>
</clipPath>
<g id="surface50195" clip-path="url(#clip2)">
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear13);" d="M 16.496094 51.503906 L 112.496094 51.503906 C 116.914062 51.503906 120.496094 55.085938 120.496094 59.503906 L 120.496094 107.503906 C 120.496094 111.921875 116.914062 115.503906 112.496094 115.503906 L 16.496094 115.503906 C 12.078125 115.503906 8.496094 111.921875 8.496094 107.503906 L 8.496094 59.503906 C 8.496094 55.085938 12.078125 51.503906 16.496094 51.503906 Z M 16.496094 51.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.470588%,96.078432%,95.686275%);fill-opacity:1;" d="M 16.496094 27.503906 L 112.496094 27.503906 C 116.914062 27.503906 120.496094 31.464844 120.496094 36.347656 L 120.496094 102.664062 C 120.496094 107.546875 116.914062 111.503906 112.496094 111.503906 L 16.496094 111.503906 C 12.078125 111.503906 8.496094 107.546875 8.496094 102.664062 L 8.496094 36.347656 C 8.496094 31.464844 12.078125 27.503906 16.496094 27.503906 Z M 16.496094 27.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 21.496094 39.503906 L 27.496094 39.503906 C 29.710938 39.503906 31.273438 41.300781 31.496094 43.503906 L 32.496094 53.503906 C 32.714844 55.710938 30.710938 57.503906 28.496094 57.503906 L 20.496094 57.503906 C 18.277344 57.503906 16.273438 55.710938 16.496094 53.503906 L 17.496094 43.503906 C 17.714844 41.300781 19.277344 39.503906 21.496094 39.503906 Z M 21.496094 39.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear14);" d="M 31.496094 43.503906 L 31.496094 47.503906 C 31.496094 49.722656 29.710938 51.503906 27.496094 51.503906 L 21.496094 51.503906 C 19.277344 51.503906 17.496094 49.722656 17.496094 47.503906 L 17.496094 43.503906 C 17.496094 41.289062 19.277344 39.503906 21.496094 39.503906 L 27.496094 39.503906 C 29.710938 39.503906 31.496094 41.289062 31.496094 43.503906 Z M 31.496094 43.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 41.496094 39.503906 L 47.496094 39.503906 C 49.710938 39.503906 51.273438 41.300781 51.496094 43.503906 L 52.496094 53.503906 C 52.714844 55.710938 50.710938 57.503906 48.496094 57.503906 L 40.496094 57.503906 C 38.277344 57.503906 36.273438 55.710938 36.496094 53.503906 L 37.496094 43.503906 C 37.714844 41.300781 39.277344 39.503906 41.496094 39.503906 Z M 41.496094 39.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 61.496094 39.503906 L 67.496094 39.503906 C 69.710938 39.503906 71.273438 41.300781 71.496094 43.503906 L 72.496094 53.503906 C 72.714844 55.710938 70.710938 57.503906 68.496094 57.503906 L 60.496094 57.503906 C 58.277344 57.503906 56.273438 55.710938 56.496094 53.503906 L 57.496094 43.503906 C 57.714844 41.300781 59.277344 39.503906 61.496094 39.503906 Z M 61.496094 39.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 81.496094 39.503906 L 87.496094 39.503906 C 89.710938 39.503906 91.273438 41.300781 91.496094 43.503906 L 92.496094 53.503906 C 92.714844 55.710938 90.710938 57.503906 88.496094 57.503906 L 80.496094 57.503906 C 78.277344 57.503906 76.273438 55.710938 76.496094 53.503906 L 77.496094 43.503906 C 77.714844 41.300781 79.277344 39.503906 81.496094 39.503906 Z M 81.496094 39.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 101.496094 39.503906 L 107.496094 39.503906 C 109.710938 39.503906 111.273438 41.300781 111.496094 43.503906 L 112.496094 53.503906 C 112.714844 55.710938 110.710938 57.503906 108.496094 57.503906 L 100.496094 57.503906 C 98.277344 57.503906 96.273438 55.710938 96.496094 53.503906 L 97.496094 43.503906 C 97.714844 41.300781 99.277344 39.503906 101.496094 39.503906 Z M 101.496094 39.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 31.496094 61.503906 L 37.496094 61.503906 C 39.710938 61.503906 41.273438 63.300781 41.496094 65.503906 L 42.496094 75.503906 C 42.714844 77.710938 40.710938 79.503906 38.496094 79.503906 L 30.496094 79.503906 C 28.277344 79.503906 26.273438 77.710938 26.496094 75.503906 L 27.496094 65.503906 C 27.714844 63.300781 29.277344 61.503906 31.496094 61.503906 Z M 31.496094 61.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 51.496094 61.503906 L 57.496094 61.503906 C 59.710938 61.503906 61.273438 63.300781 61.496094 65.503906 L 62.496094 75.503906 C 62.714844 77.710938 60.710938 79.503906 58.496094 79.503906 L 50.496094 79.503906 C 48.277344 79.503906 46.273438 77.710938 46.496094 75.503906 L 47.496094 65.503906 C 47.714844 63.300781 49.277344 61.503906 51.496094 61.503906 Z M 51.496094 61.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 71.496094 61.503906 L 77.496094 61.503906 C 79.710938 61.503906 81.273438 63.300781 81.496094 65.503906 L 82.496094 75.503906 C 82.714844 77.710938 80.710938 79.503906 78.496094 79.503906 L 70.496094 79.503906 C 68.277344 79.503906 66.273438 77.710938 66.496094 75.503906 L 67.496094 65.503906 C 67.714844 63.300781 69.277344 61.503906 71.496094 61.503906 Z M 71.496094 61.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(77.64706%,27.450982%,0%);fill-opacity:1;" d="M 91.496094 61.503906 L 98.496094 61.503906 C 100.710938 61.503906 102.273438 63.300781 102.496094 65.503906 L 103.496094 75.503906 C 103.714844 77.710938 101.710938 79.503906 99.496094 79.503906 L 90.496094 79.503906 C 88.277344 79.503906 86.273438 77.710938 86.496094 75.503906 L 87.496094 65.503906 C 87.714844 63.300781 89.277344 61.503906 91.496094 61.503906 Z M 91.496094 61.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 25.496094 83.503906 L 31.496094 83.503906 C 33.710938 83.503906 35.273438 85.300781 35.496094 87.503906 L 36.496094 97.503906 C 36.714844 99.710938 34.710938 101.503906 32.496094 101.503906 L 24.496094 101.503906 C 22.277344 101.503906 20.273438 99.710938 20.496094 97.503906 L 21.496094 87.503906 C 21.714844 85.300781 23.277344 83.503906 25.496094 83.503906 Z M 25.496094 83.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 97.496094 83.503906 L 103.496094 83.503906 C 105.710938 83.503906 107.273438 85.300781 107.496094 87.503906 L 108.496094 97.503906 C 108.714844 99.710938 106.710938 101.503906 104.496094 101.503906 L 96.496094 101.503906 C 94.277344 101.503906 92.273438 99.710938 92.496094 97.503906 L 93.496094 87.503906 C 93.714844 85.300781 95.277344 83.503906 97.496094 83.503906 Z M 97.496094 83.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear15);" d="M 107.496094 87.503906 L 107.496094 91.503906 C 107.496094 93.722656 105.710938 95.503906 103.496094 95.503906 L 97.496094 95.503906 C 95.277344 95.503906 93.496094 93.722656 93.496094 91.503906 L 93.496094 87.503906 C 93.496094 85.289062 95.277344 83.503906 97.496094 83.503906 L 103.496094 83.503906 C 105.710938 83.503906 107.496094 85.289062 107.496094 87.503906 Z M 107.496094 87.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50.980395%,50.588238%,52.549022%);fill-opacity:1;" d="M 45.496094 83.503906 L 83.496094 83.503906 C 85.710938 83.503906 87.273438 85.300781 87.496094 87.503906 L 88.496094 97.503906 C 88.714844 99.710938 86.710938 101.503906 84.496094 101.503906 L 44.496094 101.503906 C 42.277344 101.503906 40.273438 99.710938 40.496094 97.503906 L 41.496094 87.503906 C 41.714844 85.300781 43.277344 83.503906 45.496094 83.503906 Z M 45.496094 83.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear16);" d="M 87.496094 87.503906 L 87.496094 91.503906 C 87.496094 93.722656 85.710938 95.503906 83.496094 95.503906 L 45.496094 95.503906 C 43.277344 95.503906 41.496094 93.722656 41.496094 91.503906 L 41.496094 87.503906 C 41.496094 85.289062 43.277344 83.503906 45.496094 83.503906 L 83.496094 83.503906 C 85.710938 83.503906 87.496094 85.289062 87.496094 87.503906 Z M 87.496094 87.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear17);" d="M 51.496094 43.503906 L 51.496094 47.503906 C 51.496094 49.722656 49.710938 51.503906 47.496094 51.503906 L 41.496094 51.503906 C 39.277344 51.503906 37.496094 49.722656 37.496094 47.503906 L 37.496094 43.503906 C 37.496094 41.289062 39.277344 39.503906 41.496094 39.503906 L 47.496094 39.503906 C 49.710938 39.503906 51.496094 41.289062 51.496094 43.503906 Z M 51.496094 43.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear18);" d="M 71.496094 43.503906 L 71.496094 47.503906 C 71.496094 49.722656 69.710938 51.503906 67.496094 51.503906 L 61.496094 51.503906 C 59.277344 51.503906 57.496094 49.722656 57.496094 47.503906 L 57.496094 43.503906 C 57.496094 41.289062 59.277344 39.503906 61.496094 39.503906 L 67.496094 39.503906 C 69.710938 39.503906 71.496094 41.289062 71.496094 43.503906 Z M 71.496094 43.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear19);" d="M 91.496094 43.503906 L 91.496094 47.503906 C 91.496094 49.722656 89.710938 51.503906 87.496094 51.503906 L 81.496094 51.503906 C 79.277344 51.503906 77.496094 49.722656 77.496094 47.503906 L 77.496094 43.503906 C 77.496094 41.289062 79.277344 39.503906 81.496094 39.503906 L 87.496094 39.503906 C 89.710938 39.503906 91.496094 41.289062 91.496094 43.503906 Z M 91.496094 43.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear20);" d="M 111.496094 43.503906 L 111.496094 47.503906 C 111.496094 49.722656 109.710938 51.503906 107.496094 51.503906 L 101.496094 51.503906 C 99.277344 51.503906 97.496094 49.722656 97.496094 47.503906 L 97.496094 43.503906 C 97.496094 41.289062 99.277344 39.503906 101.496094 39.503906 L 107.496094 39.503906 C 109.710938 39.503906 111.496094 41.289062 111.496094 43.503906 Z M 111.496094 43.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear21);" d="M 41.496094 65.503906 L 41.496094 69.503906 C 41.496094 71.722656 39.710938 73.503906 37.496094 73.503906 L 31.496094 73.503906 C 29.277344 73.503906 27.496094 71.722656 27.496094 69.503906 L 27.496094 65.503906 C 27.496094 63.289062 29.277344 61.503906 31.496094 61.503906 L 37.496094 61.503906 C 39.710938 61.503906 41.496094 63.289062 41.496094 65.503906 Z M 41.496094 65.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear22);" d="M 61.496094 65.503906 L 61.496094 69.503906 C 61.496094 71.722656 59.710938 73.503906 57.496094 73.503906 L 51.496094 73.503906 C 49.277344 73.503906 47.496094 71.722656 47.496094 69.503906 L 47.496094 65.503906 C 47.496094 63.289062 49.277344 61.503906 51.496094 61.503906 L 57.496094 61.503906 C 59.710938 61.503906 61.496094 63.289062 61.496094 65.503906 Z M 61.496094 65.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear23);" d="M 81.496094 65.503906 L 81.496094 69.503906 C 81.496094 71.722656 79.710938 73.503906 77.496094 73.503906 L 71.496094 73.503906 C 69.277344 73.503906 67.496094 71.722656 67.496094 69.503906 L 67.496094 65.503906 C 67.496094 63.289062 69.277344 61.503906 71.496094 61.503906 L 77.496094 61.503906 C 79.710938 61.503906 81.496094 63.289062 81.496094 65.503906 Z M 81.496094 65.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear24);" d="M 102.496094 65.503906 L 102.496094 69.503906 C 102.496094 71.722656 100.710938 73.503906 98.496094 73.503906 L 91.496094 73.503906 C 89.277344 73.503906 87.496094 71.722656 87.496094 69.503906 L 87.496094 65.503906 C 87.496094 63.289062 89.277344 61.503906 91.496094 61.503906 L 98.496094 61.503906 C 100.710938 61.503906 102.496094 63.289062 102.496094 65.503906 Z M 102.496094 65.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear25);" d="M 35.496094 87.503906 L 35.496094 91.503906 C 35.496094 93.722656 33.710938 95.503906 31.496094 95.503906 L 25.496094 95.503906 C 23.277344 95.503906 21.496094 93.722656 21.496094 91.503906 L 21.496094 87.503906 C 21.496094 85.289062 23.277344 83.503906 25.496094 83.503906 L 31.496094 83.503906 C 33.710938 83.503906 35.496094 85.289062 35.496094 87.503906 Z M 35.496094 87.503906 "/>
</g>
<clipPath id="clip1">
<rect x="0" y="0" width="128" height="128"/>
</clipPath>
<filter id="alpha" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">
<feColorMatrix type="matrix" in="SourceGraphic" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
</filter>
<g id="surface50198" clip-path="url(#clip1)" filter="url(#alpha)">
<use xlink:href="#surface50195"/>
</g>
<mask id="mask0">
<use xlink:href="#surface50198"/>
</mask>
<mask id="mask1">
<g filter="url(#alpha)">
<rect x="0" y="0" width="128" height="128" style="fill:rgb(0%,0%,0%);fill-opacity:0.8;stroke:none;"/>
</g>
</mask>
<linearGradient id="linear26" gradientUnits="userSpaceOnUse" x1="300" y1="235" x2="428" y2="235" gradientTransform="matrix(0.000000000000000023,0.37,-0.98462,0.00000000000000006,295.38501,-30.360001)">
<stop offset="0" style="stop-color:rgb(97.647059%,94.117647%,41.960785%);stop-opacity:1;"/>
<stop offset="1" style="stop-color:rgb(96.078432%,76.078433%,6.666667%);stop-opacity:1;"/>
</linearGradient>
<clipPath id="clip4">
<rect x="0" y="0" width="128" height="128"/>
</clipPath>
<g id="surface50192" clip-path="url(#clip4)">
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear26);" d="M 128 80.640625 L 128 128 L 0 128 L 0 80.640625 Z M 128 80.640625 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 13.308594 80.640625 L 60.664062 128 L 81.878906 128 L 34.519531 80.640625 Z M 55.730469 80.640625 L 103.09375 128 L 124.308594 128 L 76.945312 80.640625 Z M 98.160156 80.640625 L 128 110.480469 L 128 89.269531 L 119.371094 80.640625 Z M 0 88.546875 L 0 109.761719 L 18.238281 128 L 39.453125 128 Z M 0 88.546875 "/>
</g>
<clipPath id="clip3">
<rect x="0" y="0" width="128" height="128"/>
</clipPath>
<g id="surface50197" clip-path="url(#clip3)">
<use xlink:href="#surface50192" mask="url(#mask1)"/>
</g>
</defs>
<g id="surface50185">
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear0);" d="M 16.496094 51.503906 L 112.496094 51.503906 C 116.914062 51.503906 120.496094 55.085938 120.496094 59.503906 L 120.496094 107.503906 C 120.496094 111.921875 116.914062 115.503906 112.496094 115.503906 L 16.496094 115.503906 C 12.078125 115.503906 8.496094 111.921875 8.496094 107.503906 L 8.496094 59.503906 C 8.496094 55.085938 12.078125 51.503906 16.496094 51.503906 Z M 16.496094 51.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(96.470588%,96.078432%,95.686275%);fill-opacity:1;" d="M 16.496094 27.503906 L 112.496094 27.503906 C 116.914062 27.503906 120.496094 31.464844 120.496094 36.347656 L 120.496094 102.664062 C 120.496094 107.546875 116.914062 111.503906 112.496094 111.503906 L 16.496094 111.503906 C 12.078125 111.503906 8.496094 107.546875 8.496094 102.664062 L 8.496094 36.347656 C 8.496094 31.464844 12.078125 27.503906 16.496094 27.503906 Z M 16.496094 27.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 21.496094 39.503906 L 27.496094 39.503906 C 29.710938 39.503906 31.273438 41.300781 31.496094 43.503906 L 32.496094 53.503906 C 32.714844 55.710938 30.710938 57.503906 28.496094 57.503906 L 20.496094 57.503906 C 18.277344 57.503906 16.273438 55.710938 16.496094 53.503906 L 17.496094 43.503906 C 17.714844 41.300781 19.277344 39.503906 21.496094 39.503906 Z M 21.496094 39.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear1);" d="M 31.496094 43.503906 L 31.496094 47.503906 C 31.496094 49.722656 29.710938 51.503906 27.496094 51.503906 L 21.496094 51.503906 C 19.277344 51.503906 17.496094 49.722656 17.496094 47.503906 L 17.496094 43.503906 C 17.496094 41.289062 19.277344 39.503906 21.496094 39.503906 L 27.496094 39.503906 C 29.710938 39.503906 31.496094 41.289062 31.496094 43.503906 Z M 31.496094 43.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 41.496094 39.503906 L 47.496094 39.503906 C 49.710938 39.503906 51.273438 41.300781 51.496094 43.503906 L 52.496094 53.503906 C 52.714844 55.710938 50.710938 57.503906 48.496094 57.503906 L 40.496094 57.503906 C 38.277344 57.503906 36.273438 55.710938 36.496094 53.503906 L 37.496094 43.503906 C 37.714844 41.300781 39.277344 39.503906 41.496094 39.503906 Z M 41.496094 39.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 61.496094 39.503906 L 67.496094 39.503906 C 69.710938 39.503906 71.273438 41.300781 71.496094 43.503906 L 72.496094 53.503906 C 72.714844 55.710938 70.710938 57.503906 68.496094 57.503906 L 60.496094 57.503906 C 58.277344 57.503906 56.273438 55.710938 56.496094 53.503906 L 57.496094 43.503906 C 57.714844 41.300781 59.277344 39.503906 61.496094 39.503906 Z M 61.496094 39.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 81.496094 39.503906 L 87.496094 39.503906 C 89.710938 39.503906 91.273438 41.300781 91.496094 43.503906 L 92.496094 53.503906 C 92.714844 55.710938 90.710938 57.503906 88.496094 57.503906 L 80.496094 57.503906 C 78.277344 57.503906 76.273438 55.710938 76.496094 53.503906 L 77.496094 43.503906 C 77.714844 41.300781 79.277344 39.503906 81.496094 39.503906 Z M 81.496094 39.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 101.496094 39.503906 L 107.496094 39.503906 C 109.710938 39.503906 111.273438 41.300781 111.496094 43.503906 L 112.496094 53.503906 C 112.714844 55.710938 110.710938 57.503906 108.496094 57.503906 L 100.496094 57.503906 C 98.277344 57.503906 96.273438 55.710938 96.496094 53.503906 L 97.496094 43.503906 C 97.714844 41.300781 99.277344 39.503906 101.496094 39.503906 Z M 101.496094 39.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 31.496094 61.503906 L 37.496094 61.503906 C 39.710938 61.503906 41.273438 63.300781 41.496094 65.503906 L 42.496094 75.503906 C 42.714844 77.710938 40.710938 79.503906 38.496094 79.503906 L 30.496094 79.503906 C 28.277344 79.503906 26.273438 77.710938 26.496094 75.503906 L 27.496094 65.503906 C 27.714844 63.300781 29.277344 61.503906 31.496094 61.503906 Z M 31.496094 61.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 51.496094 61.503906 L 57.496094 61.503906 C 59.710938 61.503906 61.273438 63.300781 61.496094 65.503906 L 62.496094 75.503906 C 62.714844 77.710938 60.710938 79.503906 58.496094 79.503906 L 50.496094 79.503906 C 48.277344 79.503906 46.273438 77.710938 46.496094 75.503906 L 47.496094 65.503906 C 47.714844 63.300781 49.277344 61.503906 51.496094 61.503906 Z M 51.496094 61.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 71.496094 61.503906 L 77.496094 61.503906 C 79.710938 61.503906 81.273438 63.300781 81.496094 65.503906 L 82.496094 75.503906 C 82.714844 77.710938 80.710938 79.503906 78.496094 79.503906 L 70.496094 79.503906 C 68.277344 79.503906 66.273438 77.710938 66.496094 75.503906 L 67.496094 65.503906 C 67.714844 63.300781 69.277344 61.503906 71.496094 61.503906 Z M 71.496094 61.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(77.64706%,27.450982%,0%);fill-opacity:1;" d="M 91.496094 61.503906 L 98.496094 61.503906 C 100.710938 61.503906 102.273438 63.300781 102.496094 65.503906 L 103.496094 75.503906 C 103.714844 77.710938 101.710938 79.503906 99.496094 79.503906 L 90.496094 79.503906 C 88.277344 79.503906 86.273438 77.710938 86.496094 75.503906 L 87.496094 65.503906 C 87.714844 63.300781 89.277344 61.503906 91.496094 61.503906 Z M 91.496094 61.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 25.496094 83.503906 L 31.496094 83.503906 C 33.710938 83.503906 35.273438 85.300781 35.496094 87.503906 L 36.496094 97.503906 C 36.714844 99.710938 34.710938 101.503906 32.496094 101.503906 L 24.496094 101.503906 C 22.277344 101.503906 20.273438 99.710938 20.496094 97.503906 L 21.496094 87.503906 C 21.714844 85.300781 23.277344 83.503906 25.496094 83.503906 Z M 25.496094 83.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(23.921569%,21.960784%,27.450982%);fill-opacity:1;" d="M 97.496094 83.503906 L 103.496094 83.503906 C 105.710938 83.503906 107.273438 85.300781 107.496094 87.503906 L 108.496094 97.503906 C 108.714844 99.710938 106.710938 101.503906 104.496094 101.503906 L 96.496094 101.503906 C 94.277344 101.503906 92.273438 99.710938 92.496094 97.503906 L 93.496094 87.503906 C 93.714844 85.300781 95.277344 83.503906 97.496094 83.503906 Z M 97.496094 83.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear2);" d="M 107.496094 87.503906 L 107.496094 91.503906 C 107.496094 93.722656 105.710938 95.503906 103.496094 95.503906 L 97.496094 95.503906 C 95.277344 95.503906 93.496094 93.722656 93.496094 91.503906 L 93.496094 87.503906 C 93.496094 85.289062 95.277344 83.503906 97.496094 83.503906 L 103.496094 83.503906 C 105.710938 83.503906 107.496094 85.289062 107.496094 87.503906 Z M 107.496094 87.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(50.980395%,50.588238%,52.549022%);fill-opacity:1;" d="M 45.496094 83.503906 L 83.496094 83.503906 C 85.710938 83.503906 87.273438 85.300781 87.496094 87.503906 L 88.496094 97.503906 C 88.714844 99.710938 86.710938 101.503906 84.496094 101.503906 L 44.496094 101.503906 C 42.277344 101.503906 40.273438 99.710938 40.496094 97.503906 L 41.496094 87.503906 C 41.714844 85.300781 43.277344 83.503906 45.496094 83.503906 Z M 45.496094 83.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear3);" d="M 87.496094 87.503906 L 87.496094 91.503906 C 87.496094 93.722656 85.710938 95.503906 83.496094 95.503906 L 45.496094 95.503906 C 43.277344 95.503906 41.496094 93.722656 41.496094 91.503906 L 41.496094 87.503906 C 41.496094 85.289062 43.277344 83.503906 45.496094 83.503906 L 83.496094 83.503906 C 85.710938 83.503906 87.496094 85.289062 87.496094 87.503906 Z M 87.496094 87.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear4);" d="M 51.496094 43.503906 L 51.496094 47.503906 C 51.496094 49.722656 49.710938 51.503906 47.496094 51.503906 L 41.496094 51.503906 C 39.277344 51.503906 37.496094 49.722656 37.496094 47.503906 L 37.496094 43.503906 C 37.496094 41.289062 39.277344 39.503906 41.496094 39.503906 L 47.496094 39.503906 C 49.710938 39.503906 51.496094 41.289062 51.496094 43.503906 Z M 51.496094 43.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear5);" d="M 71.496094 43.503906 L 71.496094 47.503906 C 71.496094 49.722656 69.710938 51.503906 67.496094 51.503906 L 61.496094 51.503906 C 59.277344 51.503906 57.496094 49.722656 57.496094 47.503906 L 57.496094 43.503906 C 57.496094 41.289062 59.277344 39.503906 61.496094 39.503906 L 67.496094 39.503906 C 69.710938 39.503906 71.496094 41.289062 71.496094 43.503906 Z M 71.496094 43.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear6);" d="M 91.496094 43.503906 L 91.496094 47.503906 C 91.496094 49.722656 89.710938 51.503906 87.496094 51.503906 L 81.496094 51.503906 C 79.277344 51.503906 77.496094 49.722656 77.496094 47.503906 L 77.496094 43.503906 C 77.496094 41.289062 79.277344 39.503906 81.496094 39.503906 L 87.496094 39.503906 C 89.710938 39.503906 91.496094 41.289062 91.496094 43.503906 Z M 91.496094 43.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear7);" d="M 111.496094 43.503906 L 111.496094 47.503906 C 111.496094 49.722656 109.710938 51.503906 107.496094 51.503906 L 101.496094 51.503906 C 99.277344 51.503906 97.496094 49.722656 97.496094 47.503906 L 97.496094 43.503906 C 97.496094 41.289062 99.277344 39.503906 101.496094 39.503906 L 107.496094 39.503906 C 109.710938 39.503906 111.496094 41.289062 111.496094 43.503906 Z M 111.496094 43.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear8);" d="M 41.496094 65.503906 L 41.496094 69.503906 C 41.496094 71.722656 39.710938 73.503906 37.496094 73.503906 L 31.496094 73.503906 C 29.277344 73.503906 27.496094 71.722656 27.496094 69.503906 L 27.496094 65.503906 C 27.496094 63.289062 29.277344 61.503906 31.496094 61.503906 L 37.496094 61.503906 C 39.710938 61.503906 41.496094 63.289062 41.496094 65.503906 Z M 41.496094 65.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear9);" d="M 61.496094 65.503906 L 61.496094 69.503906 C 61.496094 71.722656 59.710938 73.503906 57.496094 73.503906 L 51.496094 73.503906 C 49.277344 73.503906 47.496094 71.722656 47.496094 69.503906 L 47.496094 65.503906 C 47.496094 63.289062 49.277344 61.503906 51.496094 61.503906 L 57.496094 61.503906 C 59.710938 61.503906 61.496094 63.289062 61.496094 65.503906 Z M 61.496094 65.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear10);" d="M 81.496094 65.503906 L 81.496094 69.503906 C 81.496094 71.722656 79.710938 73.503906 77.496094 73.503906 L 71.496094 73.503906 C 69.277344 73.503906 67.496094 71.722656 67.496094 69.503906 L 67.496094 65.503906 C 67.496094 63.289062 69.277344 61.503906 71.496094 61.503906 L 77.496094 61.503906 C 79.710938 61.503906 81.496094 63.289062 81.496094 65.503906 Z M 81.496094 65.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear11);" d="M 102.496094 65.503906 L 102.496094 69.503906 C 102.496094 71.722656 100.710938 73.503906 98.496094 73.503906 L 91.496094 73.503906 C 89.277344 73.503906 87.496094 71.722656 87.496094 69.503906 L 87.496094 65.503906 C 87.496094 63.289062 89.277344 61.503906 91.496094 61.503906 L 98.496094 61.503906 C 100.710938 61.503906 102.496094 63.289062 102.496094 65.503906 Z M 102.496094 65.503906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:url(#linear12);" d="M 35.496094 87.503906 L 35.496094 91.503906 C 35.496094 93.722656 33.710938 95.503906 31.496094 95.503906 L 25.496094 95.503906 C 23.277344 95.503906 21.496094 93.722656 21.496094 91.503906 L 21.496094 87.503906 C 21.496094 85.289062 23.277344 83.503906 25.496094 83.503906 L 31.496094 83.503906 C 33.710938 83.503906 35.496094 85.289062 35.496094 87.503906 Z M 35.496094 87.503906 "/>
<use xlink:href="#surface50197" mask="url(#mask0)"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 37 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 137 KiB

View File

@ -1,7 +1,6 @@
install_data(
'de.wolfvollprecht.UberWriter.svg',
install_dir: datadir / 'icons' / 'hicolor' / 'scalable' / 'apps',
rename: '@0@.svg'.format(application_id)
'@0@.svg'.format(application_id),
install_dir: datadir / 'icons' / 'hicolor' / 'scalable' / 'apps'
)
install_data(

View File

@ -27,6 +27,19 @@
caret-color: @theme_fg_color;
}
.uberwriter-window.focus:not(.tiled):not(.tiled-top):not(.tiled-bottom):not(.tiled-left):not(.tiled-right):not(.maximized):not(.fullscreen) {
border-top-left-radius: 8px;
border-top-right-radius: 8px;
}
.uberwriter-window.focus:not(.tiled):not(.tiled-top):not(.tiled-bottom):not(.tiled-left):not(.tiled-right):not(.maximized):not(.fullscreen):dir(ltr) scrollbar {
border-top-right-radius: 8px;
}
.uberwriter-window.focus:not(.tiled):not(.tiled-top):not(.tiled-bottom):not(.tiled-left):not(.tiled-right):not(.maximized):not(.fullscreen):dir(rtl) scrollbar {
border-top-left-radius: 8px;
}
#titlebar-revealer {
padding: 0;
}
@ -94,6 +107,7 @@
.inline-button {
color: alpha(@theme_fg_color, 0.6);
background-color: alpha(@theme_base_color, 0.9);
text-shadow: inherit;
box-shadow: initial;
background-clip: initial;
@ -157,5 +171,48 @@
}
.quick-preview-popup label {
color: @theme_fg_color;
color: @theme_fg_color;
}
.plain-listview {
background-color: @fg-color;
}
/* theme selector */
.color-button {
padding: 12px;
border-radius: 999px;
-gtk-outline-radius: 999px;
outline-offset: 1px;
border: none;
-gtk-icon-shadow: none;
min-width: 0px;
min-height: 0px;
color: transparent;
transition: all 200ms ease-out;
}
.color-light {
background: #ffffff;
box-shadow: inset 0 0 0 1px #2e3436;
}
.color-light:checked {
color: #2e3436;
box-shadow: inset 0 0 0 2px @theme_selected_bg_color;
}
.color-dark {
background: #2d2d2d;
box-shadow: inset 0 0 0 1px alpha(black, .35);
}
.color-dark:checked {
color: #eeeeec;
box-shadow: inset 0 0 0 2px @theme_selected_bg_color;
}
.color-button:disabled {
background: #929292;
box-shadow: inset 0 0 0 1px #2e3436;
}

View File

@ -15,5 +15,23 @@
--kbd-background-color: #f1f1f1;
--kbd-border-color: #bdc1c6;
--kbd-shadow-color: #8c939a;
}
}
@media (prefers-color-scheme: dark) {
:root {
--text-color: #eeeeec;
--background-color: #353535;
--alt-background-color: #3a3a3a;
--link-color: #b5daff;
--blockquote-text-color: #a8a8a6;
--blockquote-border-color: #525252;
--header-border-color: #474747;
--hr-background-color: #505050;
--table-tr-border-color: #696969;
--table-td-border-color: #525252;
--kbd-text-color: #cececc;
--kbd-background-color: #3c3c3c;
--kbd-border-color: #696969;
--kbd-shadow-color: #979797;
}
}

View File

@ -1,18 +0,0 @@
@import url("base.css");
:root {
--text-color: #eeeeec;
--background-color: #353535;
--alt-background-color: #3a3a3a;
--link-color: #b5daff;
--blockquote-text-color: #a8a8a6;
--blockquote-border-color: #525252;
--header-border-color: #474747;
--hr-background-color: #505050;
--table-tr-border-color: #696969;
--table-td-border-color: #525252;
--kbd-text-color: #cececc;
--kbd-background-color: #3c3c3c;
--kbd-border-color: #696969;
--kbd-shadow-color: #979797;
}

View File

@ -15,4 +15,23 @@
--kbd-background-color: #f0f2f4;
--kbd-border-color: #bcc2c9;
--kbd-shadow-color: #8b949d;
}
}
@media (prefers-color-scheme: dark) {
:root {
--text-color: #d3dae3;
--background-color: #383c4a;
--alt-background-color: #3d414f;
--link-color: #9ac6ff;
--blockquote-text-color: #8d949d;
--blockquote-border-color: #555967;
--header-border-color: #4a4e5c;
--hr-background-color: #535765;
--table-tr-border-color: #6c707e;
--table-td-border-color: #555967;
--kbd-text-color: #b3bac3;
--kbd-background-color: #3f4351;
--kbd-border-color: #6c707e;
--kbd-shadow-color: #9a9eac;
}
}

View File

@ -1,18 +0,0 @@
@import url("base.css");
:root {
--text-color: #d3dae3;
--background-color: #383c4a;
--alt-background-color: #3d414f;
--link-color: #9ac6ff;
--blockquote-text-color: #8d949d;
--blockquote-border-color: #555967;
--header-border-color: #4a4e5c;
--hr-background-color: #535765;
--table-tr-border-color: #6c707e;
--table-td-border-color: #555967;
--kbd-text-color: #b3bac3;
--kbd-background-color: #3f4351;
--kbd-border-color: #6c707e;
--kbd-shadow-color: #9a9eac;
}

View File

@ -1 +0,0 @@
@import url("arc.css");

Binary file not shown.

Before

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 322 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 522 B

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
version="1.1"
id="svg8"
sodipodi:docname="preview-layout-full-width-symbolic.svg"
inkscape:version="0.92.4 5da689c313, 2019-01-14">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1053"
id="namedview10"
showgrid="true"
inkscape:zoom="32"
inkscape:cx="7.7624248"
inkscape:cy="7.9170424"
inkscape:window-x="1280"
inkscape:window-y="484"
inkscape:window-maximized="1"
inkscape:current-layer="svg8">
<inkscape:grid
type="xygrid"
id="grid4526" />
</sodipodi:namedview>
<g
id="g873">
<rect
y="6"
x="2"
height="5.5"
width="11.5"
id="rect869"
style="opacity:0.5;fill:#474747;fill-opacity:1;stroke:none;stroke-width:1.2544198;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="sssssssssccccc"
inkscape:connector-curvature="0"
id="path4659-5"
d="M 15,6 C 15,5.057191 13.942809,4 13,4 H 2 C 1.057191,4 0,5.057191 0,6 v 5 c 0,0.942809 1.057191,2 2,2 h 11 c 0.942809,0 2,-1.057191 2,-2 z m -2,0 v 5 H 2 V 6 Z"
style="fill:#474747;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
inkscape:label="path4659-5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
version="1.1"
id="svg8"
sodipodi:docname="preview-layout-half-height-symbolic.svg"
inkscape:version="0.92.4 5da689c313, 2019-01-14">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1053"
id="namedview10"
showgrid="true"
inkscape:zoom="22.627417"
inkscape:cx="-3.659756"
inkscape:cy="3.0846355"
inkscape:window-x="1280"
inkscape:window-y="484"
inkscape:window-maximized="1"
inkscape:current-layer="g873"
inkscape:snap-smooth-nodes="true">
<inkscape:grid
type="xygrid"
id="grid4526" />
</sodipodi:namedview>
<g
id="g873"
transform="matrix(0,1,1,0,-1,0)">
<rect
y="3.46875"
x="8"
height="9.53125"
width="4"
id="rect869"
style="opacity:0.5;fill:#474747;fill-opacity:1;stroke:none;stroke-width:1.2544198;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="ssssssssscccccccccc"
inkscape:connector-curvature="0"
id="path4659-5"
d="M 13,4 C 13,3.057191 11.942809,2 11,2 H 4 C 3.057191,2 2,3.057191 2,4 v 9 c 0,0.942809 1.057191,2 2,2 h 7 c 0.942809,0 2,-1.057191 2,-2 z m -2,0 v 9 H 8 V 4 Z M 7,4 v 9 H 4 V 4 Z"
style="fill:#474747;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
version="1.1"
id="svg8"
sodipodi:docname="ds-touchscreen-right.svg"
inkscape:version="0.92.2 2405546, 2018-03-11">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2560"
inkscape:window-height="1376"
id="namedview10"
showgrid="true"
inkscape:zoom="64"
inkscape:cx="3.6767386"
inkscape:cy="8.1664307"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg8">
<inkscape:grid
type="xygrid"
id="grid4526" />
</sodipodi:namedview>
<g
id="g873">
<rect
y="5.5"
x="7.5"
height="6"
width="6"
id="rect869"
style="opacity:0.5;fill:#474747;fill-opacity:1;stroke:none;stroke-width:1.2544198;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="ssssssssscccccccccc"
inkscape:connector-curvature="0"
id="path4659-5"
d="M 15,6 C 15,5.057191 13.942809,4 13,4 H 2 C 1.057191,4 0,5.057191 0,6 v 5 c 0,0.942809 1.057191,2 2,2 h 11 c 0.942809,0 2,-1.057191 2,-2 z m -2,0 v 5 H 8 V 6 Z M 7,6 v 5 H 2 V 6 Z"
style="fill:#474747;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
version="1.1"
id="svg8"
sodipodi:docname="screen-layout-quick-switch-symbolic.svg"
inkscape:version="0.92.4 5da689c313, 2019-01-14">
<metadata
id="metadata14">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs12" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1016"
id="namedview10"
showgrid="true"
inkscape:zoom="32"
inkscape:cx="8.3953872"
inkscape:cy="9.5898251"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg8">
<inkscape:grid
type="xygrid"
id="grid4526" />
</sodipodi:namedview>
<path
style="opacity:0.5;fill:#474747;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 9,1 c 0.942809,0 1.999979,1.057191 2,2 V 4 H 9 V 3 H 3 v 6 h 1 v 2 H 3 C 2.057191,11 1.000021,9.942809 1,9 V 3 C 0.999979,2.057191 2.057191,1 3,1 Z"
id="path872"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sccccccccsccss" />
<path
sodipodi:nodetypes="sccssccssccccc"
inkscape:connector-curvature="0"
id="path817"
d="m 13,5 c 0.942809,0 1.999979,1.057191 2,2 v 6 c 2.1e-5,0.942809 -1.057191,2 -2,2 H 7 C 6.057191,15 5.000021,13.942809 5,13 V 7 C 4.999979,6.057191 6.057191,5 7,5 Z m 0,2 H 7 v 6 h 6 z"
style="fill:#474747;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,14 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/de/wolfvollprecht/UberWriter/">
<file compressed="true" alias="icons/scalable/status/preview-layout-full-width-symbolic.svg">media/icons/preview-layout-full-width-symbolic.svg</file>
<file compressed="true" alias="icons/scalable/status/preview-layout-half-width-symbolic.svg">media/icons/preview-layout-half-width-symbolic.svg</file>
<file compressed="true" alias="icons/scalable/status/preview-layout-windowed-symbolic.svg">media/icons/preview-layout-windowed-symbolic.svg</file>
<file compressed="true" alias="icons/scalable/status/preview-layout-half-height-symbolic.svg">media/icons/preview-layout-half-height-symbolic.svg</file>
<file compressed="true">media/css/gtk/base.css</file>
<file compressed="true" preprocess="xml-stripblanks">ui/Export.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/ExportPopover.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/Menu.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/Preferences.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/Preview.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/Recents.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/Shortcuts.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/Window.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/Headerbar.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/PreviewLayoutSwitcherItem.ui</file>
<file compressed="true" preprocess="xml-stripblanks">About.ui</file>
</gresource>
</gresources>

View File

@ -584,6 +584,9 @@
<property name="position">1</property>
</packing>
</child>
<style>
<class name="linked"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
@ -591,28 +594,45 @@
</packing>
</child>
</object>
<object class="GtkFileFilter" id="html_filter">
<mime-types>
<mime-type>text/html</mime-type>
</mime-types>
</object>
<object class="GtkFileFilter" id="odt_filter">
<mime-types>
<mime-type>application/vnd.oasis.opendocument.text</mime-type>
</mime-types>
</object>
<object class="GtkFileFilter" id="pdf_filter">
<mime-types>
<mime-type>application/pdf</mime-type>
</mime-types>
</object>
<object class="GtkDialog" id="Export">
<property name="can_focus">False</property>
<property name="type_hint">dialog</property>
<action-widgets>
<action-widget response="cancel">cancel_btn</action-widget>
<action-widget response="1" default="true">export_btn</action-widget>
<action-widget response="accept" default="true">export_btn</action-widget>
</action-widgets>
<child type="titlebar">
<object class="GtkHeaderBar" id="Export_hb">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="has_subtitle">False</property>
<child>
<object class="GtkButton" id="cancel_btn">
<property name="label">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="export_btn">
<property name="label" translatable="yes">Export</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
<child internal-child="vbox">
<object class="GtkBox" id="DialogBox">
<property name="can_focus">False</property>
@ -629,58 +649,12 @@
</packing>
</child>
<child>
<object class="GtkStack" id="export_stack">
<object class="GtkFileChooserWidget" id="advanced">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="transition_type">crossfade</property>
<child>
<object class="GtkFileChooserWidget" id="html">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="action">save</property>
<property name="filter">html_filter</property>
</object>
<packing>
<property name="name">html</property>
<property name="title" translatable="yes">HTML</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="pdf_disabled">
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="name">pdf_disabled</property>
<property name="title" translatable="yes">PDF</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkFileChooserWidget" id="pdf">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="action">save</property>
<property name="filter">pdf_filter</property>
</object>
<packing>
<property name="name">pdf</property>
<property name="title" translatable="yes">PDF</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkFileChooserWidget" id="advanced">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="extra_widget">advanced_export_options</property>
</object>
<packing>
<property name="name">advanced</property>
<property name="title" translatable="yes">Advanced</property>
<property name="position">3</property>
</packing>
</child>
<property name="action">select-folder</property>
<property name="do_overwrite_confirmation">True</property>
<property name="extra_widget">advanced_export_options</property>
</object>
<packing>
<property name="expand">False</property>

View File

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkPopover" id="export_menu">
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin">12</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkModelButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.save_as</property>
<property name="text" translatable="yes">Save as...</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkModelButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.export</property>
<property name="action_target">"pdf"</property>
<property name="text" translatable="yes">Pdf</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkModelButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.export</property>
<property name="action_target">"html"</property>
<property name="text" translatable="yes">Html</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkModelButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.export</property>
<property name="action_target">"odt"</property>
<property name="text" translatable="yes">ODT</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkModelButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.export</property>
<property name="action_target">"advanced"</property>
<property name="text" translatable="yes">Advanced</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

View File

@ -0,0 +1,388 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkPopover">
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkImage" id="exit_fs_icon">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">view-restore-symbolic</property>
</object>
<object class="GtkImage" id="new_icon">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">document-new-symbolic</property>
</object>
<object class="GtkImage" id="preview_icon">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">view-dual-symbolic</property>
</object>
<object class="GtkPopover" id="preview_switcher">
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">12</property>
<property name="margin_bottom">6</property>
<property name="hexpand">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkListBox" id="preview_switch_options">
<property name="visible">True</property>
<property name="can_focus">False</property>
<style>
<class name="plain-listview"/>
</style>
</object>
</child>
<child type="label_item">
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">10</property>
<property name="margin_bottom">12</property>
<property name="spacing">10</property>
<child>
<object class="GtkSwitch" id="sync_scroll_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">6</property>
<property name="label" translatable="yes">Sync views</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkImage" id="search_icon">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">system-search-symbolic</property>
</object>
<object class="GtkRevealer" id="titlebar_revealer">
<property name="name">titlebar-revealer</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
<property name="transition_duration">350</property>
<property name="reveal_child">True</property>
<signal name="size-allocate" handler="header_size_allocate" swapped="no"/>
<child>
<object class="GtkHeaderBar" id="Headerbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">7</property>
<child>
<object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">New</property>
<property name="action_name">app.new</property>
<property name="image">new_icon</property>
</object>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Open</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.open</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkMenuButton" id="recents_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Open Recent</property>
<property name="action_name">app.on_open_recent</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<style>
<class name="linked"/>
</style>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton">
<property name="label" translatable="yes">Save</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.save</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkMenuButton" id="export_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Save as...</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<style>
<class name="linked"/>
</style>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="exit_fs_button">
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="no_show_all">True</property>
<property name="action_name">app.fullscreen</property>
<property name="image">exit_fs_icon</property>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkMenuButton" id="menu_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Menu</property>
<property name="icon_name">open-menu-symbolic</property>
</object>
</child>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">2</property>
<child>
<object class="GtkToggleButton" id="preview_switch_toggle">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Preview</property>
<property name="action_name">app.preview</property>
<property name="image">preview_icon</property>
<property name="always_show_image">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkRevealer" id="preview_switch_revealer">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="transition_type">slide-right</property>
<child>
<object class="GtkMenuButton" id="preview_switch_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="popover">preview_switcher</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkImage" id="preview_switch_toggle_icon">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-copy</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">pan-down-symbolic</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Find</property>
<property name="action_name">app.search</property>
<property name="image">search_icon</property>
<property name="always_show_image">True</property>
</object>
<packing>
<property name="pack_type">end</property>
<property name="position">4</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

View File

@ -1,61 +1,228 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface domain="uberwriter">
<menu id="Menu">
<section>
<item>
<attribute name="label" translatable="yes">Focus Mode</attribute>
<attribute name="action">app.focus_mode</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Hemingway Mode</attribute>
<attribute name="action">app.hemingway_mode</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Preview</attribute>
<attribute name="action">app.preview</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Fullscreen</attribute>
<attribute name="action">app.fullscreen</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">Save As</attribute>
<attribute name="action">app.save_as</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Export</attribute>
<attribute name="action">app.export</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Copy HTML</attribute>
<attribute name="action">app.copy_html</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">Find and Replace</attribute>
<attribute name="action">app.search_replace</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">Preferences</attribute>
<attribute name="action">app.preferences</attribute>
</item>
<item>
<attribute name="action">app.shortcuts</attribute>
<attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Open Tutorial</attribute>
<attribute name="action">app.open_tutorial</attribute>
</item>
<item>
<attribute name="action">app.about</attribute>
<attribute name="label" translatable="yes">_About UberWriter</attribute>
</item>
</section>
</menu>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkPopover" id="Menu">
<property name="can_focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">center</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_bottom">6</property>
<property name="spacing">24</property>
<child>
<object class="GtkRadioButton" id="light_mode_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">center</property>
<property name="draw_indicator">False</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">emblem-ok-symbolic</property>
</object>
</child>
<style>
<class name="color-button"/>
<class name="color-light"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="dark_mode_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">center</property>
<property name="draw_indicator">False</property>
<property name="group">light_mode_button</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">emblem-ok-symbolic</property>
</object>
</child>
<style>
<class name="color-button"/>
<class name="color-dark"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkModelButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.hemingway_mode</property>
<property name="text" translatable="yes">Hemingway mode</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkModelButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.focus_mode</property>
<property name="text" translatable="yes">Focus Mode</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkModelButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.search_replace</property>
<property name="text" translatable="yes">Find and Replace</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">6</property>
</packing>
</child>
<child>
<object class="GtkModelButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.preferences</property>
<property name="text" translatable="yes">Preferences</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">7</property>
</packing>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">8</property>
</packing>
</child>
<child>
<object class="GtkModelButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.open_tutorial</property>
<property name="text" translatable="yes">Open Tutorial</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">9</property>
</packing>
</child>
<child>
<object class="GtkModelButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.shortcuts</property>
<property name="text" translatable="yes">Keyboard Shortcuts</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">10</property>
</packing>
</child>
<child>
<object class="GtkModelButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="action_name">app.about</property>
<property name="text" translatable="yes">About Uberwriter</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">11</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

View File

@ -41,54 +41,6 @@
<property name="margin_bottom">16</property>
<property name="row_spacing">8</property>
<property name="column_spacing">8</property>
<child>
<object class="GtkLabel" id="dark_mode_auto_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Set dark mode automatically</property>
<property name="justify">right</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="dark_mode_auto_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="dark_mode_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Force dark mode</property>
<property name="justify">right</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="dark_mode_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="spellcheck_label">
<property name="visible">True</property>
@ -99,7 +51,7 @@
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
@ -110,55 +62,7 @@
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="gradient_overlay_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Draw scroll gradient</property>
<property name="justify">right</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="gradient_overlay_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="sync_scroll_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Synchronize editor/preview scrolling</property>
<property name="justify">right</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">4</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="sync_scroll_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">4</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
@ -171,7 +75,7 @@
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">5</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
@ -184,7 +88,7 @@
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">5</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
@ -196,17 +100,33 @@
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">5</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<placeholder/>
<object class="GtkLabel" id="autohide_headerbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Autohide header and statusbars while typing</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Autohide headerbar</property>
<property name="justify">right</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
<object class="GtkSwitch" id="autohide_headerbar_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<placeholder/>

View File

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkImage" id="pan-down">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">pan-down-symbolic</property>
<property name="icon_size">2</property>
</object>
<object class="GtkBox" id="preview">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkRevealer" id="preview_mode_revealer">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="transition_type">crossfade</property>
<property name="transition_duration">750</property>
<property name="reveal_child">True</property>
<child>
<object class="GtkButton" id="preview_mode_button">
<property name="label" translatable="yes">Full-Width</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Switch Preview Mode</property>
<property name="halign">end</property>
<property name="image">pan-down</property>
<property name="image_position">right</property>
<property name="always_show_image">True</property>
<style>
<class name="inline-button"/>
</style>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
</interface>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkListBoxRow" id="switcherItem">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="action_name">app.preview_mode</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">4</property>
<property name="margin_bottom">4</property>
<property name="spacing">10</property>
<child>
<object class="GtkImage" id="icon">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="pixel_size">16</property>
<property name="icon_name">preview-layout-full-width-symbolic</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="margin_right">12</property>
<property name="label" translatable="yes">Full-Width</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

View File

@ -17,6 +17,10 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
<property name="margin_left">6</property>
<property name="margin_right">6</property>
<property name="margin_top">6</property>
<property name="margin_bottom">6</property>
<property name="filter">recent_md_filter</property>
<property name="limit">20</property>
<property name="show_icons">False</property>

View File

@ -1,12 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<!-- Generated with glade 3.22.2 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<!-- interface-local-resource-path ../media -->
<object class="GtkImage" id="edit-find-replace">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xpad">12</property>
<property name="icon_name">edit-find-replace-symbolic</property>
</object>
<object class="GtkImage" id="go-up">
@ -30,12 +29,12 @@
<property name="can_focus">False</property>
<property name="stock">gtk-spell-check</property>
</object>
<object class="GtkOverlay" id="FullscreenOverlay">
<object class="GtkOverlay" id="AppOverlay">
<property name="name">FullscreenOverlay</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkGrid" id="grid1">
<object class="GtkGrid" id="app_grid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
@ -71,10 +70,9 @@
<property name="can_focus">False</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkBox" id="editor">
<object class="GtkOverlay" id="editor">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkScrolledWindow" id="editor_scrolledwindow">
<property name="visible">True</property>
@ -87,15 +85,15 @@
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="index">-1</property>
</packing>
</child>
<child>
<child type="overlay">
<object class="GtkRevealer" id="editor_stats_revealer">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_ENTER_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
<property name="valign">end</property>
<property name="transition_type">crossfade</property>
<property name="transition_duration">750</property>
<property name="reveal_child">True</property>
@ -116,11 +114,6 @@
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
@ -236,6 +229,7 @@
<object class="GtkBox" id="searchtools_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkToggleButton" id="case_sensitive">
<property name="label" translatable="yes">aA</property>
@ -414,27 +408,27 @@
<child type="overlay">
<object class="GtkEventBox" id="FullscreenEventbox">
<property name="height_request">1</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
<child>
<object class="GtkRevealer" id="FullscreenHbPlaceholder">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
<child>
<object class="GtkHeaderBar" id="FullscreenHeaderbar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
<placeholder/>
</child>
</object>
</child>
<child type="overlay">
<object class="GtkEventBox" id="HeaderbarEventbox">
<property name="height_request">60</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
<property name="visible_window">False</property>
<property name="above_child">True</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="index">1</property>
</packing>
</child>
</object>
</interface>

View File

@ -5,7 +5,7 @@ project(
)
if get_option('profile') == 'development'
profile = 'Devel'
profile = '.Devel'
name_suffix = ' (Development)'
vcs_tag = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip()
if vcs_tag == ''

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 177 KiB

View File

@ -41,6 +41,7 @@ class Application(Gtk.Application):
Gtk.Application.do_startup(self)
self.settings.connect("changed", self.on_settings_changed)
self._set_dark_mode ()
# Header bar
@ -65,7 +66,6 @@ class Application(Gtk.Application):
self.add_action(action)
# App Menu
action = Gio.SimpleAction.new_stateful(
"focus_mode", None, GLib.Variant.new_boolean(False))
action.connect("change-state", self.on_focus_mode)
@ -90,7 +90,7 @@ class Application(Gtk.Application):
action.connect("activate", self.on_save_as)
self.add_action(action)
action = Gio.SimpleAction.new("export", None)
action = Gio.SimpleAction.new("export", GLib.VariantType("s"))
action.connect("activate", self.on_export)
self.add_action(action)
@ -184,13 +184,22 @@ class Application(Gtk.Application):
self.activate()
return 0
def _set_dark_mode (self):
dark = self.settings.get_value("dark-mode")
settings = Gtk.Settings.get_default()
settings.props.gtk_application_prefer_dark_theme = dark
if settings.props.gtk_theme_name == "HighContrast" and dark:
settings.props.gtk_theme_name = "HighContrastInverse"
elif settings.props.gtk_theme_name == "HighContrastInverse" and not dark:
settings.props.gtk_theme_name = "HighContrast"
def on_settings_changed(self, settings, key):
if key == "dark-mode-auto" or key == "dark-mode":
self.window.apply_current_theme()
if key == "dark-mode":
self._set_dark_mode ()
elif key == "spellcheck":
self.window.toggle_spellcheck(settings.get_value(key))
elif key == "gradient-overlay":
self.window.toggle_gradient_overlay(settings.get_value(key))
elif key == "input-format":
self.window.reload_preview()
elif key == "sync-scroll":
@ -237,8 +246,8 @@ class Application(Gtk.Application):
def on_save_as(self, _action, _value):
self.window.save_document_as()
def on_export(self, _action, _value):
self.window.open_advanced_export()
def on_export(self, _action, value):
self.window.open_advanced_export(value.get_string())
def on_copy_html(self, _action, _value):
self.window.copy_html_to_clipboard()

View File

@ -24,7 +24,7 @@ from gettext import gettext as _
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gtk, GLib
from uberwriter import helpers
from uberwriter.theme import Theme
@ -147,42 +147,101 @@ class Export:
}
]
def __init__(self, filename):
"""Set up the about dialog"""
def __init__(self, filename, export_format, text):
"""Set up the export dialog"""
self.export_menu = {
"pdf":
{
"extension": "pdf",
"name": "PDF",
"mimetype": "application/pdf",
"dialog": self.regular_export_dialog
},
"html":
{
"extension": "html",
"name": "HTML",
"mimetype": "text/html",
"dialog": self.regular_export_dialog
},
"odt":
{
"extension": "odt",
"name": "ODT",
"mimetype": "application/vnd.oasis.opendocument.text",
"dialog": self.regular_export_dialog
},
"advanced":
{
"extension": "",
"name": "",
"mimetype": "",
"dialog": self.advanced_export_dialog
}
}
self.filename = filename or _("Untitled document.md")
self.export_format = export_format
self.dialog = self.export_menu[export_format]["dialog"]()
response = self.dialog.run()
if response == Gtk.ResponseType.ACCEPT:
try:
self.export(export_format, text)
except (NotADirectoryError, Exception) as e:
dialog = Gtk.MessageDialog(None,
Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
Gtk.MessageType.ERROR,
Gtk.ButtonsType.CLOSE,
_("An error happened while trying to export:\n\n{err_msg}")
.format(err_msg= str(e).encode().decode("unicode-escape"))
)
dialog.run()
dialog.destroy()
def regular_export_dialog(self):
texlive_installed = helpers.exist_executable("pdftex")
if (self.export_menu[self.export_format]["extension"] == "pdf" and
not texlive_installed):
dialog = Gtk.MessageDialog(None,
Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
Gtk.MessageType.INFO,
Gtk.ButtonsType.CLOSE,
_("Oh, no!")
)
dialog.props.secondary_text = _("Seems that you don't have TexLive installed.\n" +
disabled_text())
else:
dialog = Gtk.FileChooserNative.new(_("Export"),
None,
Gtk.FileChooserAction.SAVE,
_("Export to %s") %
self.export_menu[self.export_format]["extension"],
_("Cancel"))
dialog_filter = Gtk.FileFilter.new()
dialog_filter.set_name(self.export_menu[self.export_format]["name"])
dialog_filter.add_mime_type(self.export_menu[self.export_format]["mimetype"])
dialog.add_filter(dialog_filter)
dialog.set_do_overwrite_confirmation(True)
dialog.set_current_folder(os.path.dirname(self.filename))
dialog.set_current_name(os.path.basename(self.filename)[:-2] +
self.export_menu[self.export_format]["extension"])
return dialog
def advanced_export_dialog(self):
self.builder = Gtk.Builder()
self.builder.add_from_resource(
"/de/wolfvollprecht/UberWriter/ui/Export.ui")
self.dialog = self.builder.get_object("Export")
self.stack = self.builder.get_object("export_stack")
self.stack_switcher = self.builder.get_object("format_switcher")
self.paper_size = self.builder.get_object("combobox_paper_size")
stack_pdf_disabled = self.builder.get_object("pdf_disabled")
filename = filename or _("Untitled document.md")
self.filechoosers = {export_format: self.stack.get_child_by_name(export_format)
for export_format in ["pdf", "html", "advanced"]}
for export_format, filechooser in self.filechoosers.items():
filechooser.set_do_overwrite_confirmation(True)
filechooser.set_current_folder(os.path.dirname(filename))
if export_format == "advanced":
self.adv_export_name = self.builder.get_object("advanced_export_name")
self.adv_export_name.set_text(os.path.basename(filename)[:-3])
else:
filechooser.set_current_name(os.path.basename(filename)[:-2] + export_format)
# Disable pdf if Texlive not installed
texlive_installed = helpers.exist_executable("pdftex")
if not texlive_installed:
self.filechoosers["pdf"].set_visible(False)
stack_pdf_disabled.set_visible(True)
stack_pdf_disabled.set_text(disabled_text())
stack_pdf_disabled.set_justify(Gtk.Justification.CENTER)
self.stack.connect('notify', self.allow_export, 'visible_child_name')
self.builder.get_object("highlight_style").set_active(0)
self.builder.get_object("css_filechooser").set_uri(
helpers.path_to_file(Theme.get_current().web_css_path))
@ -197,7 +256,14 @@ class Export:
self.format_field.add_attribute(format_renderer, "text", 1)
self.format_field.set_active(0)
def export(self, text=""):
self.adv_export_folder = self.builder.get_object("advanced")
self.adv_export_name = self.builder.get_object("advanced_export_name")
self.adv_export_name.set_text(os.path.basename(self.filename)[:-3])
return self.builder.get_object("Export")
def export(self, export_type, text=""):
"""Export the given text using the specified format.
For advanced export, this includes special flags for the enabled options.
@ -205,11 +271,16 @@ class Export:
text {str} -- Text to export (default: {""})
"""
export_type = self.stack.get_visible_child_name()
args = []
if export_type == "advanced":
filename = self.adv_export_name.get_text()
output_dir = os.path.abspath(self.filechoosers["advanced"].get_current_folder())
# TODO: use walrust operator
output_uri = self.adv_export_folder.get_uri()
if output_uri:
output_dir = GLib.filename_from_uri(output_uri)[0]
else:
raise NotADirectoryError(_("A folder must be selected before proceeding"))
basename = os.path.basename(filename)
fmt = self.formats[self.format_field.get_active()]
@ -227,7 +298,6 @@ class Export:
args = [
"--variable=papersize:a4"
]
filename = self.filechoosers[export_type].get_filename()
if filename.endswith("." + export_type):
filename = filename[:-len(export_type)-1]
output_dir = os.path.abspath(os.path.join(filename, os.path.pardir))
@ -344,19 +414,6 @@ class Export:
return paper_formats[paper_size]
def allow_export(self, widget, data, signal):
"""Disable export button if the visible child is "pdf_disabled"
"""
del widget, data, signal
export_btn = self.builder.get_object("export_btn")
if self.stack.get_visible_child_name() == "pdf_disabled":
export_btn.set_sensitive(False)
else:
export_btn.set_sensitive(True)
def disabled_text():
"""Return the TexLive installation instructions

View File

@ -16,41 +16,236 @@
"""Manage all the headerbars related stuff
"""
from collections import namedtuple
from gettext import gettext as _
import gi
from gettext import gettext as _
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from gi.repository import Gtk, GLib
from uberwriter.helpers import get_descendant
from uberwriter.settings import Settings
class MainHeaderbar: #pylint: disable=too-few-public-methods
class BaseHeaderbar:
"""Base class for all headerbars
"""
# preview modes
FULL_WIDTH = 0
HALF_WIDTH = 1
HALF_HEIGHT = 2
WINDOWED = 3
def __init__(self, app):
self.settings = Settings.new()
self.builder = Gtk.Builder()
self.builder.add_from_resource(
"/de/wolfvollprecht/UberWriter/ui/Headerbar.ui")
self.builder.add_from_resource(
"/de/wolfvollprecht/UberWriter/ui/ExportPopover.ui")
self.hb = self.builder.get_object(
"Headerbar")
self.hb_revealer = self.builder.get_object(
"titlebar_revealer")
self.preview_toggle_revealer = self.builder.get_object(
"preview_switch_revealer")
self.preview_switcher_icon = self.builder.get_object(
"preview_switch_toggle_icon")
self.__populate_layout_switcher_menu()
self.update_preview_layout_icon()
self.sync_scroll_switch = self.builder.get_object("sync_scroll_switch")
self.sync_scroll_switch.set_active(self.settings.get_value("sync-scroll"))
self.sync_scroll_switch.connect("state-set", self.__on_sync_scroll)
self.menu_button = self.builder.get_object("menu_button")
self.recents_button = self.builder.get_object("recents_button")
self.export_button = self.builder.get_object("export_button")
export_popover = self.builder.get_object("export_menu")
self.preview_switch_button = self.builder.get_object("preview_switch_button")
self.export_button.set_popover(export_popover)
add_menus(self, app)
settings = Gtk.Settings.get_default()
# TODO: use walrust operator whenever Python3.8 lands on SDK
# if global_dark:= settings.props.gtk_theme_name.endswith("-dark"):
global_dark = settings.props.gtk_theme_name.endswith("-dark")
if global_dark:
self.light_button.set_sensitive(False)
self.light_button.set_tooltip_text(_(
"Light mode isn't available while using a dark global theme"))
self.dark_button.set_active(self.settings.get_boolean("dark-mode") or global_dark)
self.light_button.connect("toggled", self.__on_dark_mode)
self.select_preview_layout_row()
def update_preview_layout_icon(self):
mode = self.settings.get_enum("preview-mode")
self.preview_switcher_icon.set_from_icon_name(
self.__get_icon_for_preview_mode(mode), 4)
def select_preview_layout_row(self):
mode = self.settings.get_enum("preview-mode")
row = self.preview_menu.get_row_at_index(mode)
self.preview_menu.select_row(row)
def __populate_layout_switcher_menu(self):
self.preview_menu = self.builder.get_object("preview_switch_options")
modes = self.settings.props.settings_schema.get_key("preview-mode").get_range()[1]
for i, mode in enumerate(modes):
item_builder = Gtk.Builder()
item_builder.add_from_resource(
"/de/wolfvollprecht/UberWriter/ui/PreviewLayoutSwitcherItem.ui")
menu_item = item_builder.get_object("switcherItem")
menu_item.label = item_builder.get_object("label")
menu_item.label.set_text(self.__get_text_for_preview_mode(i))
menu_item.icon = item_builder.get_object("icon")
menu_item.icon.set_from_icon_name(self.__get_icon_for_preview_mode(i), 16)
menu_item.set_action_name("app.preview_mode")
menu_item.set_action_target_value(GLib.Variant.new_string(mode))
menu_item.show_all()
self.preview_menu.insert(menu_item, -1)
def __get_text_for_preview_mode(self, mode):
if mode == self.FULL_WIDTH:
return _("Full-Width")
elif mode == self.HALF_WIDTH:
return _("Half-Width")
elif mode == self.HALF_HEIGHT:
return _("Half-Height")
elif mode == self.WINDOWED:
return _("Windowed")
else:
raise ValueError("Unknown preview mode {}".format(mode))
def __get_icon_for_preview_mode(self, mode):
if mode == self.FULL_WIDTH:
return "preview-layout-full-width-symbolic"
elif mode == self.HALF_WIDTH:
return "preview-layout-half-width-symbolic"
elif mode == self.HALF_HEIGHT:
return "preview-layout-half-height-symbolic"
elif mode == self.WINDOWED:
return "preview-layout-windowed-symbolic"
else:
raise ValueError("Unknown preview mode {}".format(mode))
def __on_sync_scroll(self, _, state):
self.settings.set_boolean("sync-scroll", state)
return False
def __on_dark_mode(self, _):
self.settings.set_boolean("dark-mode", self.dark_button.get_active())
class MainHeaderbar(BaseHeaderbar): # pylint: disable=too-few-public-methods
"""Sets up the main application headerbar
"""
def __init__(self, app):
self.hb = Gtk.HeaderBar().new() #pylint: disable=C0103
self.hb.props.show_close_button = True
self.hb.get_style_context().add_class("titlebar")
self.hb_revealer = Gtk.Revealer(name='titlebar-revealer')
self.hb_revealer.add(self.hb)
self.hb_revealer.props.transition_duration = 750
self.hb_revealer.props.transition_type = Gtk.RevealerTransitionType.CROSSFADE
self.hb_revealer.show()
BaseHeaderbar.__init__(self, app)
self.hb.set_show_close_button(True)
self.hb_revealer.props.transition_duration = 0
class FullscreenHeaderbar(BaseHeaderbar):
"""Sets up and manages the fullscreen headerbar and his events
"""
def __init__(self, fs_builder, app):
BaseHeaderbar.__init__(self, app)
self.hb.set_show_close_button(False)
self.exit_fs_button = self.builder.get_object("exit_fs_button")
self.exit_fs_button.set_visible(True)
self.events = fs_builder.get_object("FullscreenEventbox")
self.events.add(self.hb_revealer)
# this is a little tricky
# we show hb when the cursor enters an area of 1px at the top
# as the hb is shown the height of the eventbox grows to accomodate it
self.events.connect('enter_notify_event', self.show_fs_hb)
self.events.connect('leave_notify_event', self.hide_fs_hb)
self.menu_button.get_popover().connect('closed', self.hide_fs_hb)
self.recents_button.get_popover().connect('closed', self.hide_fs_hb)
self.export_button.get_popover().connect('closed', self.hide_fs_hb)
self.preview_switch_button.get_popover().connect('closed', self.hide_fs_hb)
def show_fs_hb(self, _widget=None, _data=None):
"""show headerbar of the fullscreen mode
"""
self.hb_revealer.set_reveal_child(True)
self.hb_container = Gtk.Frame(name='titlebar-container')
self.hb_container.set_shadow_type(Gtk.ShadowType.NONE)
self.hb_container.add(self.hb_revealer)
self.hb_container.show()
def hide_fs_hb(self, _widget=None, _data=None):
"""hide headerbar of the fullscreen mode
"""
if (self.menu_button.get_active() or
self.recents_button.get_active() or
self.export_button.get_active() or
self.preview_switch_button.get_active()):
pass
else:
self.hb_revealer.set_reveal_child(False)
self.btns = main_buttons(app)
pack_main_buttons(self.hb, self.btns)
self.hb.show_all()
class DummyHeaderbar(BaseHeaderbar):
"""Sets up and manages the dummy headerbar wich fades away when entering
the free-distracting mode
"""
def __init__(self, app):
BaseHeaderbar.__init__(self, app)
self.hb.set_show_close_button(True)
self.hb_revealer.set_transition_type(
Gtk.RevealerTransitionType.CROSSFADE)
self.hb_revealer.set_reveal_child(False)
self.menu_button.set_sensitive(True)
self.recents_button.set_sensitive(True)
def show_dm_hb(self):
"""show dummy headerbar:
It appears instantly to inmediatly fade away
"""
self.hb_revealer.show()
self.hb_revealer.set_transition_duration(0)
self.hb_revealer.set_reveal_child(True)
self.hb_revealer.set_transition_duration(600)
self.hb_revealer.set_reveal_child(False)
def hide_dm_hb(self):
"""hide dummy headerbar
It appears slowly to inmediatly dissapear
"""
self.hb_revealer.set_transition_duration(400)
self.hb_revealer.set_reveal_child(True)
GLib.timeout_add(400, self.hide_dm_hb_with_wait)
def hide_dm_hb_with_wait(self):
self.hb_revealer.set_transition_duration(0)
self.hb_revealer.set_reveal_child(False)
self.hb_revealer.hide()
return False
class PreviewHeaderbar:
@ -62,10 +257,11 @@ class PreviewHeaderbar:
self.hb.props.show_close_button = True
self.hb.get_style_context().add_class("titlebar")
self.hb_revealer = Gtk.Revealer(name="titlebar-revealer")
self.hb_revealer = Gtk.Revealer(name="titlebar-revealer-pv")
self.hb_revealer.add(self.hb)
self.hb_revealer.props.transition_duration = 750
self.hb_revealer.props.transition_type = Gtk.RevealerTransitionType.CROSSFADE
self.hb_revealer.set_transition_type(
Gtk.RevealerTransitionType.CROSSFADE)
self.hb_revealer.show()
self.hb_revealer.set_reveal_child(True)
@ -77,76 +273,22 @@ class PreviewHeaderbar:
self.hb.show_all()
class FullscreenHeaderbar:
"""Sets up and manages the fullscreen headerbar and his events
def add_menus(headerbar, app):
""" Add menu models to hb buttons
"""
def __init__(self, builder, app):
self.events = builder.get_object("FullscreenEventbox")
self.revealer = builder.get_object(
"FullscreenHbPlaceholder")
self.revealer.show()
self.revealer.set_reveal_child(False)
self.hb = builder.get_object("FullscreenHeaderbar") #pylint: disable=C0103
self.hb.get_style_context().add_class("titlebar")
self.hb.show()
self.events.hide()
self.btns = main_buttons(app)
fs_btn_exit = Gtk.Button().new_from_icon_name("view-restore-symbolic",
Gtk.IconSize.BUTTON)
fs_btn_exit.set_tooltip_text(_("Exit Fullscreen"))
fs_btn_exit.set_action_name("app.fullscreen")
pack_main_buttons(self.hb, self.btns, fs_btn_exit)
self.hb.show_all()
# this is a little tricky
# we show hb when the cursor enters an area of 1 px at the top of the window
# as the hb is shown the height of the eventbox grows to accomodate it
self.events.connect('enter_notify_event', self.show_fs_hb)
self.events.connect('leave_notify_event', self.hide_fs_hb)
self.btns.menu.get_popover().connect('closed', self.hide_fs_hb)
def show_fs_hb(self, _widget, _data=None):
"""show headerbar of the fullscreen mode
"""
self.revealer.set_reveal_child(True)
def hide_fs_hb(self, _widget, _data=None):
"""hide headerbar of the fullscreen mode
"""
if self.btns.menu.get_active():
pass
else:
self.revealer.set_reveal_child(False)
def main_buttons(app):
"""constructor for the headerbar buttons
Returns:
[NamedTupple] -- tupple of Gtk.Buttons
"""
Button = namedtuple("Button", "new open_recent save search menu")
btn = Button(Gtk.Button().new_with_label(_("New")),
Gtk.Box().new(0, 0),
Gtk.Button().new_with_label(_("Save")),
Gtk.Button().new_from_icon_name("system-search-symbolic",
Gtk.IconSize.BUTTON),
Gtk.MenuButton().new())
# Add menu model to the menu button
builder_window_menu = Gtk.Builder()
builder_window_menu.add_from_resource(
"/de/wolfvollprecht/UberWriter/ui/Menu.ui")
model = builder_window_menu.get_object("Menu")
headerbar.light_button = builder_window_menu.get_object("light_mode_button")
headerbar.dark_button = builder_window_menu.get_object("dark_mode_button")
open_button = Gtk.Button().new_with_label(_("Open"))
open_button.set_action_name("app.open")
headerbar.menu_button.set_popover(model)
# Add recents menu to the open recents button
recents_builder = Gtk.Builder()
recents_builder.add_from_resource(
@ -159,44 +301,5 @@ def main_buttons(app):
recents_wd = recents_builder.get_object("recent_md_widget")
recents_wd.connect('item-activated', app.on_open_recent)
recents_button = Gtk.MenuButton().new()
recents_button.set_image(Gtk.Image.new_from_icon_name("pan-down-symbolic",
Gtk.IconSize.BUTTON))
recents_button.set_tooltip_text(_("Open Recent"))
recents_button.set_popover(recents)
btn.open_recent.get_style_context().add_class("linked")
btn.open_recent.pack_start(open_button, False, False, 0)
btn.open_recent.pack_end(recents_button, False, False, 0)
btn.search.set_tooltip_text(_("Find"))
btn.menu.set_tooltip_text(_("Menu"))
btn.menu.set_image(Gtk.Image.new_from_icon_name("open-menu-symbolic",
Gtk.IconSize.BUTTON))
btn.menu.set_use_popover(True)
btn.menu.set_menu_model(model)
btn.new.set_action_name("app.new")
btn.save.set_action_name("app.save")
btn.search.set_action_name("app.search")
return btn
def pack_main_buttons(headerbar, btn, btn_exit=None):
"""Pack the given buttons in the given headerbar
Arguments:
headerbar {Gtk.HeaderBar} -- The headerbar where to put the buttons
btn {Tupple of Gtk.Buttons} -- The buttons to pack
Keyword Arguments:
btn_exit {Gtk.Button} -- Optional exit fullscreen button (default: {None})
"""
headerbar.pack_start(btn.new)
headerbar.pack_start(btn.open_recent)
if btn_exit:
headerbar.pack_end(btn_exit)
headerbar.pack_end(btn.menu)
headerbar.pack_end(btn.search)
headerbar.pack_end(btn.save)
headerbar.recents_button.set_popover(recents)
headerbar.recents_button.set_sensitive(True)

View File

@ -35,7 +35,6 @@ from gi.repository import Gtk, Gdk, GObject, GLib, Gio
import cairo
from uberwriter import helpers
from uberwriter.theme import Theme
from uberwriter.sidebar import Sidebar
from uberwriter.search_and_replace import SearchAndReplace
@ -74,7 +73,7 @@ class MainWindow(StyledWindow):
builder = Gtk.Builder()
builder.add_from_resource(
"/de/wolfvollprecht/UberWriter/ui/Window.ui")
root = builder.get_object("FullscreenOverlay")
root = builder.get_object("AppOverlay")
self.connect("delete-event", self.on_delete_called)
self.add(root)
@ -84,18 +83,35 @@ class MainWindow(StyledWindow):
self.settings = Settings.new()
# Headerbars
self.last_height = 0
self.headerbar = headerbars.MainHeaderbar(app)
self.set_titlebar(self.headerbar.hb_container)
self.headerbar.hb_revealer.connect(
"size_allocate", self.header_size_allocate)
self.set_titlebar(self.headerbar.hb_revealer)
self.fs_headerbar = headerbars.FullscreenHeaderbar(builder, app)
# Bind properties between normal and fs headerbar
self.headerbar.light_button.bind_property(
"active", self.fs_headerbar.light_button, "active",
GObject.BindingFlags.BIDIRECTIONAL
| GObject.BindingFlags.SYNC_CREATE)
self.headerbar.dark_button.bind_property(
"active", self.fs_headerbar.dark_button, "active",
GObject.BindingFlags.BIDIRECTIONAL
| GObject.BindingFlags.SYNC_CREATE)
# The dummy headerbar is a cosmetic hack to be able to
# crossfade the hb on top of the window
self.dm_headerbar = headerbars.DummyHeaderbar(app)
root.add_overlay(self.dm_headerbar.hb_revealer)
root.reorder_overlay(self.dm_headerbar.hb_revealer, 0)
root.set_overlay_pass_through(self.dm_headerbar.hb_revealer, True)
self.title_end = " UberWriter"
self.set_headerbar_title("New File" + self.title_end)
self.timestamp_last_mouse_motion = 0
if self.settings.get_value("poll-motion"):
self.connect("motion-notify-event", self.on_motion_notify)
GObject.timeout_add(3000, self.poll_for_motion)
self.accel_group = Gtk.AccelGroup()
self.add_accel_group(self.accel_group)
@ -103,6 +119,7 @@ class MainWindow(StyledWindow):
# Setup text editor
self.text_view = TextView(self.settings.get_int("characters-per-line"))
self.text_view.set_top_margin(80)
self.text_view.connect('focus-out-event', self.focus_out)
self.text_view.get_buffer().connect('changed', self.on_text_changed)
self.text_view.show()
@ -119,16 +136,11 @@ class MainWindow(StyledWindow):
editor = builder.get_object('editor')
self.preview_handler = PreviewHandler(self, content, editor, self.text_view)
# Setup header/stats bar hide after 3 seconds
self.top_bottom_bars_visible = True
self.was_motion = True
# Setup header/stats bar
self.headerbar_visible = True
self.bottombar_visible = True
self.buffer_modified_for_status_bar = False
# some people seems to have performance problems with the overlay.
# Let them disable it
self.overlay_id = None
self.toggle_gradient_overlay(self.settings.get_value("gradient-overlay"))
# Init file name with None
self.set_filename()
@ -151,6 +163,32 @@ class MainWindow(StyledWindow):
###
self.searchreplace = SearchAndReplace(self, self.text_view, builder)
# EventBoxes
self.headerbar_eventbox = builder.get_object("HeaderbarEventbox")
self.headerbar_eventbox.connect('enter_notify_event',
self.reveal_headerbar_bottombar)
self.stats_revealer.connect('enter_notify_event', self.reveal_bottombar)
def header_size_allocate(self, widget, allocation):
""" When the main hb starts to shrink its size, add that size
to the textview margin, so it stays in place
"""
# prevent 1px jumps
if allocation.height == 1 and not widget.get_child_revealed():
allocation.height = 0
height = self.headerbar.hb.get_allocated_height() - allocation.height
if height == self.last_height:
return
self.last_height = height
self.text_view.update_vertical_margin(height)
self.text_view.queue_draw()
def on_text_changed(self, *_args):
"""called when the text changes, sets the self.did_change to true and
updates the title and the counters to reflect that
@ -162,6 +200,8 @@ class MainWindow(StyledWindow):
self.set_headerbar_title("* " + title)
self.buffer_modified_for_status_bar = True
if self.settings.get_value("autohide-headerbar"):
self.hide_headerbar_bottombar()
def set_fullscreen(self, state):
"""Puts the application in fullscreen mode and show/hides
@ -174,16 +214,19 @@ class MainWindow(StyledWindow):
if state.get_boolean():
self.fullscreen()
self.fs_headerbar.events.show()
self.fs_headerbar.hide_fs_hb()
self.headerbar_eventbox.hide()
else:
self.unfullscreen()
self.fs_headerbar.events.hide()
self.headerbar_eventbox.show()
self.text_view.grab_focus()
def set_focus_mode(self, state):
"""toggle focusmode
"""
self.text_view.set_focus_mode(state.get_boolean())
self.text_view.set_focus_mode(state.get_boolean(), self.headerbar.hb.get_allocated_height())
self.text_view.grab_focus()
def set_hemingway_mode(self, state):
@ -203,9 +246,15 @@ class MainWindow(StyledWindow):
if state.get_boolean():
self.text_view.grab_focus()
self.preview_handler.show()
self.headerbar.preview_toggle_revealer.set_reveal_child(True)
self.fs_headerbar.preview_toggle_revealer.set_reveal_child(True)
self.dm_headerbar.preview_toggle_revealer.set_reveal_child(True)
else:
self.preview_handler.hide()
self.text_view.grab_focus()
self.headerbar.preview_toggle_revealer.set_reveal_child(False)
self.fs_headerbar.preview_toggle_revealer.set_reveal_child(False)
self.dm_headerbar.preview_toggle_revealer.set_reveal_child(False)
return True
@ -258,7 +307,7 @@ class MainWindow(StyledWindow):
self.set_filename(filename)
self.set_headerbar_title(
os.path.basename(filename) + self.title_end)
os.path.basename(filename) + self.title_end, filename)
self.did_change = False
filechooser.destroy()
@ -299,7 +348,7 @@ class MainWindow(StyledWindow):
self.set_filename(filename)
self.set_headerbar_title(
os.path.basename(filename) + self.title_end)
os.path.basename(filename) + self.title_end, filename)
try:
self.recent_manager.add_item(filename)
@ -360,16 +409,27 @@ class MainWindow(StyledWindow):
"""Show dialog to prevent loss of unsaved changes
"""
if self.filename:
title = os.path.basename(self.filename)
else:
title = _("New File")
if self.did_change and self.text_view.get_text():
dialog = Gtk.MessageDialog(self,
Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
Gtk.MessageType.WARNING,
Gtk.ButtonsType.NONE,
_("You have not saved your changes.")
_("Save changes to document “%s” before closing?") %
title
)
dialog.add_button(_("Close without saving"), Gtk.ResponseType.NO)
dialog.props.secondary_text = _("If you dont save, " +
"all your changes will be permanently lost.")
close_button = dialog.add_button(_("Close without saving"), Gtk.ResponseType.NO)
dialog.add_button(_("Cancel"), Gtk.ResponseType.CANCEL)
dialog.add_button(_("Save now"), Gtk.ResponseType.YES)
close_button.get_style_context().add_class("destructive-action")
# dialog.set_default_size(200, 60)
dialog.set_default_response(Gtk.ResponseType.YES)
response = dialog.run()
@ -405,6 +465,10 @@ class MainWindow(StyledWindow):
def update_preview_mode(self):
self.preview_handler.update_preview_mode()
self.headerbar.update_preview_layout_icon()
self.headerbar.select_preview_layout_row()
self.fs_headerbar.update_preview_layout_icon()
self.fs_headerbar.select_preview_layout_row()
def menu_toggle_sidebar(self, _widget=None):
"""WIP
@ -420,18 +484,6 @@ class MainWindow(StyledWindow):
self.text_view.set_spellcheck(state.get_boolean())
def toggle_gradient_overlay(self, state):
"""Toggle the gradient overlay
Arguments:
state {gtk bool} -- Desired state of the gradient overlay (enabled/disabled)
"""
if state.get_boolean():
self.overlay_id = self.scrolled_window.connect_after("draw", self.draw_gradient)
elif self.overlay_id:
self.scrolled_window.disconnect(self.overlay_id)
def reload_preview(self, reshow=False):
self.preview_handler.reload(reshow=reshow)
@ -443,7 +495,8 @@ class MainWindow(StyledWindow):
if filename:
if filename.startswith('file://'):
filename = urllib.parse.unquote(filename)[7:]
filename = filename[7:]
filename = urllib.parse.unquote_plus(filename)
self.text_view.clear()
try:
if os.path.exists(filename):
@ -460,7 +513,7 @@ class MainWindow(StyledWindow):
dialog.run()
dialog.destroy()
self.set_headerbar_title(os.path.basename(filename) + self.title_end)
self.set_headerbar_title(os.path.basename(filename) + self.title_end, filename)
self.set_filename(filename)
except Exception as e:
@ -492,29 +545,12 @@ class MainWindow(StyledWindow):
self.searchreplace.toggle_search(replace=replace)
def open_advanced_export(self, _widget=None, _data=None):
def open_advanced_export(self, export_format):
"""open the export and advanced export dialog
"""
text = bytes(self.text_view.get_text(), "utf-8")
self.export = Export(self.filename)
self.export.dialog.set_transient_for(self)
response = self.export.dialog.run()
if response == 1:
try:
self.export.export(bytes(self.text_view.get_text(), "utf-8"))
except Exception as e:
dialog = Gtk.MessageDialog(self,
Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
Gtk.MessageType.ERROR,
Gtk.ButtonsType.CLOSE,
_("An error happened while trying to export:\n\n{err_msg}")
.format(err_msg= str(e).encode().decode("unicode-escape"))
)
dialog.run()
dialog.destroy()
self.export.dialog.destroy()
self.export = Export(self.filename, export_format, text)
def open_recent(self, _widget, data=None):
"""open the given recent document
@ -525,79 +561,52 @@ class MainWindow(StyledWindow):
return
self.load_file(data)
def poll_for_motion(self):
"""check if the user has moved the cursor to show the headerbar
Returns:
True -- Gtk things
"""
if (not self.was_motion
and self.buffer_modified_for_status_bar
and self.text_view.props.has_focus):
self.reveal_top_bottom_bars(False)
self.was_motion = False
return True
def on_motion_notify(self, _widget, event, _data=None):
"""check the motion of the mouse to fade in the headerbar
"""
now = event.get_time()
if now - self.timestamp_last_mouse_motion > 150:
# filter out accidental motions
self.timestamp_last_mouse_motion = now
return
if now - self.timestamp_last_mouse_motion < 100:
# filter out accidental motion
return
if now - self.timestamp_last_mouse_motion > 100:
# react on motion by fading in headerbar and statusbar
self.reveal_top_bottom_bars(True)
self.was_motion = True
def focus_out(self, _widget, _data=None):
"""events called when the window losses focus
"""
self.reveal_top_bottom_bars(True)
self.reveal_headerbar_bottombar()
def reveal_top_bottom_bars(self, reveal):
if self.top_bottom_bars_visible != reveal:
self.headerbar.hb_revealer.set_reveal_child(reveal)
self.stats_revealer.set_reveal_child(reveal)
for revealer in self.preview_handler.get_top_bottom_bar_revealers():
revealer.set_reveal_child(reveal)
self.top_bottom_bars_visible = reveal
self.buffer_modified_for_status_bar = reveal
def reveal_headerbar_bottombar(self, _widget=None, _data=None):
def draw_gradient(self, _widget, cr):
"""draw fading gradient over the top and the bottom of the
TextWindow
"""
bg_color = self.get_style_context().get_background_color(Gtk.StateFlags.ACTIVE)
def __reveal_hb():
self.headerbar_eventbox.hide()
self.headerbar.hb_revealer.set_reveal_child(True)
self.get_style_context().remove_class("focus")
return False
lg_top = cairo.LinearGradient(0, 0, 0, 32) # pylint: disable=no-member
lg_top.add_color_stop_rgba(
0, bg_color.red, bg_color.green, bg_color.blue, 1)
lg_top.add_color_stop_rgba(
1, bg_color.red, bg_color.green, bg_color.blue, 0)
self.reveal_bottombar()
width = self.scrolled_window.get_allocation().width
height = self.scrolled_window.get_allocation().height
if not self.headerbar_visible:
self.dm_headerbar.hide_dm_hb()
GLib.timeout_add(400, __reveal_hb)
cr.rectangle(0, 0, width, 32)
cr.set_source(lg_top)
cr.fill()
cr.rectangle(0, height - 32, width, height)
self.headerbar_visible = True
lg_btm = cairo.LinearGradient(0, height - 32, 0, height) # pylint: disable=no-member
lg_btm.add_color_stop_rgba(
1, bg_color.red, bg_color.green, bg_color.blue, 1)
lg_btm.add_color_stop_rgba(
0, bg_color.red, bg_color.green, bg_color.blue, 0)
def reveal_bottombar(self, _widget=None, _data=None):
cr.set_source(lg_btm)
cr.fill()
if not self.bottombar_visible:
self.stats_revealer.set_reveal_child(True)
self.bottombar_visible = True
self.buffer_modified_for_status_bar = True
def hide_headerbar_bottombar(self):
if self.headerbar_visible:
self.headerbar.hb_revealer.set_reveal_child(False)
self.dm_headerbar.show_dm_hb()
self.get_style_context().add_class("focus")
self.headerbar_visible = False
if self.bottombar_visible:
self.stats_revealer.set_reveal_child(False)
self.bottombar_visible = False
self.headerbar_eventbox.show()
self.buffer_modified_for_status_bar = False
def on_delete_called(self, _widget, _data=None):
"""Called when the TexteditorWindow is closed.
@ -616,11 +625,18 @@ class MainWindow(StyledWindow):
self.destroy()
return
def set_headerbar_title(self, title):
def set_headerbar_title(self, title, subtitle=None):
"""set the desired headerbar title
"""
self.headerbar.hb.props.title = title
self.dm_headerbar.hb.props.title = title
self.fs_headerbar.hb.props.title = title
if subtitle:
self.headerbar.hb.props.subtitle = subtitle
self.dm_headerbar.hb.props.subtitle = subtitle
self.fs_headerbar.hb.props.subtitle = subtitle
self.headerbar.hb.set_tooltip_text(subtitle)
self.fs_headerbar.hb.set_tooltip_text(subtitle)
self.set_title(title)
def set_filename(self, filename=None):

View File

@ -67,26 +67,14 @@ class PreferencesDialog:
self.builder.add_from_resource(
"/de/wolfvollprecht/UberWriter/ui/Preferences.ui")
self.dark_mode_auto_switch = self.builder.get_object("dark_mode_auto_switch")
self.dark_mode_auto_switch.set_active(self.settings.get_value("dark-mode-auto"))
self.dark_mode_auto_switch.connect("state-set", self.on_dark_mode_auto)
self.dark_mode_switch = self.builder.get_object("dark_mode_switch")
self.dark_mode_switch.set_active(self.settings.get_value("dark-mode"))
self.dark_mode_switch.connect("state-set", self.on_dark_mode)
self.autohide_headerbar_switch = self.builder.get_object("autohide_headerbar_switch")
self.autohide_headerbar_switch.set_active(self.settings.get_value("autohide-headerbar"))
self.autohide_headerbar_switch.connect("state-set", self.on_autohide_headerbar)
self.spellcheck_switch = self.builder.get_object("spellcheck_switch")
self.spellcheck_switch.set_active(self.settings.get_value("spellcheck"))
self.spellcheck_switch.connect("state-set", self.on_spellcheck)
self.gradient_overlay_switch = self.builder.get_object("gradient_overlay_switch")
self.gradient_overlay_switch.set_active(self.settings.get_value("gradient-overlay"))
self.gradient_overlay_switch.connect("state-set", self.on_gradient_overlay)
self.sync_scroll_switch = self.builder.get_object("sync_scroll_switch")
self.sync_scroll_switch.set_active(self.settings.get_value("sync-scroll"))
self.sync_scroll_switch.connect("state-set", self.on_sync_scroll)
input_format_store = Gtk.ListStore(int, str)
input_format = self.settings.get_string("input-format")
input_format_active = 0
@ -111,30 +99,14 @@ class PreferencesDialog:
preferences_window.set_transient_for(window)
preferences_window.show()
def on_dark_mode_auto(self, _, state):
self.settings.set_boolean("dark-mode-auto", state)
if state and self.dark_mode_switch.get_active():
self.dark_mode_switch.set_active(GLib.Variant.new_boolean(False))
return False
def on_dark_mode(self, _, state):
self.settings.set_boolean("dark-mode", state)
if state and self.dark_mode_auto_switch.get_active():
self.dark_mode_auto_switch.set_active(GLib.Variant.new_boolean(False))
def on_autohide_headerbar(self, _, state):
self.settings.set_boolean("autohide-headerbar", state)
return False
def on_spellcheck(self, _, state):
self.settings.set_boolean("spellcheck", state)
return False
def on_gradient_overlay(self, _, state):
self.settings.set_boolean("gradient-overlay", state)
return False
def on_sync_scroll(self, _, state):
self.settings.set_boolean("sync-scroll", state)
return False
def on_input_format(self, combobox):
fmt = self.formats[combobox.get_active()]
self.settings.set_string("input-format", fmt["format"])

View File

@ -32,16 +32,9 @@ class PreviewHandler:
self.web_view = None
self.web_view_pending_html = None
builder = Gtk.Builder()
builder.add_from_resource(
"/de/wolfvollprecht/UberWriter/ui/Preview.ui")
preview = builder.get_object("preview")
mode_button = builder.get_object("preview_mode_button")
self.mode_revealer = builder.get_object("preview_mode_revealer")
self.preview_converter = PreviewConverter()
self.preview_renderer = PreviewRenderer(
window, content, editor, text_view, preview, self.mode_revealer, mode_button)
window, content, editor, text_view)
window.connect("style-updated", self.reload)
@ -135,12 +128,6 @@ class PreviewHandler:
def update_preview_mode(self):
self.preview_renderer.update_mode(self.web_view)
def get_top_bottom_bar_revealers(self):
if self.shown and not self.preview_renderer.window:
return [self.mode_revealer]
else:
return []
def on_load_changed(self, _web_view, event):
if event == WebKit2.LoadEvent.FINISHED:
self.loading = False

View File

@ -17,16 +17,12 @@ class PreviewRenderer:
WINDOWED = 3
def __init__(
self, main_window, content, editor, text_view, preview, mode_revealer, mode_button):
self, main_window, content, editor, text_view):
self.main_window = main_window
self.main_window.connect("delete-event", self.on_window_closed)
self.content = content
self.editor = editor
self.text_view = text_view
self.preview = preview
self.mode_revealer = mode_revealer
self.mode_button = mode_button
self.mode_button.connect("clicked", self.show_mode_popover)
self.settings = Settings.new()
self.popover = None
@ -49,9 +45,6 @@ class PreviewRenderer:
headerbar = headerbars.PreviewHeaderbar()
self.headerbar = headerbar.hb
self.headerbar.set_title(_("Preview"))
self.mode_button.get_style_context().remove_class("inline-button")
self.mode_revealer.remove(self.mode_button)
self.headerbar.pack_end(self.mode_button)
self.window.set_titlebar(headerbar.hb_container)
# Position it next to the main window.
@ -67,8 +60,7 @@ class PreviewRenderer:
self.window.show()
else:
self.preview.pack_start(web_view, True, True, 0)
self.content.add(self.preview)
self.content.pack_start(web_view, True, True, 0)
# Full-width preview: swap editor with preview.
if self.mode == self.FULL_WIDTH:
@ -97,17 +89,13 @@ class PreviewRenderer:
# Windowed preview: remove preview and destroy window.
if self.mode == self.WINDOWED:
self.main_window.present()
self.headerbar.remove(self.mode_button)
self.mode_button.get_style_context().add_class("inline-button")
self.mode_revealer.add(self.mode_button)
self.headerbar = None
self.window.remove(web_view)
self.window.destroy()
self.window = None
else:
self.preview.remove(web_view)
self.content.remove(self.preview)
self.content.remove(web_view)
# Full-width preview: swap preview with editor.
if self.mode == self.FULL_WIDTH:
@ -130,32 +118,6 @@ class PreviewRenderer:
self.show(web_view)
else:
self.mode = mode
if self.mode_button:
text = self.get_text_for_preview_mode(self.mode)
self.mode_button.set_label(text)
if self.popover:
self.popover.popdown()
def show_mode_popover(self, button):
"""Show preview mode popover."""
self.mode_button.set_state_flags(Gtk.StateFlags.CHECKED, False)
menu = Gio.Menu()
modes = self.settings.props.settings_schema.get_key("preview-mode").get_range()[1]
for i, mode in enumerate(modes):
menu_item = Gio.MenuItem.new(self.get_text_for_preview_mode(i), None)
menu_item.set_action_and_target_value("app.preview_mode", GLib.Variant.new_string(mode))
menu.append_item(menu_item)
self.popover = Gtk.Popover.new_from_model(button, menu)
self.popover.connect('closed', self.on_popover_closed)
self.popover.popup()
def on_popover_closed(self, _popover):
self.mode_button.unset_state_flags(Gtk.StateFlags.CHECKED)
self.popover = None
self.text_view.grab_focus()
def on_window_closed(self, window, _event):
preview_action = window.get_application().lookup_action("preview")

View File

@ -62,6 +62,8 @@ if (canScroll && isRendered) {{
self.connect("load-failed", self.on_load_failed)
self.connect("destroy", self.on_destroy)
self.props.expand = True
self.scroll_scale = -1
self.state_loaded = False

View File

@ -1,7 +1,6 @@
import gi
from uberwriter import helpers
from uberwriter.theme import Theme
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib, Gio
@ -13,27 +12,11 @@ class StyledWindow(Gtk.ApplicationWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.connect("style-updated", self.apply_current_theme)
self.apply_current_theme()
def apply_current_theme(self, *_):
"""Adjusts the window, CSD and preview for the current theme."""
# Get current theme
theme, changed = Theme.get_current_changed()
if changed:
# Set theme variant (dark/light)
Gtk.Settings.get_default().set_property(
"gtk-application-prefer-dark-theme",
GLib.Variant("b", theme.is_dark))
# Set theme css
css_provider_file = Gio.File.new_for_uri(
"resource:///de/wolfvollprecht/UberWriter/media/css/gtk/base.css")
style_provider = Gtk.CssProvider()
style_provider.load_from_file(css_provider_file)
Gtk.StyleContext.add_provider_for_screen(
self.get_screen(), style_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
# Redraw contents of window
self.queue_draw()
# Set theme css
css_provider_file = Gio.File.new_for_uri(
"resource:///de/wolfvollprecht/UberWriter/media/css/gtk/base.css")
style_provider = Gtk.CssProvider()
style_provider.load_from_file(css_provider_file)
Gtk.StyleContext.add_provider_for_screen(
self.get_screen(), style_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

View File

@ -54,6 +54,9 @@ class TextView(Gtk.TextView):
self.set_pixels_inside_wrap(8)
self.get_style_context().add_class('uberwriter-editor')
self.set_margin_left(8)
self.set_margin_right(8)
# Text sizing
self.props.halign = Gtk.Align.FILL
self.line_chars = line_chars
@ -144,7 +147,6 @@ class TextView(Gtk.TextView):
def on_size_allocate(self, *_):
self.update_horizontal_margin()
self.update_vertical_margin()
self.markup.update_margins_indents()
self.queue_draw()
@ -192,14 +194,14 @@ class TextView(Gtk.TextView):
self.frozen_scroll_scale = None
self.queue_draw()
def set_focus_mode(self, focus_mode):
def set_focus_mode(self, focus_mode, hb_height):
"""Toggle focus mode.
When in focus mode, the cursor sits in the middle of the text view,
and the surrounding text is greyed out."""
self.focus_mode = focus_mode
self.update_vertical_margin()
self.update_vertical_margin(hb_size=hb_height)
self.markup.apply()
self.smooth_scroll_to()
self.set_spellcheck(self.spellcheck)
@ -227,13 +229,14 @@ class TextView(Gtk.TextView):
self.props.left_margin = horizontal_margin
self.props.right_margin = horizontal_margin
def update_vertical_margin(self):
def update_vertical_margin(self, top_margin=0, hb_size=0):
if self.focus_mode:
height = self.get_allocation().height
self.props.top_margin = height / 2
self.props.bottom_margin = height / 2
height = self.get_allocation().height + top_margin + hb_size
self.props.top_margin = height / 2 + top_margin
self.props.bottom_margin = height / 2 - top_margin
else:
self.props.top_margin = 80
self.props.top_margin = 80 + top_margin
self.props.bottom_margin = 64
def set_hemingway_mode(self, hemingway_mode):

View File

@ -31,10 +31,9 @@ class Theme:
@classmethod
def get_current_changed(cls):
theme_name = Gtk.Settings.get_default().get_property('gtk-theme-name')
dark_mode_auto = cls.settings.get_boolean('dark-mode-auto')
dark_mode = cls.settings.get_boolean('dark-mode')
current_theme = cls.get_for_name(theme_name)
if not dark_mode_auto and dark_mode != current_theme.is_dark and current_theme.inverse_name:
if dark_mode != current_theme.is_dark and current_theme.inverse_name:
current_theme = cls.get_for_name(current_theme.inverse_name, current_theme.name)
changed = current_theme != cls.previous
cls.previous = current_theme
@ -56,11 +55,11 @@ class Theme:
defaultThemes = [
# https://gitlab.gnome.org/GNOME/gtk/tree/master/gtk/theme/Adwaita
Theme('Adwaita', get_css_path('web/adwaita.css'), False, 'Adwaita-dark'),
Theme('Adwaita-dark', get_css_path('web/adwaita_dark.css'), True, 'Adwaita'),
Theme('Adwaita-dark', get_css_path('web/adwaita.css'), True, 'Adwaita'),
# https://github.com/NicoHood/arc-theme/tree/master/common/gtk-3.0/3.20/sass
Theme('Arc', get_css_path('web/arc.css'), False, 'Arc-Dark'),
Theme('Arc-Darker', get_css_path('web/arc_darker.css'), False, 'Arc-Dark'),
Theme('Arc-Dark', get_css_path('web/arc_dark.css'), True, 'Arc'),
Theme('Arc-Darker', get_css_path('web/arc.css'), False, 'Arc-Dark'),
Theme('Arc-Dark', get_css_path('web/arc.css'), True, 'Arc'),
# https://gitlab.gnome.org/GNOME/gtk/tree/master/gtk/theme/HighContrast
Theme('HighContrast', get_css_path('web/highcontrast.css'), False, 'HighContrastInverse'),
Theme('HighContrastInverse', get_css_path('web/highcontrast_inverse.css'), True, 'HighContrast')