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 *.pyc
__pycache__/ __pycache__/
_build/*
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/ .vscode/
.idea/ .idea/
*.glade~
dist/uberwriter-2.0b0-py3.7.egg
builddir/* builddir/*
dist/ build-aux/*
uberwriter.egg-info flatpak/*
build-aux/flatpak/.flatpak-builder/*

View File

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

View File

@ -3,7 +3,7 @@
<id>@app-id@</id> <id>@app-id@</id>
<launchable type="desktop-id">@app-id@.desktop</launchable> <launchable type="desktop-id">@app-id@.desktop</launchable>
<name>UberWriter</name> <name>UberWriter</name>
<summary>An elegant, free distraction GTK+ markdown editor</summary> <summary>An elegant, distraction-free GTK+ markdown editor</summary>
<description> <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>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> <p>You can install the recommended TexLive extension with the command:</p>

View File

@ -18,17 +18,9 @@
</enum> </enum>
<schema path="/de/wolfvollprecht/UberWriter/" id="de.wolfvollprecht.UberWriter"> <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'> <key name='dark-mode' type='b'>
<default>false</default> <default>false</default>
<summary>Force dark mode</summary> <summary>Use dark mode</summary>
<description> <description>
Enable or disable the dark mode. Enable or disable the dark mode.
</description> </description>
@ -40,14 +32,6 @@
Enable or disable spellchecking. Enable or disable spellchecking.
</description> </description>
</key> </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'> <key name='sync-scroll' type='b'>
<default>true</default> <default>true</default>
<summary>Synchronize editor/preview scrolling</summary> <summary>Synchronize editor/preview scrolling</summary>
@ -62,11 +46,11 @@
Input format to use when previewing and exporting using Pandoc. Input format to use when previewing and exporting using Pandoc.
</description> </description>
</key> </key>
<key name='poll-motion' type='b'> <key name='autohide-headerbar' type='b'>
<default>true</default> <default>true</default>
<summary>Allow Uberwriter to poll cursor motion</summary> <summary>Autohide Headerbar</summary>
<description> <description>
Hide the header and status bars if the cursor is not moving. Hide the header and status bars when typing.
</description> </description>
</key> </key>
<key name='open-file-path' type='s'> <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( install_data(
'de.wolfvollprecht.UberWriter.svg', '@0@.svg'.format(application_id),
install_dir: datadir / 'icons' / 'hicolor' / 'scalable' / 'apps', install_dir: datadir / 'icons' / 'hicolor' / 'scalable' / 'apps'
rename: '@0@.svg'.format(application_id)
) )
install_data( install_data(

View File

@ -27,6 +27,19 @@
caret-color: @theme_fg_color; 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 { #titlebar-revealer {
padding: 0; padding: 0;
} }
@ -94,6 +107,7 @@
.inline-button { .inline-button {
color: alpha(@theme_fg_color, 0.6); color: alpha(@theme_fg_color, 0.6);
background-color: alpha(@theme_base_color, 0.9);
text-shadow: inherit; text-shadow: inherit;
box-shadow: initial; box-shadow: initial;
background-clip: initial; background-clip: initial;
@ -157,5 +171,48 @@
} }
.quick-preview-popup label { .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-background-color: #f1f1f1;
--kbd-border-color: #bdc1c6; --kbd-border-color: #bdc1c6;
--kbd-shadow-color: #8c939a; --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-background-color: #f0f2f4;
--kbd-border-color: #bcc2c9; --kbd-border-color: #bcc2c9;
--kbd-shadow-color: #8b949d; --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"?> <?xml version="1.0" encoding="UTF-8"?>
<gresources> <gresources>
<gresource prefix="/de/wolfvollprecht/UberWriter/"> <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">media/css/gtk/base.css</file>
<file compressed="true" preprocess="xml-stripblanks">ui/Export.ui</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/Menu.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/Preferences.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/Recents.ui</file>
<file compressed="true" preprocess="xml-stripblanks">ui/Shortcuts.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/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> <file compressed="true" preprocess="xml-stripblanks">About.ui</file>
</gresource> </gresource>
</gresources> </gresources>

View File

@ -584,6 +584,9 @@
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<style>
<class name="linked"/>
</style>
</object> </object>
<packing> <packing>
<property name="left_attach">0</property> <property name="left_attach">0</property>
@ -591,28 +594,45 @@
</packing> </packing>
</child> </child>
</object> </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"> <object class="GtkDialog" id="Export">
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="type_hint">dialog</property> <property name="type_hint">dialog</property>
<action-widgets> <action-widgets>
<action-widget response="cancel">cancel_btn</action-widget> <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> </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"> <child internal-child="vbox">
<object class="GtkBox" id="DialogBox"> <object class="GtkBox" id="DialogBox">
<property name="can_focus">False</property> <property name="can_focus">False</property>
@ -629,58 +649,12 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkStack" id="export_stack"> <object class="GtkFileChooserWidget" id="advanced">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="transition_type">crossfade</property> <property name="action">select-folder</property>
<child> <property name="do_overwrite_confirmation">True</property>
<object class="GtkFileChooserWidget" id="html"> <property name="extra_widget">advanced_export_options</property>
<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>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <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"?> <?xml version="1.0" encoding="UTF-8"?>
<interface domain="uberwriter"> <!-- Generated with glade 3.22.1 -->
<menu id="Menu"> <interface>
<section> <requires lib="gtk+" version="3.20"/>
<item> <object class="GtkPopover" id="Menu">
<attribute name="label" translatable="yes">Focus Mode</attribute> <property name="can_focus">False</property>
<attribute name="action">app.focus_mode</attribute> <child>
</item> <object class="GtkBox">
<item> <property name="visible">True</property>
<attribute name="label" translatable="yes">Hemingway Mode</attribute> <property name="can_focus">False</property>
<attribute name="action">app.hemingway_mode</attribute> <property name="margin_left">12</property>
</item> <property name="margin_right">12</property>
<item> <property name="margin_top">12</property>
<attribute name="label" translatable="yes">Preview</attribute> <property name="margin_bottom">12</property>
<attribute name="action">app.preview</attribute> <property name="orientation">vertical</property>
</item> <child>
<item> <object class="GtkBox">
<attribute name="label" translatable="yes">Fullscreen</attribute> <property name="visible">True</property>
<attribute name="action">app.fullscreen</attribute> <property name="can_focus">False</property>
</item> <property name="halign">center</property>
</section> <property name="margin_left">12</property>
<section> <property name="margin_right">12</property>
<item> <property name="margin_bottom">6</property>
<attribute name="label" translatable="yes">Save As</attribute> <property name="spacing">24</property>
<attribute name="action">app.save_as</attribute> <child>
</item> <object class="GtkRadioButton" id="light_mode_button">
<item> <property name="visible">True</property>
<attribute name="label" translatable="yes">Export</attribute> <property name="can_focus">True</property>
<attribute name="action">app.export</attribute> <property name="receives_default">False</property>
</item> <property name="halign">center</property>
<item> <property name="draw_indicator">False</property>
<attribute name="label" translatable="yes">Copy HTML</attribute> <child>
<attribute name="action">app.copy_html</attribute> <object class="GtkImage">
</item> <property name="visible">True</property>
</section> <property name="can_focus">False</property>
<section> <property name="icon_name">emblem-ok-symbolic</property>
<item> </object>
<attribute name="label" translatable="yes">Find and Replace</attribute> </child>
<attribute name="action">app.search_replace</attribute> <style>
</item> <class name="color-button"/>
</section> <class name="color-light"/>
<section> </style>
<item> </object>
<attribute name="label" translatable="yes">Preferences</attribute> <packing>
<attribute name="action">app.preferences</attribute> <property name="expand">False</property>
</item> <property name="fill">True</property>
<item> <property name="position">0</property>
<attribute name="action">app.shortcuts</attribute> </packing>
<attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute> </child>
</item> <child>
<item> <object class="GtkRadioButton" id="dark_mode_button">
<attribute name="label" translatable="yes">Open Tutorial</attribute> <property name="visible">True</property>
<attribute name="action">app.open_tutorial</attribute> <property name="can_focus">True</property>
</item> <property name="receives_default">False</property>
<item> <property name="halign">center</property>
<attribute name="action">app.about</attribute> <property name="draw_indicator">False</property>
<attribute name="label" translatable="yes">_About UberWriter</attribute> <property name="group">light_mode_button</property>
</item> <child>
</section> <object class="GtkImage">
</menu> <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> </interface>

View File

@ -41,54 +41,6 @@
<property name="margin_bottom">16</property> <property name="margin_bottom">16</property>
<property name="row_spacing">8</property> <property name="row_spacing">8</property>
<property name="column_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> <child>
<object class="GtkLabel" id="spellcheck_label"> <object class="GtkLabel" id="spellcheck_label">
<property name="visible">True</property> <property name="visible">True</property>
@ -99,7 +51,7 @@
</object> </object>
<packing> <packing>
<property name="left_attach">0</property> <property name="left_attach">0</property>
<property name="top_attach">2</property> <property name="top_attach">1</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -110,55 +62,7 @@
</object> </object>
<packing> <packing>
<property name="left_attach">2</property> <property name="left_attach">2</property>
<property name="top_attach">2</property> <property name="top_attach">1</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>
</packing> </packing>
</child> </child>
<child> <child>
@ -171,7 +75,7 @@
</object> </object>
<packing> <packing>
<property name="left_attach">0</property> <property name="left_attach">0</property>
<property name="top_attach">5</property> <property name="top_attach">2</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -184,7 +88,7 @@
</object> </object>
<packing> <packing>
<property name="left_attach">2</property> <property name="left_attach">2</property>
<property name="top_attach">5</property> <property name="top_attach">2</property>
</packing> </packing>
</child> </child>
<child> <child>
@ -196,17 +100,33 @@
</object> </object>
<packing> <packing>
<property name="left_attach">1</property> <property name="left_attach">1</property>
<property name="top_attach">5</property> <property name="top_attach">2</property>
</packing> </packing>
</child> </child>
<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>
<child> <child>
<placeholder/> <object class="GtkSwitch" id="autohide_headerbar_switch">
</child> <property name="visible">True</property>
<child> <property name="can_focus">True</property>
<placeholder/> <property name="halign">end</property>
</object>
<packing>
<property name="left_attach">2</property>
<property name="top_attach">0</property>
</packing>
</child> </child>
<child> <child>
<placeholder/> <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="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="valign">start</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="filter">recent_md_filter</property>
<property name="limit">20</property> <property name="limit">20</property>
<property name="show_icons">False</property> <property name="show_icons">False</property>

View File

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

View File

@ -5,7 +5,7 @@ project(
) )
if get_option('profile') == 'development' if get_option('profile') == 'development'
profile = 'Devel' profile = '.Devel'
name_suffix = ' (Development)' name_suffix = ' (Development)'
vcs_tag = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip() vcs_tag = run_command('git', 'rev-parse', '--short', 'HEAD').stdout().strip()
if vcs_tag == '' 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) Gtk.Application.do_startup(self)
self.settings.connect("changed", self.on_settings_changed) self.settings.connect("changed", self.on_settings_changed)
self._set_dark_mode ()
# Header bar # Header bar
@ -65,7 +66,6 @@ class Application(Gtk.Application):
self.add_action(action) self.add_action(action)
# App Menu # App Menu
action = Gio.SimpleAction.new_stateful( action = Gio.SimpleAction.new_stateful(
"focus_mode", None, GLib.Variant.new_boolean(False)) "focus_mode", None, GLib.Variant.new_boolean(False))
action.connect("change-state", self.on_focus_mode) action.connect("change-state", self.on_focus_mode)
@ -90,7 +90,7 @@ class Application(Gtk.Application):
action.connect("activate", self.on_save_as) action.connect("activate", self.on_save_as)
self.add_action(action) self.add_action(action)
action = Gio.SimpleAction.new("export", None) action = Gio.SimpleAction.new("export", GLib.VariantType("s"))
action.connect("activate", self.on_export) action.connect("activate", self.on_export)
self.add_action(action) self.add_action(action)
@ -184,13 +184,22 @@ class Application(Gtk.Application):
self.activate() self.activate()
return 0 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): def on_settings_changed(self, settings, key):
if key == "dark-mode-auto" or key == "dark-mode": if key == "dark-mode":
self.window.apply_current_theme() self._set_dark_mode ()
elif key == "spellcheck": elif key == "spellcheck":
self.window.toggle_spellcheck(settings.get_value(key)) 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": elif key == "input-format":
self.window.reload_preview() self.window.reload_preview()
elif key == "sync-scroll": elif key == "sync-scroll":
@ -237,8 +246,8 @@ class Application(Gtk.Application):
def on_save_as(self, _action, _value): def on_save_as(self, _action, _value):
self.window.save_document_as() self.window.save_document_as()
def on_export(self, _action, _value): def on_export(self, _action, value):
self.window.open_advanced_export() self.window.open_advanced_export(value.get_string())
def on_copy_html(self, _action, _value): def on_copy_html(self, _action, _value):
self.window.copy_html_to_clipboard() self.window.copy_html_to_clipboard()

View File

@ -24,7 +24,7 @@ from gettext import gettext as _
import gi import gi
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
from gi.repository import Gtk from gi.repository import Gtk, GLib
from uberwriter import helpers from uberwriter import helpers
from uberwriter.theme import Theme from uberwriter.theme import Theme
@ -147,42 +147,101 @@ class Export:
} }
] ]
def __init__(self, filename): def __init__(self, filename, export_format, text):
"""Set up the about dialog""" """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 = Gtk.Builder()
self.builder.add_from_resource( self.builder.add_from_resource(
"/de/wolfvollprecht/UberWriter/ui/Export.ui") "/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("highlight_style").set_active(0)
self.builder.get_object("css_filechooser").set_uri( self.builder.get_object("css_filechooser").set_uri(
helpers.path_to_file(Theme.get_current().web_css_path)) 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.add_attribute(format_renderer, "text", 1)
self.format_field.set_active(0) 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. """Export the given text using the specified format.
For advanced export, this includes special flags for the enabled options. For advanced export, this includes special flags for the enabled options.
@ -205,11 +271,16 @@ class Export:
text {str} -- Text to export (default: {""}) text {str} -- Text to export (default: {""})
""" """
export_type = self.stack.get_visible_child_name()
args = [] args = []
if export_type == "advanced": if export_type == "advanced":
filename = self.adv_export_name.get_text() 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) basename = os.path.basename(filename)
fmt = self.formats[self.format_field.get_active()] fmt = self.formats[self.format_field.get_active()]
@ -227,7 +298,6 @@ class Export:
args = [ args = [
"--variable=papersize:a4" "--variable=papersize:a4"
] ]
filename = self.filechoosers[export_type].get_filename()
if filename.endswith("." + export_type): if filename.endswith("." + export_type):
filename = filename[:-len(export_type)-1] filename = filename[:-len(export_type)-1]
output_dir = os.path.abspath(os.path.join(filename, os.path.pardir)) output_dir = os.path.abspath(os.path.join(filename, os.path.pardir))
@ -344,19 +414,6 @@ class Export:
return paper_formats[paper_size] 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(): def disabled_text():
"""Return the TexLive installation instructions """Return the TexLive installation instructions

View File

@ -16,41 +16,236 @@
"""Manage all the headerbars related stuff """Manage all the headerbars related stuff
""" """
from collections import namedtuple
from gettext import gettext as _
import gi import gi
from gettext import gettext as _
gi.require_version('Gtk', '3.0') 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.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 """Sets up the main application headerbar
""" """
def __init__(self, app): 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') BaseHeaderbar.__init__(self, app)
self.hb_revealer.add(self.hb)
self.hb_revealer.props.transition_duration = 750 self.hb.set_show_close_button(True)
self.hb_revealer.props.transition_type = Gtk.RevealerTransitionType.CROSSFADE
self.hb_revealer.show() 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_revealer.set_reveal_child(True)
self.hb_container = Gtk.Frame(name='titlebar-container') def hide_fs_hb(self, _widget=None, _data=None):
self.hb_container.set_shadow_type(Gtk.ShadowType.NONE) """hide headerbar of the fullscreen mode
self.hb_container.add(self.hb_revealer) """
self.hb_container.show() 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: class PreviewHeaderbar:
@ -62,10 +257,11 @@ class PreviewHeaderbar:
self.hb.props.show_close_button = True self.hb.props.show_close_button = True
self.hb.get_style_context().add_class("titlebar") 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.add(self.hb)
self.hb_revealer.props.transition_duration = 750 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.show()
self.hb_revealer.set_reveal_child(True) self.hb_revealer.set_reveal_child(True)
@ -77,76 +273,22 @@ class PreviewHeaderbar:
self.hb.show_all() self.hb.show_all()
class FullscreenHeaderbar: def add_menus(headerbar, app):
"""Sets up and manages the fullscreen headerbar and his events """ Add menu models to hb buttons
""" """
def __init__(self, builder, app): # Add menu model to the menu button
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())
builder_window_menu = Gtk.Builder() builder_window_menu = Gtk.Builder()
builder_window_menu.add_from_resource( builder_window_menu.add_from_resource(
"/de/wolfvollprecht/UberWriter/ui/Menu.ui") "/de/wolfvollprecht/UberWriter/ui/Menu.ui")
model = builder_window_menu.get_object("Menu") 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")) headerbar.menu_button.set_popover(model)
open_button.set_action_name("app.open")
# Add recents menu to the open recents button
recents_builder = Gtk.Builder() recents_builder = Gtk.Builder()
recents_builder.add_from_resource( recents_builder.add_from_resource(
@ -159,44 +301,5 @@ def main_buttons(app):
recents_wd = recents_builder.get_object("recent_md_widget") recents_wd = recents_builder.get_object("recent_md_widget")
recents_wd.connect('item-activated', app.on_open_recent) recents_wd.connect('item-activated', app.on_open_recent)
recents_button = Gtk.MenuButton().new() headerbar.recents_button.set_popover(recents)
recents_button.set_image(Gtk.Image.new_from_icon_name("pan-down-symbolic", headerbar.recents_button.set_sensitive(True)
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)

View File

@ -35,7 +35,6 @@ from gi.repository import Gtk, Gdk, GObject, GLib, Gio
import cairo import cairo
from uberwriter import helpers from uberwriter import helpers
from uberwriter.theme import Theme
from uberwriter.sidebar import Sidebar from uberwriter.sidebar import Sidebar
from uberwriter.search_and_replace import SearchAndReplace from uberwriter.search_and_replace import SearchAndReplace
@ -74,7 +73,7 @@ class MainWindow(StyledWindow):
builder = Gtk.Builder() builder = Gtk.Builder()
builder.add_from_resource( builder.add_from_resource(
"/de/wolfvollprecht/UberWriter/ui/Window.ui") "/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.connect("delete-event", self.on_delete_called)
self.add(root) self.add(root)
@ -84,18 +83,35 @@ class MainWindow(StyledWindow):
self.settings = Settings.new() self.settings = Settings.new()
# Headerbars # Headerbars
self.last_height = 0
self.headerbar = headerbars.MainHeaderbar(app) 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) 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.title_end = " UberWriter"
self.set_headerbar_title("New File" + self.title_end) 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.accel_group = Gtk.AccelGroup()
self.add_accel_group(self.accel_group) self.add_accel_group(self.accel_group)
@ -103,6 +119,7 @@ class MainWindow(StyledWindow):
# Setup text editor # Setup text editor
self.text_view = TextView(self.settings.get_int("characters-per-line")) 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.connect('focus-out-event', self.focus_out)
self.text_view.get_buffer().connect('changed', self.on_text_changed) self.text_view.get_buffer().connect('changed', self.on_text_changed)
self.text_view.show() self.text_view.show()
@ -119,16 +136,11 @@ class MainWindow(StyledWindow):
editor = builder.get_object('editor') editor = builder.get_object('editor')
self.preview_handler = PreviewHandler(self, content, editor, self.text_view) self.preview_handler = PreviewHandler(self, content, editor, self.text_view)
# Setup header/stats bar hide after 3 seconds # Setup header/stats bar
self.top_bottom_bars_visible = True self.headerbar_visible = True
self.was_motion = True self.bottombar_visible = True
self.buffer_modified_for_status_bar = False 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 # Init file name with None
self.set_filename() self.set_filename()
@ -151,6 +163,32 @@ class MainWindow(StyledWindow):
### ###
self.searchreplace = SearchAndReplace(self, self.text_view, builder) 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): def on_text_changed(self, *_args):
"""called when the text changes, sets the self.did_change to true and """called when the text changes, sets the self.did_change to true and
updates the title and the counters to reflect that updates the title and the counters to reflect that
@ -162,6 +200,8 @@ class MainWindow(StyledWindow):
self.set_headerbar_title("* " + title) self.set_headerbar_title("* " + title)
self.buffer_modified_for_status_bar = True self.buffer_modified_for_status_bar = True
if self.settings.get_value("autohide-headerbar"):
self.hide_headerbar_bottombar()
def set_fullscreen(self, state): def set_fullscreen(self, state):
"""Puts the application in fullscreen mode and show/hides """Puts the application in fullscreen mode and show/hides
@ -174,16 +214,19 @@ class MainWindow(StyledWindow):
if state.get_boolean(): if state.get_boolean():
self.fullscreen() self.fullscreen()
self.fs_headerbar.events.show() self.fs_headerbar.events.show()
self.fs_headerbar.hide_fs_hb()
self.headerbar_eventbox.hide()
else: else:
self.unfullscreen() self.unfullscreen()
self.fs_headerbar.events.hide() self.fs_headerbar.events.hide()
self.headerbar_eventbox.show()
self.text_view.grab_focus() self.text_view.grab_focus()
def set_focus_mode(self, state): def set_focus_mode(self, state):
"""toggle focusmode """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() self.text_view.grab_focus()
def set_hemingway_mode(self, state): def set_hemingway_mode(self, state):
@ -203,9 +246,15 @@ class MainWindow(StyledWindow):
if state.get_boolean(): if state.get_boolean():
self.text_view.grab_focus() self.text_view.grab_focus()
self.preview_handler.show() 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: else:
self.preview_handler.hide() self.preview_handler.hide()
self.text_view.grab_focus() 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 return True
@ -258,7 +307,7 @@ class MainWindow(StyledWindow):
self.set_filename(filename) self.set_filename(filename)
self.set_headerbar_title( self.set_headerbar_title(
os.path.basename(filename) + self.title_end) os.path.basename(filename) + self.title_end, filename)
self.did_change = False self.did_change = False
filechooser.destroy() filechooser.destroy()
@ -299,7 +348,7 @@ class MainWindow(StyledWindow):
self.set_filename(filename) self.set_filename(filename)
self.set_headerbar_title( self.set_headerbar_title(
os.path.basename(filename) + self.title_end) os.path.basename(filename) + self.title_end, filename)
try: try:
self.recent_manager.add_item(filename) self.recent_manager.add_item(filename)
@ -360,16 +409,27 @@ class MainWindow(StyledWindow):
"""Show dialog to prevent loss of unsaved changes """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(): if self.did_change and self.text_view.get_text():
dialog = Gtk.MessageDialog(self, dialog = Gtk.MessageDialog(self,
Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
Gtk.MessageType.WARNING, Gtk.MessageType.WARNING,
Gtk.ButtonsType.NONE, 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(_("Cancel"), Gtk.ResponseType.CANCEL)
dialog.add_button(_("Save now"), Gtk.ResponseType.YES) 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_size(200, 60)
dialog.set_default_response(Gtk.ResponseType.YES) dialog.set_default_response(Gtk.ResponseType.YES)
response = dialog.run() response = dialog.run()
@ -405,6 +465,10 @@ class MainWindow(StyledWindow):
def update_preview_mode(self): def update_preview_mode(self):
self.preview_handler.update_preview_mode() 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): def menu_toggle_sidebar(self, _widget=None):
"""WIP """WIP
@ -420,18 +484,6 @@ class MainWindow(StyledWindow):
self.text_view.set_spellcheck(state.get_boolean()) 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): def reload_preview(self, reshow=False):
self.preview_handler.reload(reshow=reshow) self.preview_handler.reload(reshow=reshow)
@ -443,7 +495,8 @@ class MainWindow(StyledWindow):
if filename: if filename:
if filename.startswith('file://'): if filename.startswith('file://'):
filename = urllib.parse.unquote(filename)[7:] filename = filename[7:]
filename = urllib.parse.unquote_plus(filename)
self.text_view.clear() self.text_view.clear()
try: try:
if os.path.exists(filename): if os.path.exists(filename):
@ -460,7 +513,7 @@ class MainWindow(StyledWindow):
dialog.run() dialog.run()
dialog.destroy() 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) self.set_filename(filename)
except Exception as e: except Exception as e:
@ -492,29 +545,12 @@ class MainWindow(StyledWindow):
self.searchreplace.toggle_search(replace=replace) 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 """open the export and advanced export dialog
""" """
text = bytes(self.text_view.get_text(), "utf-8")
self.export = Export(self.filename) self.export = Export(self.filename, export_format, text)
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()
def open_recent(self, _widget, data=None): def open_recent(self, _widget, data=None):
"""open the given recent document """open the given recent document
@ -525,79 +561,52 @@ class MainWindow(StyledWindow):
return return
self.load_file(data) 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): def focus_out(self, _widget, _data=None):
"""events called when the window losses focus """events called when the window losses focus
""" """
self.reveal_top_bottom_bars(True) self.reveal_headerbar_bottombar()
def reveal_top_bottom_bars(self, reveal): def reveal_headerbar_bottombar(self, _widget=None, _data=None):
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 draw_gradient(self, _widget, cr): def __reveal_hb():
"""draw fading gradient over the top and the bottom of the self.headerbar_eventbox.hide()
TextWindow self.headerbar.hb_revealer.set_reveal_child(True)
""" self.get_style_context().remove_class("focus")
bg_color = self.get_style_context().get_background_color(Gtk.StateFlags.ACTIVE) return False
lg_top = cairo.LinearGradient(0, 0, 0, 32) # pylint: disable=no-member self.reveal_bottombar()
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)
width = self.scrolled_window.get_allocation().width if not self.headerbar_visible:
height = self.scrolled_window.get_allocation().height self.dm_headerbar.hide_dm_hb()
GLib.timeout_add(400, __reveal_hb)
cr.rectangle(0, 0, width, 32) self.headerbar_visible = True
cr.set_source(lg_top)
cr.fill()
cr.rectangle(0, height - 32, width, height)
lg_btm = cairo.LinearGradient(0, height - 32, 0, height) # pylint: disable=no-member def reveal_bottombar(self, _widget=None, _data=None):
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)
cr.set_source(lg_btm) if not self.bottombar_visible:
cr.fill() 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): def on_delete_called(self, _widget, _data=None):
"""Called when the TexteditorWindow is closed. """Called when the TexteditorWindow is closed.
@ -616,11 +625,18 @@ class MainWindow(StyledWindow):
self.destroy() self.destroy()
return return
def set_headerbar_title(self, title): def set_headerbar_title(self, title, subtitle=None):
"""set the desired headerbar title """set the desired headerbar title
""" """
self.headerbar.hb.props.title = title self.headerbar.hb.props.title = title
self.dm_headerbar.hb.props.title = title
self.fs_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) self.set_title(title)
def set_filename(self, filename=None): def set_filename(self, filename=None):

View File

@ -67,26 +67,14 @@ class PreferencesDialog:
self.builder.add_from_resource( self.builder.add_from_resource(
"/de/wolfvollprecht/UberWriter/ui/Preferences.ui") "/de/wolfvollprecht/UberWriter/ui/Preferences.ui")
self.dark_mode_auto_switch = self.builder.get_object("dark_mode_auto_switch") self.autohide_headerbar_switch = self.builder.get_object("autohide_headerbar_switch")
self.dark_mode_auto_switch.set_active(self.settings.get_value("dark-mode-auto")) self.autohide_headerbar_switch.set_active(self.settings.get_value("autohide-headerbar"))
self.dark_mode_auto_switch.connect("state-set", self.on_dark_mode_auto) self.autohide_headerbar_switch.connect("state-set", self.on_autohide_headerbar)
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.spellcheck_switch = self.builder.get_object("spellcheck_switch") self.spellcheck_switch = self.builder.get_object("spellcheck_switch")
self.spellcheck_switch.set_active(self.settings.get_value("spellcheck")) self.spellcheck_switch.set_active(self.settings.get_value("spellcheck"))
self.spellcheck_switch.connect("state-set", self.on_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_store = Gtk.ListStore(int, str)
input_format = self.settings.get_string("input-format") input_format = self.settings.get_string("input-format")
input_format_active = 0 input_format_active = 0
@ -111,30 +99,14 @@ class PreferencesDialog:
preferences_window.set_transient_for(window) preferences_window.set_transient_for(window)
preferences_window.show() preferences_window.show()
def on_dark_mode_auto(self, _, state): def on_autohide_headerbar(self, _, state):
self.settings.set_boolean("dark-mode-auto", state) self.settings.set_boolean("autohide-headerbar", 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))
return False return False
def on_spellcheck(self, _, state): def on_spellcheck(self, _, state):
self.settings.set_boolean("spellcheck", state) self.settings.set_boolean("spellcheck", state)
return False 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): def on_input_format(self, combobox):
fmt = self.formats[combobox.get_active()] fmt = self.formats[combobox.get_active()]
self.settings.set_string("input-format", fmt["format"]) self.settings.set_string("input-format", fmt["format"])

View File

@ -32,16 +32,9 @@ class PreviewHandler:
self.web_view = None self.web_view = None
self.web_view_pending_html = 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_converter = PreviewConverter()
self.preview_renderer = PreviewRenderer( 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) window.connect("style-updated", self.reload)
@ -135,12 +128,6 @@ class PreviewHandler:
def update_preview_mode(self): def update_preview_mode(self):
self.preview_renderer.update_mode(self.web_view) 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): def on_load_changed(self, _web_view, event):
if event == WebKit2.LoadEvent.FINISHED: if event == WebKit2.LoadEvent.FINISHED:
self.loading = False self.loading = False

View File

@ -17,16 +17,12 @@ class PreviewRenderer:
WINDOWED = 3 WINDOWED = 3
def __init__( 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 = main_window
self.main_window.connect("delete-event", self.on_window_closed) self.main_window.connect("delete-event", self.on_window_closed)
self.content = content self.content = content
self.editor = editor self.editor = editor
self.text_view = text_view 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.settings = Settings.new()
self.popover = None self.popover = None
@ -49,9 +45,6 @@ class PreviewRenderer:
headerbar = headerbars.PreviewHeaderbar() headerbar = headerbars.PreviewHeaderbar()
self.headerbar = headerbar.hb self.headerbar = headerbar.hb
self.headerbar.set_title(_("Preview")) 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) self.window.set_titlebar(headerbar.hb_container)
# Position it next to the main window. # Position it next to the main window.
@ -67,8 +60,7 @@ class PreviewRenderer:
self.window.show() self.window.show()
else: else:
self.preview.pack_start(web_view, True, True, 0) self.content.pack_start(web_view, True, True, 0)
self.content.add(self.preview)
# Full-width preview: swap editor with preview. # Full-width preview: swap editor with preview.
if self.mode == self.FULL_WIDTH: if self.mode == self.FULL_WIDTH:
@ -97,17 +89,13 @@ class PreviewRenderer:
# Windowed preview: remove preview and destroy window. # Windowed preview: remove preview and destroy window.
if self.mode == self.WINDOWED: if self.mode == self.WINDOWED:
self.main_window.present() 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.headerbar = None
self.window.remove(web_view) self.window.remove(web_view)
self.window.destroy() self.window.destroy()
self.window = None self.window = None
else: else:
self.preview.remove(web_view) self.content.remove(web_view)
self.content.remove(self.preview)
# Full-width preview: swap preview with editor. # Full-width preview: swap preview with editor.
if self.mode == self.FULL_WIDTH: if self.mode == self.FULL_WIDTH:
@ -130,32 +118,6 @@ class PreviewRenderer:
self.show(web_view) self.show(web_view)
else: else:
self.mode = mode 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): def on_window_closed(self, window, _event):
preview_action = window.get_application().lookup_action("preview") 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("load-failed", self.on_load_failed)
self.connect("destroy", self.on_destroy) self.connect("destroy", self.on_destroy)
self.props.expand = True
self.scroll_scale = -1 self.scroll_scale = -1
self.state_loaded = False self.state_loaded = False

View File

@ -1,7 +1,6 @@
import gi import gi
from uberwriter import helpers from uberwriter import helpers
from uberwriter.theme import Theme
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib, Gio from gi.repository import Gtk, GLib, Gio
@ -13,27 +12,11 @@ class StyledWindow(Gtk.ApplicationWindow):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.connect("style-updated", self.apply_current_theme) # Set theme css
self.apply_current_theme() css_provider_file = Gio.File.new_for_uri(
"resource:///de/wolfvollprecht/UberWriter/media/css/gtk/base.css")
def apply_current_theme(self, *_): style_provider = Gtk.CssProvider()
"""Adjusts the window, CSD and preview for the current theme.""" style_provider.load_from_file(css_provider_file)
# Get current theme Gtk.StyleContext.add_provider_for_screen(
theme, changed = Theme.get_current_changed() self.get_screen(), style_provider,
if changed: Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
# 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()

View File

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

View File

@ -31,10 +31,9 @@ class Theme:
@classmethod @classmethod
def get_current_changed(cls): def get_current_changed(cls):
theme_name = Gtk.Settings.get_default().get_property('gtk-theme-name') 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') dark_mode = cls.settings.get_boolean('dark-mode')
current_theme = cls.get_for_name(theme_name) 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) current_theme = cls.get_for_name(current_theme.inverse_name, current_theme.name)
changed = current_theme != cls.previous changed = current_theme != cls.previous
cls.previous = current_theme cls.previous = current_theme
@ -56,11 +55,11 @@ class Theme:
defaultThemes = [ defaultThemes = [
# https://gitlab.gnome.org/GNOME/gtk/tree/master/gtk/theme/Adwaita # https://gitlab.gnome.org/GNOME/gtk/tree/master/gtk/theme/Adwaita
Theme('Adwaita', get_css_path('web/adwaita.css'), False, 'Adwaita-dark'), 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 # 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', get_css_path('web/arc.css'), False, 'Arc-Dark'),
Theme('Arc-Darker', get_css_path('web/arc_darker.css'), False, 'Arc-Dark'), Theme('Arc-Darker', get_css_path('web/arc.css'), False, 'Arc-Dark'),
Theme('Arc-Dark', get_css_path('web/arc_dark.css'), True, 'Arc'), Theme('Arc-Dark', get_css_path('web/arc.css'), True, 'Arc'),
# https://gitlab.gnome.org/GNOME/gtk/tree/master/gtk/theme/HighContrast # https://gitlab.gnome.org/GNOME/gtk/tree/master/gtk/theme/HighContrast
Theme('HighContrast', get_css_path('web/highcontrast.css'), False, 'HighContrastInverse'), Theme('HighContrast', get_css_path('web/highcontrast.css'), False, 'HighContrastInverse'),
Theme('HighContrastInverse', get_css_path('web/highcontrast_inverse.css'), True, 'HighContrast') Theme('HighContrastInverse', get_css_path('web/highcontrast_inverse.css'), True, 'HighContrast')