├── .editorconfig ├── .gitignore ├── .travis.yml ├── README.md ├── data ├── com.github.artemanufrij.trimdown.appdata.xml.in ├── com.github.artemanufrij.trimdown.desktop.in ├── icons │ ├── 16 │ │ └── com.github.artemanufrij.trimdown.svg │ ├── 24 │ │ └── com.github.artemanufrij.trimdown.svg │ ├── 32 │ │ └── com.github.artemanufrij.trimdown.svg │ ├── 48 │ │ └── com.github.artemanufrij.trimdown.svg │ ├── 64 │ │ └── com.github.artemanufrij.trimdown.svg │ └── 128 │ │ └── com.github.artemanufrij.trimdown.svg └── meson.build ├── meson.build ├── meson └── post_install.py ├── po ├── LINGUAS ├── POTFILES ├── com.github.artemanufrij.trimdown.pot ├── extra │ ├── LINGUAS │ ├── POTFILES │ ├── extra.pot │ ├── fr.po │ ├── meson.build │ └── nl.po ├── fr.po ├── meson.build └── nl.po ├── schemas ├── com.github.artemanufrij.trimdown.gschema.xml └── meson.build ├── src ├── Application.vala ├── Dialogs │ ├── NewProject.vala │ └── Preferences.vala ├── MainWindow.vala ├── Objects │ ├── BaseObject.vala │ ├── Chapter.vala │ ├── Note.vala │ ├── Project.vala │ └── Scene.vala ├── Services │ └── ProjectManager.vala ├── Settings.vala ├── Utils │ ├── Enums.vala │ ├── Lists.vala │ └── Utils.vala ├── Widgets │ ├── Bin.vala │ ├── Chapter.vala │ ├── ChapterList.vala │ ├── Note.vala │ ├── Notes.vala │ ├── Scene.vala │ ├── SceneList.vala │ └── Views │ │ ├── Welcome.vala │ │ └── Writer.vala └── meson.build └── uncrustify.cfg /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig 2 | root = true 3 | 4 | # elementary defaults 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | indent_size = tab 9 | indent_style = space 10 | insert_final_newline = true 11 | max_line_length = 80 12 | tab_width = 4 13 | 14 | # Markup files 15 | [{*.html,*.xml,*.xml.in,*.yml}] 16 | tab_width = 2 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | build/ 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | language: generic 3 | 4 | services: 5 | - docker 6 | 7 | script: 8 | - wget -O- https://raw.githubusercontent.com/harisvsulaiman/element-build/master/script.sh | sh - 9 | 10 | branches: 11 | except: 12 | - /^debian\/\d/ 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

TrimDown

3 |


A simple, feature rich, writing app for writing Novels, Short stories, Scripts and Articles.

4 |

Designed for elementary OS

5 |
6 | 7 | ### Donate 8 | PayPal | LiberaPay | Patreon 9 | 10 | ## Install from Github. 11 | As first you need some packages 12 | ``` 13 | sudo apt install git meson libgranite-dev libgtksourceview-3.0-dev 14 | ``` 15 | Clone repository and change directory 16 | ``` 17 | git clone https://github.com/artemanufrij/trimdown.git 18 | cd trimdown 19 | ``` 20 | Compile, install and start Find File Conflicts on your system 21 | ``` 22 | meson build --prefix=/usr 23 | cd build 24 | sudo ninja install 25 | com.github.artemanufrij.trimdown 26 | -------------------------------------------------------------------------------- /data/com.github.artemanufrij.trimdown.appdata.xml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | com.github.artemanufrij.trimdown 5 | CC0-1.0 6 | GPL-3.0+ 7 | TrimDown 8 | An app for Novels and script Writer 9 | 10 |

A simple, feature rich, writing app for writing Novels, Short stories, Scripts and Articles.

11 |
12 | 13 | Office 14 | 15 | 16 | 17 | 18 | 19 | 20 | Artem Anufrij 21 | http://anufrij.org 22 | https://github.com/artemanufrij/trimdown/issues 23 | https://github.com/artemanufrij/trimdown/issues 24 | artem.anufrij@live.de 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | none 33 | none 34 | none 35 | none 36 | none 37 | none 38 | none 39 | none 40 | none 41 | none 42 | none 43 | none 44 | none 45 | none 46 | none 47 | none 48 | none 49 | none 50 | none 51 | none 52 | none 53 | none 54 | none 55 | none 56 | none 57 | none 58 | none 59 | 60 |
61 | -------------------------------------------------------------------------------- /data/com.github.artemanufrij.trimdown.desktop.in: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=TrimDown 3 | GenericName=TrimDown 4 | Comment=An app for Novels and script Writer 5 | Keywords=write;novel;script;article; 6 | Exec=com.github.artemanufrij.trimdown %U 7 | Icon=com.github.artemanufrij.trimdown 8 | Terminal=false 9 | Type=Application 10 | Categories=Office;GNOME;GTK; 11 | X-GNOME-Gettext-Domain=com.github.artemanufrij.trimdown 12 | -------------------------------------------------------------------------------- /data/icons/128/com.github.artemanufrij.trimdown.svg: -------------------------------------------------------------------------------- 1 | 2 | 20 | 41 | 45 | 55 | 56 | 58 | 60 | 64 | 68 | 72 | 73 | 75 | 79 | 83 | 87 | 91 | 92 | 101 | 111 | 113 | 117 | 121 | 125 | 129 | 130 | 140 | 149 | 151 | 155 | 159 | 163 | 167 | 168 | 177 | 179 | 183 | 187 | 191 | 195 | 196 | 206 | 208 | 212 | 216 | 220 | 224 | 225 | 226 | 228 | 229 | 231 | image/svg+xml 232 | 234 | 235 | 236 | 237 | 238 | 245 | 252 | 259 | 266 | 273 | 280 | 286 | 292 | 298 | 304 | 310 | 316 | 322 | 328 | 334 | 340 | 347 | 352 | 357 | 362 | 363 | -------------------------------------------------------------------------------- /data/icons/16/com.github.artemanufrij.trimdown.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 38 | 42 | 52 | 53 | 55 | 58 | 62 | 66 | 67 | 76 | 78 | 82 | 86 | 90 | 94 | 95 | 97 | 101 | 105 | 106 | 115 | 125 | 127 | 131 | 135 | 139 | 143 | 144 | 153 | 155 | 159 | 163 | 167 | 171 | 172 | 183 | 184 | 186 | 187 | 189 | image/svg+xml 190 | 192 | 193 | 194 | 195 | 196 | 205 | 212 | 219 | 225 | 232 | 239 | 245 | 251 | 257 | 263 | 269 | 276 | 283 | 290 | 291 | -------------------------------------------------------------------------------- /data/icons/24/com.github.artemanufrij.trimdown.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 38 | 42 | 52 | 53 | 55 | 57 | 61 | 65 | 69 | 70 | 72 | 76 | 80 | 84 | 88 | 89 | 91 | 95 | 99 | 100 | 102 | 106 | 110 | 111 | 120 | 122 | 126 | 130 | 134 | 138 | 139 | 149 | 158 | 168 | 177 | 179 | 183 | 187 | 191 | 195 | 196 | 206 | 207 | 209 | 210 | 212 | image/svg+xml 213 | 215 | 216 | 217 | 218 | 219 | 226 | 233 | 240 | 247 | 254 | 261 | 267 | 273 | 279 | 285 | 291 | 297 | 304 | 309 | 314 | 315 | -------------------------------------------------------------------------------- /data/icons/32/com.github.artemanufrij.trimdown.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 38 | 42 | 52 | 53 | 55 | 57 | 61 | 65 | 69 | 70 | 80 | 89 | 91 | 95 | 99 | 103 | 107 | 108 | 110 | 114 | 118 | 122 | 126 | 127 | 129 | 133 | 137 | 138 | 140 | 144 | 148 | 152 | 156 | 157 | 166 | 176 | 186 | 195 | 197 | 201 | 205 | 206 | 207 | 209 | 210 | 212 | image/svg+xml 213 | 215 | 216 | 217 | 218 | 219 | 226 | 233 | 240 | 247 | 254 | 261 | 266 | 271 | 277 | 283 | 289 | 295 | 301 | 307 | 314 | 315 | -------------------------------------------------------------------------------- /data/meson.build: -------------------------------------------------------------------------------- 1 | icon_sizes = ['16', '24', '32', '48', '64', '128'] 2 | 3 | foreach i : icon_sizes 4 | install_data( 5 | join_paths('icons', i, meson.project_name() + '.svg'), 6 | install_dir: join_paths(get_option('datadir'), 'icons', 'hicolor', i + 'x' + i, 'apps') 7 | ) 8 | install_data( 9 | join_paths('icons', i, meson.project_name() + '.svg'), 10 | install_dir: join_paths(get_option('datadir'), 'icons', 'hicolor', i + 'x' + i + '@2', 'apps') 11 | ) 12 | endforeach 13 | 14 | i18n.merge_file( 15 | input: meson.project_name() + '.desktop.in', 16 | output: meson.project_name() + '.desktop', 17 | po_dir: join_paths(meson.source_root(), 'po', 'extra'), 18 | type: 'desktop', 19 | install: true, 20 | install_dir: join_paths(get_option('datadir'), 'applications') 21 | ) 22 | 23 | i18n.merge_file( 24 | input: meson.project_name() + '.appdata.xml.in', 25 | output: meson.project_name() + '.appdata.xml', 26 | po_dir: join_paths(meson.source_root(), 'po', 'extra'), 27 | install: true, 28 | install_dir: join_paths(get_option('datadir'), 'metainfo') 29 | ) 30 | 31 | desktop_file_validate = find_program('desktop-file-validate', required:false) 32 | 33 | if desktop_file_validate.found() 34 | test ( 35 | 'Validate desktop file', 36 | desktop_file_validate, 37 | args: join_paths(meson.current_build_dir (), meson.project_name() + '.desktop') 38 | ) 39 | endif 40 | 41 | appstreamcli = find_program(['appstreamcli', 'appstream-util'], required:false) 42 | 43 | if appstreamcli.found() 44 | test ( 45 | 'Validate appdata file', 46 | appstreamcli, 47 | args: ['validate', join_paths(meson.current_build_dir (), meson.project_name() + '.appdata.xml')] 48 | ) 49 | endif 50 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('com.github.artemanufrij.trimdown', 'vala', 'c', version: '1.0.0') 2 | 3 | i18n = import('i18n') 4 | gnome = import('gnome') 5 | 6 | conf = configuration_data() 7 | conf.set_quoted('GETTEXT_PACKAGE', meson.project_name()) 8 | configure_file(output: 'config.h', configuration: conf) 9 | config_h_dir = include_directories('.') 10 | 11 | c_args = [ 12 | '-include', 'config.h' 13 | ] 14 | 15 | subdir('src') 16 | 17 | executable( 18 | meson.project_name(), 19 | sources, 20 | c_args: c_args, 21 | dependencies: [ 22 | dependency('granite'), 23 | dependency('gtk+-3.0'), 24 | dependency('gtksourceview-3.0'), 25 | meson.get_compiler('vala').find_library('posix') 26 | ], 27 | install : true 28 | ) 29 | 30 | subdir('data') 31 | subdir('po') 32 | subdir('schemas') 33 | 34 | meson.add_install_script('meson/post_install.py') 35 | -------------------------------------------------------------------------------- /meson/post_install.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import subprocess 5 | 6 | schema_dir = os.path.join(os.environ['MESON_INSTALL_PREFIX'], 'share', 'glib-2.0', 'schemas') 7 | icon_cache_dir = os.path.join(os.environ['MESON_INSTALL_PREFIX'], 'share', 'icons', 'hicolor') 8 | 9 | if not os.environ.get('DESTDIR'): 10 | print('Compiling gsettings schemas…') 11 | subprocess.call(['glib-compile-schemas', schema_dir]) 12 | 13 | print('Updating desktop icon cache…') 14 | subprocess.call(['gtk-update-icon-cache', '-qtf', icon_cache_dir]) 15 | -------------------------------------------------------------------------------- /po/LINGUAS: -------------------------------------------------------------------------------- 1 | fr 2 | -------------------------------------------------------------------------------- /po/POTFILES: -------------------------------------------------------------------------------- 1 | src/Dialogs/NewProject.vala 2 | src/Dialogs/Preferences.vala 3 | src/Objects/Chapter.vala 4 | src/Objects/Project.vala 5 | src/Services/ProjectManager.vala 6 | src/Widgets/Views/Welcome.vala 7 | src/Widgets/Chapter.vala 8 | src/Widgets/ChapterList.vala 9 | src/Widgets/Note.vala 10 | src/Widgets/Notes.vala 11 | src/Widgets/Scene.vala 12 | src/Widgets/SceneList.vala 13 | src/MainWindow.vala 14 | -------------------------------------------------------------------------------- /po/com.github.artemanufrij.trimdown.pot: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the com.github.artemanufrij.trimdown package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: com.github.artemanufrij.trimdown\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2019-08-02 11:58+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=CHARSET\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: src/Dialogs/NewProject.vala:54 src/MainWindow.vala:85 21 | msgid "New Project" 22 | msgstr "" 23 | 24 | #: src/Dialogs/NewProject.vala:67 25 | msgid "Project Title" 26 | msgstr "" 27 | 28 | #: src/Dialogs/NewProject.vala:73 29 | msgid "[empty]" 30 | msgstr "" 31 | 32 | #: src/Dialogs/NewProject.vala:74 33 | msgid "SiFi" 34 | msgstr "" 35 | 36 | #: src/Dialogs/NewProject.vala:75 37 | msgid "Fantasy" 38 | msgstr "" 39 | 40 | #. ACTION BUTTONS 41 | #: src/Dialogs/NewProject.vala:85 42 | msgid "Create" 43 | msgstr "" 44 | 45 | #: src/Dialogs/Preferences.vala:62 46 | msgid "Use Dark Theme" 47 | msgstr "" 48 | 49 | #: src/Dialogs/Preferences.vala:65 50 | msgid "Remember last Project" 51 | msgstr "" 52 | 53 | #: src/Dialogs/Preferences.vala:73 54 | msgid "Close" 55 | msgstr "" 56 | 57 | #: src/Objects/Chapter.vala:65 58 | msgid "Scenes" 59 | msgstr "" 60 | 61 | #: src/Objects/Chapter.vala:66 src/Objects/Project.vala:95 62 | msgid "Notes" 63 | msgstr "" 64 | 65 | #: src/Objects/Chapter.vala:148 src/Objects/Project.vala:94 66 | #, c-format 67 | msgid "Scene %d" 68 | msgstr "" 69 | 70 | #: src/Objects/Chapter.vala:167 71 | #, c-format 72 | msgid "Note %d" 73 | msgstr "" 74 | 75 | #: src/Objects/Project.vala:51 src/Services/ProjectManager.vala:61 76 | msgid "Chapters" 77 | msgstr "" 78 | 79 | #: src/Objects/Project.vala:103 80 | #, c-format 81 | msgid "Chapter %d" 82 | msgstr "" 83 | 84 | #: src/Services/ProjectManager.vala:65 85 | msgid "Prologue" 86 | msgstr "" 87 | 88 | #: src/Services/ProjectManager.vala:75 89 | msgid "Open a TrimDown project." 90 | msgstr "" 91 | 92 | #: src/Services/ProjectManager.vala:76 93 | msgid "_Cancel" 94 | msgstr "" 95 | 96 | #: src/Services/ProjectManager.vala:77 97 | msgid "_Open" 98 | msgstr "" 99 | 100 | #: src/Services/ProjectManager.vala:80 101 | msgid "TrimDown Project" 102 | msgstr "" 103 | 104 | #: src/Widgets/Views/Welcome.vala:38 105 | msgid "Title" 106 | msgstr "" 107 | 108 | #: src/Widgets/Views/Welcome.vala:38 109 | msgid "Subtitle." 110 | msgstr "" 111 | 112 | #: src/Widgets/Views/Welcome.vala:39 113 | msgid "Create a new Project" 114 | msgstr "" 115 | 116 | #: src/Widgets/Views/Welcome.vala:39 117 | msgid "Write your next best seller." 118 | msgstr "" 119 | 120 | #: src/Widgets/Views/Welcome.vala:40 121 | msgid "Open a Project" 122 | msgstr "" 123 | 124 | #: src/Widgets/Views/Welcome.vala:40 125 | msgid "Open an exists project from your library." 126 | msgstr "" 127 | 128 | #: src/Widgets/Chapter.vala:103 src/Widgets/Note.vala:71 129 | #: src/Widgets/Scene.vala:98 130 | msgid "Restore from Bin" 131 | msgstr "" 132 | 133 | #: src/Widgets/Chapter.vala:105 src/Widgets/Note.vala:73 134 | #: src/Widgets/Scene.vala:100 135 | msgid "Move into Bin" 136 | msgstr "" 137 | 138 | #: src/Widgets/ChapterList.vala:59 139 | msgid "Add a Chapter" 140 | msgstr "" 141 | 142 | #: src/Widgets/Notes.vala:80 143 | msgid "Add a Note" 144 | msgstr "" 145 | 146 | #: src/Widgets/SceneList.vala:63 147 | msgid "Add a Scene" 148 | msgstr "" 149 | 150 | #: src/MainWindow.vala:90 151 | msgid "Open Project" 152 | msgstr "" 153 | 154 | #: src/MainWindow.vala:105 155 | msgid "Preferences" 156 | msgstr "" 157 | 158 | #: src/MainWindow.vala:121 159 | msgid "Chapter Notes" 160 | msgstr "" 161 | 162 | #: src/MainWindow.vala:141 163 | msgid "Deleted Items" 164 | msgstr "" 165 | -------------------------------------------------------------------------------- /po/extra/LINGUAS: -------------------------------------------------------------------------------- 1 | fr 2 | -------------------------------------------------------------------------------- /po/extra/POTFILES: -------------------------------------------------------------------------------- 1 | data/com.github.artemanufrij.trimdown.appdata.xml.in 2 | data/com.github.artemanufrij.trimdown.desktop.in 3 | -------------------------------------------------------------------------------- /po/extra/extra.pot: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the extra package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: extra\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2019-08-02 12:10+0200\n" 12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 | "Last-Translator: FULL NAME \n" 14 | "Language-Team: LANGUAGE \n" 15 | "Language: \n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=CHARSET\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | 20 | #: data/com.github.artemanufrij.trimdown.appdata.xml.in:7 21 | #: data/com.github.artemanufrij.trimdown.desktop.in:3 22 | #: data/com.github.artemanufrij.trimdown.desktop.in:4 23 | msgid "TrimDown" 24 | msgstr "" 25 | 26 | #: data/com.github.artemanufrij.trimdown.appdata.xml.in:8 27 | #: data/com.github.artemanufrij.trimdown.desktop.in:5 28 | msgid "An app for Novels and script Writer" 29 | msgstr "" 30 | 31 | #: data/com.github.artemanufrij.trimdown.appdata.xml.in:10 32 | msgid "" 33 | "A simple, feature rich, writing app for writing Novels, Short stories, " 34 | "Scripts and Articles." 35 | msgstr "" 36 | 37 | #: data/com.github.artemanufrij.trimdown.appdata.xml.in:20 38 | msgid "Artem Anufrij" 39 | msgstr "" 40 | 41 | #: data/com.github.artemanufrij.trimdown.desktop.in:6 42 | msgid "write;novel;script;article;" 43 | msgstr "" 44 | 45 | #: data/com.github.artemanufrij.trimdown.desktop.in:8 46 | msgid "com.github.artemanufrij.trimdown" 47 | msgstr "" 48 | -------------------------------------------------------------------------------- /po/extra/fr.po: -------------------------------------------------------------------------------- 1 | # French translations for extra package. 2 | # Copyright (C) 2019 THE extra'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the extra package. 4 | # NathanBnm, 2019. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: extra\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2019-08-02 12:10+0200\n" 11 | "PO-Revision-Date: 2019-08-02 11:58+0200\n" 12 | "Last-Translator: NathanBnm\n" 13 | "Language-Team: none\n" 14 | "Language: fr\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 19 | 20 | #: data/com.github.artemanufrij.trimdown.appdata.xml.in:7 21 | #: data/com.github.artemanufrij.trimdown.desktop.in:3 22 | #: data/com.github.artemanufrij.trimdown.desktop.in:4 23 | msgid "TrimDown" 24 | msgstr "TrimDown" 25 | 26 | #: data/com.github.artemanufrij.trimdown.appdata.xml.in:8 27 | #: data/com.github.artemanufrij.trimdown.desktop.in:5 28 | msgid "An app for Novels and script Writer" 29 | msgstr "Une application pour les écrivains de nouvelles et scripts" 30 | 31 | #: data/com.github.artemanufrij.trimdown.appdata.xml.in:10 32 | msgid "" 33 | "A simple, feature rich, writing app for writing Novels, Short stories, " 34 | "Scripts and Articles." 35 | msgstr "" 36 | "Une simple application pleine de fonctionnalités pour écrire des nouvelles, " 37 | "de courtes histories, des scripts et des articles." 38 | 39 | #: data/com.github.artemanufrij.trimdown.appdata.xml.in:20 40 | msgid "Artem Anufrij" 41 | msgstr "Artem Anufrij" 42 | 43 | #: data/com.github.artemanufrij.trimdown.desktop.in:6 44 | msgid "write;novel;script;article;" 45 | msgstr "écriture;nouvelle;script;article;" 46 | 47 | #: data/com.github.artemanufrij.trimdown.desktop.in:8 48 | msgid "com.github.artemanufrij.trimdown" 49 | msgstr "com.github.artemanufrij.trimdown" 50 | -------------------------------------------------------------------------------- /po/extra/meson.build: -------------------------------------------------------------------------------- 1 | i18n.gettext('extra', 2 | args: [ 3 | '--directory=' + meson.source_root(), 4 | '--from-code=UTF-8' 5 | ], 6 | preset: 'glib', 7 | install: false 8 | ) 9 | -------------------------------------------------------------------------------- /po/extra/nl.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the extra package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: extra\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2019-08-02 12:10+0200\n" 11 | "PO-Revision-Date: 2019-08-03 22:47+0200\n" 12 | "Language-Team: Dutch \n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: 8bit\n" 16 | "X-Generator: Poedit 2.2.3\n" 17 | "Last-Translator: Heimen Stoffels \n" 18 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 19 | "Language: nl\n" 20 | 21 | #: data/com.github.artemanufrij.trimdown.appdata.xml.in:7 22 | #: data/com.github.artemanufrij.trimdown.desktop.in:3 23 | #: data/com.github.artemanufrij.trimdown.desktop.in:4 24 | msgid "TrimDown" 25 | msgstr "TrimDown" 26 | 27 | #: data/com.github.artemanufrij.trimdown.appdata.xml.in:8 28 | #: data/com.github.artemanufrij.trimdown.desktop.in:5 29 | msgid "An app for Novels and script Writer" 30 | msgstr "Een app voor het schrijven van romans en scripts" 31 | 32 | #: data/com.github.artemanufrij.trimdown.appdata.xml.in:10 33 | msgid "" 34 | "A simple, feature rich, writing app for writing Novels, Short stories, " 35 | "Scripts and Articles." 36 | msgstr "" 37 | "Een eenvoudig te gebruiken app vol mogelijkheden voor het schrijven " 38 | "van romans, scripts, korte verhalen en artikelen." 39 | 40 | #: data/com.github.artemanufrij.trimdown.appdata.xml.in:20 41 | msgid "Artem Anufrij" 42 | msgstr "Artem Anufrij" 43 | 44 | #: data/com.github.artemanufrij.trimdown.desktop.in:6 45 | msgid "write;novel;script;article;" 46 | msgstr "schrijven;roman;script;artikel;" 47 | 48 | #: data/com.github.artemanufrij.trimdown.desktop.in:8 49 | msgid "com.github.artemanufrij.trimdown" 50 | msgstr "com.github.artemanufrij.trimdown" 51 | -------------------------------------------------------------------------------- /po/fr.po: -------------------------------------------------------------------------------- 1 | # French translations for com.github.artemanufrij.trimdown package. 2 | # Copyright (C) 2019 THE com.github.artemanufrij.trimdown'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the com.github.artemanufrij.trimdown package. 4 | # NathanBnm, 2019. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: com.github.artemanufrij.trimdown\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2019-08-02 11:58+0200\n" 11 | "PO-Revision-Date: 2019-08-02 11:58+0200\n" 12 | "Last-Translator: NathanBnm\n" 13 | "Language-Team: none\n" 14 | "Language: fr\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 19 | 20 | #: src/Dialogs/NewProject.vala:54 src/MainWindow.vala:85 21 | msgid "New Project" 22 | msgstr "Nouveau projet" 23 | 24 | #: src/Dialogs/NewProject.vala:67 25 | msgid "Project Title" 26 | msgstr "Nom du projet" 27 | 28 | #: src/Dialogs/NewProject.vala:73 29 | msgid "[empty]" 30 | msgstr "[vide]" 31 | 32 | #: src/Dialogs/NewProject.vala:74 33 | msgid "SiFi" 34 | msgstr "Sci-Fi" 35 | 36 | #: src/Dialogs/NewProject.vala:75 37 | msgid "Fantasy" 38 | msgstr "Fantasy" 39 | 40 | #. ACTION BUTTONS 41 | #: src/Dialogs/NewProject.vala:85 42 | msgid "Create" 43 | msgstr "Créer" 44 | 45 | #: src/Dialogs/Preferences.vala:62 46 | msgid "Use Dark Theme" 47 | msgstr "Utiliser le thème sombre" 48 | 49 | #: src/Dialogs/Preferences.vala:65 50 | msgid "Remember last Project" 51 | msgstr "Se souvenir du dernier projet" 52 | 53 | #: src/Dialogs/Preferences.vala:73 54 | msgid "Close" 55 | msgstr "Fermer" 56 | 57 | #: src/Objects/Chapter.vala:65 58 | msgid "Scenes" 59 | msgstr "Scènes" 60 | 61 | #: src/Objects/Chapter.vala:66 src/Objects/Project.vala:95 62 | msgid "Notes" 63 | msgstr "Notes" 64 | 65 | #: src/Objects/Chapter.vala:148 src/Objects/Project.vala:94 66 | #, c-format 67 | msgid "Scene %d" 68 | msgstr "Scène %d" 69 | 70 | #: src/Objects/Chapter.vala:167 71 | #, c-format 72 | msgid "Note %d" 73 | msgstr "Note %d" 74 | 75 | #: src/Objects/Project.vala:51 src/Services/ProjectManager.vala:61 76 | msgid "Chapters" 77 | msgstr "Chapitres" 78 | 79 | #: src/Objects/Project.vala:103 80 | #, c-format 81 | msgid "Chapter %d" 82 | msgstr "Chapitre %d" 83 | 84 | #: src/Services/ProjectManager.vala:65 85 | msgid "Prologue" 86 | msgstr "Prologue" 87 | 88 | #: src/Services/ProjectManager.vala:75 89 | msgid "Open a TrimDown project." 90 | msgstr "Ouvrir un projet TrimDown." 91 | 92 | #: src/Services/ProjectManager.vala:76 93 | msgid "_Cancel" 94 | msgstr "_Annuler" 95 | 96 | #: src/Services/ProjectManager.vala:77 97 | msgid "_Open" 98 | msgstr "_Ouvrir" 99 | 100 | #: src/Services/ProjectManager.vala:80 101 | msgid "TrimDown Project" 102 | msgstr "Projet TrimDown" 103 | 104 | #: src/Widgets/Views/Welcome.vala:38 105 | msgid "Title" 106 | msgstr "Titre" 107 | 108 | #: src/Widgets/Views/Welcome.vala:38 109 | msgid "Subtitle." 110 | msgstr "Sous-titre" 111 | 112 | #: src/Widgets/Views/Welcome.vala:39 113 | msgid "Create a new Project" 114 | msgstr "Créer un nouveau projet" 115 | 116 | #: src/Widgets/Views/Welcome.vala:39 117 | msgid "Write your next best seller." 118 | msgstr "Écrivez votre prochain best-seller." 119 | 120 | #: src/Widgets/Views/Welcome.vala:40 121 | msgid "Open a Project" 122 | msgstr "Ouvrir un projet" 123 | 124 | #: src/Widgets/Views/Welcome.vala:40 125 | msgid "Open an exists project from your library." 126 | msgstr "Ouvrez un projet existant depuis votre bibliothèque." 127 | 128 | #: src/Widgets/Chapter.vala:103 src/Widgets/Note.vala:71 129 | #: src/Widgets/Scene.vala:98 130 | msgid "Restore from Bin" 131 | msgstr "Restaurer depuis la corbeille" 132 | 133 | #: src/Widgets/Chapter.vala:105 src/Widgets/Note.vala:73 134 | #: src/Widgets/Scene.vala:100 135 | msgid "Move into Bin" 136 | msgstr "Déplacer vers la corbeille" 137 | 138 | #: src/Widgets/ChapterList.vala:59 139 | msgid "Add a Chapter" 140 | msgstr "Ajouter un chapitre" 141 | 142 | #: src/Widgets/Notes.vala:80 143 | msgid "Add a Note" 144 | msgstr "Ajouter une note" 145 | 146 | #: src/Widgets/SceneList.vala:63 147 | msgid "Add a Scene" 148 | msgstr "Ajouter une scène" 149 | 150 | #: src/MainWindow.vala:90 151 | msgid "Open Project" 152 | msgstr "Ouvrir un projet" 153 | 154 | #: src/MainWindow.vala:105 155 | msgid "Preferences" 156 | msgstr "Préférences" 157 | 158 | #: src/MainWindow.vala:121 159 | msgid "Chapter Notes" 160 | msgstr "Notes de chapitre" 161 | 162 | #: src/MainWindow.vala:141 163 | msgid "Deleted Items" 164 | msgstr "Éléments supprimés" 165 | -------------------------------------------------------------------------------- /po/meson.build: -------------------------------------------------------------------------------- 1 | i18n.gettext(meson.project_name(), 2 | args: [ 3 | '--directory=' + meson.source_root(), 4 | '--from-code=UTF-8' 5 | ], 6 | preset: 'glib' 7 | ) 8 | 9 | subdir('extra') 10 | -------------------------------------------------------------------------------- /po/nl.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the com.github.artemanufrij.trimdown package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: com.github.artemanufrij.trimdown\n" 9 | "Report-Msgid-Bugs-To: \n" 10 | "POT-Creation-Date: 2019-08-02 11:58+0200\n" 11 | "PO-Revision-Date: 2019-08-03 22:44+0200\n" 12 | "Language-Team: Dutch \n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: 8bit\n" 16 | "X-Generator: Poedit 2.2.3\n" 17 | "Last-Translator: Heimen Stoffels \n" 18 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 19 | "Language: nl\n" 20 | 21 | #: src/Dialogs/NewProject.vala:54 src/MainWindow.vala:85 22 | msgid "New Project" 23 | msgstr "Nieuw project" 24 | 25 | #: src/Dialogs/NewProject.vala:67 26 | msgid "Project Title" 27 | msgstr "Naam van project" 28 | 29 | #: src/Dialogs/NewProject.vala:73 30 | msgid "[empty]" 31 | msgstr "[leeg]" 32 | 33 | #: src/Dialogs/NewProject.vala:74 34 | msgid "SiFi" 35 | msgstr "Sci-Fi" 36 | 37 | #: src/Dialogs/NewProject.vala:75 38 | msgid "Fantasy" 39 | msgstr "Fantasy" 40 | 41 | #. ACTION BUTTONS 42 | #: src/Dialogs/NewProject.vala:85 43 | msgid "Create" 44 | msgstr "Creëren" 45 | 46 | #: src/Dialogs/Preferences.vala:62 47 | msgid "Use Dark Theme" 48 | msgstr "Donker thema gebruiken" 49 | 50 | #: src/Dialogs/Preferences.vala:65 51 | msgid "Remember last Project" 52 | msgstr "Vorige project onthouden" 53 | 54 | #: src/Dialogs/Preferences.vala:73 55 | msgid "Close" 56 | msgstr "Sluiten" 57 | 58 | #: src/Objects/Chapter.vala:65 59 | msgid "Scenes" 60 | msgstr "Scènes" 61 | 62 | #: src/Objects/Chapter.vala:66 src/Objects/Project.vala:95 63 | msgid "Notes" 64 | msgstr "Aantekeningen" 65 | 66 | #: src/Objects/Chapter.vala:148 src/Objects/Project.vala:94 67 | #, c-format 68 | msgid "Scene %d" 69 | msgstr "Scène %d" 70 | 71 | #: src/Objects/Chapter.vala:167 72 | #, c-format 73 | msgid "Note %d" 74 | msgstr "Aantekening %d" 75 | 76 | #: src/Objects/Project.vala:51 src/Services/ProjectManager.vala:61 77 | msgid "Chapters" 78 | msgstr "Hoofdstukken" 79 | 80 | #: src/Objects/Project.vala:103 81 | #, c-format 82 | msgid "Chapter %d" 83 | msgstr "Hoofdstuk %d" 84 | 85 | #: src/Services/ProjectManager.vala:65 86 | msgid "Prologue" 87 | msgstr "Voorwoord" 88 | 89 | #: src/Services/ProjectManager.vala:75 90 | msgid "Open a TrimDown project." 91 | msgstr "Open een TrimDown-project." 92 | 93 | #: src/Services/ProjectManager.vala:76 94 | msgid "_Cancel" 95 | msgstr "_Annuleren" 96 | 97 | #: src/Services/ProjectManager.vala:77 98 | msgid "_Open" 99 | msgstr "_Openen" 100 | 101 | #: src/Services/ProjectManager.vala:80 102 | msgid "TrimDown Project" 103 | msgstr "TrimDown-project" 104 | 105 | #: src/Widgets/Views/Welcome.vala:38 106 | msgid "Title" 107 | msgstr "Titel" 108 | 109 | #: src/Widgets/Views/Welcome.vala:38 110 | msgid "Subtitle." 111 | msgstr "Ondertitel." 112 | 113 | #: src/Widgets/Views/Welcome.vala:39 114 | msgid "Create a new Project" 115 | msgstr "Nieuw project creëren" 116 | 117 | #: src/Widgets/Views/Welcome.vala:39 118 | msgid "Write your next best seller." 119 | msgstr "Schrijf je volgende bestseller." 120 | 121 | #: src/Widgets/Views/Welcome.vala:40 122 | msgid "Open a Project" 123 | msgstr "Project openen" 124 | 125 | #: src/Widgets/Views/Welcome.vala:40 126 | msgid "Open an exists project from your library." 127 | msgstr "Open een bestaand project uit je bibliotheek." 128 | 129 | #: src/Widgets/Chapter.vala:103 src/Widgets/Note.vala:71 130 | #: src/Widgets/Scene.vala:98 131 | msgid "Restore from Bin" 132 | msgstr "Terughalen uit prullenbak" 133 | 134 | #: src/Widgets/Chapter.vala:105 src/Widgets/Note.vala:73 135 | #: src/Widgets/Scene.vala:100 136 | msgid "Move into Bin" 137 | msgstr "Verplaatsen naar prullenbak" 138 | 139 | #: src/Widgets/ChapterList.vala:59 140 | msgid "Add a Chapter" 141 | msgstr "Hoofdstuk toevoegen" 142 | 143 | #: src/Widgets/Notes.vala:80 144 | msgid "Add a Note" 145 | msgstr "Aantekening maken" 146 | 147 | #: src/Widgets/SceneList.vala:63 148 | msgid "Add a Scene" 149 | msgstr "Scène toevoegen" 150 | 151 | #: src/MainWindow.vala:90 152 | msgid "Open Project" 153 | msgstr "Project openen" 154 | 155 | #: src/MainWindow.vala:105 156 | msgid "Preferences" 157 | msgstr "Voorkeuren" 158 | 159 | #: src/MainWindow.vala:121 160 | msgid "Chapter Notes" 161 | msgstr "Hoofdstukaantekeningen" 162 | 163 | #: src/MainWindow.vala:141 164 | msgid "Deleted Items" 165 | msgstr "Verwijderde items" 166 | -------------------------------------------------------------------------------- /schemas/com.github.artemanufrij.trimdown.gschema.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1024 5 | The saved width of the window. 6 | The saved width of the window. 7 | 8 | 9 | 720 10 | The saved height of the window. 11 | The saved height of the window. 12 | 13 | 14 | -1 15 | The saved x-position of the window. 16 | The saved x-position of the window. 17 | 18 | 19 | -1 20 | The saved y-position of the window. 21 | The saved y-position of the window. 22 | 23 | 24 | false 25 | Maximized window. 26 | Maximized window. 27 | 28 | 29 | "" 30 | Default projects location. 31 | Default projects location. 32 | 33 | 34 | true 35 | Use Dark Theme. 36 | Use Dark Theme. 37 | 38 | 39 | true 40 | Remember last Project. 41 | Remember last Project. 42 | 43 | 44 | "" 45 | Last Project. 46 | Last Project. 47 | 48 | 49 | "" 50 | Last Chapter. 51 | Last Chapter. 52 | 53 | 54 | "" 55 | Last Scene. 56 | Last Scene. 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /schemas/meson.build: -------------------------------------------------------------------------------- 1 | install_data( 2 | meson.project_name() + '.gschema.xml', 3 | install_dir: join_paths(get_option('datadir'), 'glib-2.0', 'schemas') 4 | ) -------------------------------------------------------------------------------- /src/Application.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown { 29 | public class TrimDownApp : Gtk.Application { 30 | Settings settings; 31 | 32 | static TrimDownApp _instance = null; 33 | public static TrimDownApp instance { 34 | get { 35 | if (_instance == null) { 36 | _instance = new TrimDownApp (); 37 | } 38 | return _instance; 39 | } 40 | } 41 | 42 | construct { 43 | this.application_id = "com.github.artemanufrij.trimdown"; 44 | settings = Settings.get_default (); 45 | 46 | var action_new_chapter = new SimpleAction ("new-chapter", null); 47 | add_action (action_new_chapter); 48 | add_accelerator ("c", "app.new-chapter", null); 49 | action_new_chapter.activate.connect ( 50 | () => { 51 | if (mainwindow != null) { 52 | mainwindow.new_chapter_action (); 53 | } 54 | }); 55 | 56 | var action_new_scene = new SimpleAction ("new-scene", null); 57 | add_action (action_new_scene); 58 | add_accelerator ("s", "app.new-scene", null); 59 | action_new_scene.activate.connect ( 60 | () => { 61 | if (mainwindow != null) { 62 | mainwindow.new_scene_action (); 63 | } 64 | }); 65 | } 66 | 67 | private TrimDownApp () { 68 | create_project_folder (); 69 | } 70 | 71 | public MainWindow mainwindow { get; private set; default = null; } 72 | 73 | private void create_project_folder () { 74 | var library_path = File.new_for_path (settings.projects_location); 75 | if (settings.projects_location == "" || !library_path.query_exists ()) { 76 | settings.projects_location = Path.build_filename (GLib.Environment.get_user_special_dir (GLib.UserDirectory.DOCUMENTS), "Trimdown"); 77 | library_path = File.new_for_path (settings.projects_location); 78 | if (!library_path.query_exists ()) { 79 | try { 80 | library_path.make_directory (); 81 | } catch (Error err) { 82 | warning (err.message); 83 | } 84 | } 85 | } 86 | } 87 | 88 | protected override void activate () { 89 | if (mainwindow == null) { 90 | mainwindow = new MainWindow (); 91 | mainwindow.application = this; 92 | } 93 | mainwindow.present (); 94 | } 95 | } 96 | } 97 | 98 | public static int main (string [] args) { 99 | Gtk.init (ref args); 100 | var app = TrimDown.TrimDownApp.instance; 101 | return app.run (args); 102 | } 103 | -------------------------------------------------------------------------------- /src/Dialogs/NewProject.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Dialogs { 29 | public class NewProject : Gtk.Dialog { 30 | Services.ProjectManager project_manager; 31 | 32 | Gtk.Entry entry_title; 33 | Gtk.ComboBoxText choose_type; 34 | Gtk.Button create_button; 35 | 36 | public string project_title { get; private set; default = ""; } 37 | public string project_kind { get; private set; default = ""; } 38 | 39 | construct { 40 | project_manager = Services.ProjectManager.instance; 41 | } 42 | 43 | 44 | public NewProject (Gtk.Window parent) { 45 | Object (transient_for: parent, resizable: false, use_header_bar: 1); 46 | build_ui (); 47 | } 48 | 49 | private void build_ui () { 50 | // HEADER 51 | var header = this.get_header_bar () as Gtk.HeaderBar; 52 | header.get_style_context ().add_class ("default-decoration"); 53 | header.set_custom_title ( 54 | new Gtk.Label (_ ("New Project")) { 55 | margin_top = 6 56 | }); 57 | 58 | // CONTENT 59 | Gtk.Box content = this.get_content_area () as Gtk.Box; 60 | 61 | var grid = new Gtk.Grid (); 62 | grid.margin = 12; 63 | grid.row_spacing = 12; 64 | 65 | entry_title = new Gtk.Entry (); 66 | entry_title.hexpand = true; 67 | entry_title.placeholder_text = _ ("Project Title"); 68 | entry_title.get_style_context ().add_class ("h3"); 69 | entry_title.changed.connect (validate_entries); 70 | grid.attach (entry_title, 0, 0); 71 | 72 | choose_type = new Gtk.ComboBoxText (); 73 | choose_type.append ("[empty]", _ ("[empty]")); 74 | choose_type.append ("SiFi", _ ("SiFi")); 75 | choose_type.append ("Fantasy", _ ("Fantasy")); 76 | choose_type.active_id = "[empty]"; 77 | 78 | grid.attach (choose_type, 0, 1); 79 | 80 | content.pack_start (grid); 81 | 82 | // ACTION BUTTONS 83 | Gtk.Box actions = this.get_action_area () as Gtk.Box; 84 | 85 | create_button = new Gtk.Button.with_label (_ ("Create")); 86 | create_button.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); 87 | create_button.sensitive = false; 88 | create_button.clicked.connect ( 89 | () => { 90 | this.response (Gtk.ResponseType.ACCEPT); 91 | }); 92 | 93 | actions.add (create_button); 94 | 95 | this.show_all (); 96 | } 97 | 98 | private void validate_entries () { 99 | project_title = entry_title.text.strip (); 100 | if (choose_type.active_id == "[empty]") { 101 | project_kind = ""; 102 | } else { 103 | project_kind = choose_type.active_id; 104 | } 105 | create_button.sensitive = !project_manager.project_name_exists (project_title); 106 | } 107 | } 108 | } -------------------------------------------------------------------------------- /src/Dialogs/Preferences.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Dialogs { 29 | public class Preferences : Gtk.Dialog { 30 | Settings settings; 31 | 32 | construct { 33 | settings = Settings.get_default (); 34 | } 35 | 36 | public Preferences (Gtk.Window parent) { 37 | Object (transient_for: parent, deletable: false, resizable: false); 38 | build_ui (); 39 | } 40 | 41 | private void build_ui () { 42 | var use_dark_theme = new Gtk.Switch (); 43 | use_dark_theme.active = settings.use_dark_theme; 44 | use_dark_theme.notify["active"].connect ( 45 | () => { 46 | settings.use_dark_theme = use_dark_theme.active; 47 | }); 48 | 49 | var remember_last_project = new Gtk.Switch (); 50 | remember_last_project.active = settings.remember_last_project; 51 | remember_last_project.notify["active"].connect ( 52 | () => { 53 | settings.remember_last_project = remember_last_project.active; 54 | }); 55 | 56 | 57 | var genera_grid = new Gtk.Grid (); 58 | genera_grid.column_spacing = 12; 59 | genera_grid.row_spacing = 12; 60 | genera_grid.margin = 12; 61 | 62 | genera_grid.attach (label_generator (_ ("Use Dark Theme")), 0, 0); 63 | genera_grid.attach (use_dark_theme, 1, 0); 64 | genera_grid.attach (new Gtk.Separator (Gtk.Orientation.HORIZONTAL), 0, 1, 2, 1); 65 | genera_grid.attach (label_generator (_ ("Remember last Project")), 0, 2); 66 | genera_grid.attach (remember_last_project, 1, 2); 67 | 68 | var content = this.get_content_area () as Gtk.Box; 69 | content.pack_start (genera_grid, false, false, 0); 70 | 71 | 72 | 73 | var close_button = new Gtk.Button.with_label (_ ("Close")); 74 | close_button.clicked.connect (() => { this.destroy (); }); 75 | 76 | Gtk.Box actions = this.get_action_area () as Gtk.Box; 77 | actions.add (close_button); 78 | 79 | this.show_all (); 80 | } 81 | 82 | private Gtk.Label ? label_generator (string content) { 83 | return new Gtk.Label (content) { 84 | halign = Gtk.Align.START, 85 | hexpand = true 86 | }; 87 | } 88 | } 89 | } -------------------------------------------------------------------------------- /src/MainWindow.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown { 29 | public class MainWindow : Gtk.Window { 30 | Services.ProjectManager project_manager; 31 | Settings settings; 32 | 33 | Gtk.HeaderBar headerbar; 34 | Gtk.Stack content; 35 | Gtk.MenuButton app_menu; 36 | Gtk.Button open_proj; 37 | Gtk.Button new_proj; 38 | Gtk.Button notes_button; 39 | Gtk.Button bin_items; 40 | 41 | Widgets.Views.Writer writer; 42 | 43 | construct { 44 | settings = Settings.get_default (); 45 | settings.notify["use-dark-theme"].connect ( 46 | () => { 47 | Gtk.Settings.get_default ().gtk_application_prefer_dark_theme = settings.use_dark_theme; 48 | if (settings.use_dark_theme) { 49 | app_menu.set_image (new Gtk.Image.from_icon_name ("open-menu-symbolic", Gtk.IconSize.LARGE_TOOLBAR)); 50 | } else { 51 | app_menu.set_image (new Gtk.Image.from_icon_name ("open-menu", Gtk.IconSize.LARGE_TOOLBAR)); 52 | } 53 | }); 54 | 55 | project_manager = Services.ProjectManager.instance; 56 | } 57 | 58 | public MainWindow () { 59 | load_settings (); 60 | build_ui (); 61 | load_last_project (); 62 | this.configure_event.connect ( 63 | (event) => { 64 | settings.window_width = event.width; 65 | settings.window_height = event.height; 66 | return false; 67 | }); 68 | 69 | this.delete_event.connect ( 70 | () => { 71 | save_settings (); 72 | return false; 73 | }); 74 | Utils.set_custom_css_style (this.get_screen ()); 75 | } 76 | 77 | private void build_ui () { 78 | headerbar = new Gtk.HeaderBar (); 79 | headerbar.title = "TrimDown"; 80 | headerbar.show_close_button = true; 81 | headerbar.get_style_context ().add_class ("default-decoration"); 82 | this.set_titlebar (headerbar); 83 | 84 | new_proj = new Gtk.Button.from_icon_name ("document-new", Gtk.IconSize.LARGE_TOOLBAR); 85 | new_proj.tooltip_text = _ ("New Project"); 86 | new_proj.clicked.connect (create_project_action); 87 | headerbar.pack_start (new_proj); 88 | 89 | open_proj = new Gtk.Button.from_icon_name ("document-open", Gtk.IconSize.LARGE_TOOLBAR); 90 | open_proj.tooltip_text = _ ("Open Project"); 91 | open_proj.clicked.connect (open_project_action); 92 | headerbar.pack_start (open_proj); 93 | 94 | // SETTINGS MENU 95 | app_menu = new Gtk.MenuButton (); 96 | app_menu.valign = Gtk.Align.CENTER; 97 | if (settings.use_dark_theme) { 98 | app_menu.set_image (new Gtk.Image.from_icon_name ("open-menu-symbolic", Gtk.IconSize.LARGE_TOOLBAR)); 99 | } else { 100 | app_menu.set_image (new Gtk.Image.from_icon_name ("open-menu", Gtk.IconSize.LARGE_TOOLBAR)); 101 | } 102 | 103 | var settings_menu = new Gtk.Menu (); 104 | 105 | var menu_item_preferences = new Gtk.MenuItem.with_label (_ ("Preferences")); 106 | menu_item_preferences.activate.connect ( 107 | () => { 108 | var preferences = new Dialogs.Preferences (this); 109 | preferences.run (); 110 | }); 111 | settings_menu.append (menu_item_preferences); 112 | settings_menu.show_all (); 113 | 114 | app_menu.popup = settings_menu; 115 | headerbar.pack_end (app_menu); 116 | 117 | // NOTES 118 | var notes = new Widgets.Notes (); 119 | 120 | notes_button = new Gtk.Button.from_icon_name ("format-text-highlight", Gtk.IconSize.LARGE_TOOLBAR); 121 | notes_button.tooltip_text = _ ("Chapter Notes"); 122 | var notes_popup = new Gtk.Popover (notes_button); 123 | notes_popup.closed.connect ( 124 | () => { 125 | notes.save_note (); 126 | }); 127 | notes_popup.add (notes); 128 | notes_button.clicked.connect ( 129 | () => { 130 | if (writer.current_chapter != null) { 131 | notes.show_notes (writer.current_chapter); 132 | } 133 | notes_popup.show_all (); 134 | }); 135 | headerbar.pack_end (notes_button); 136 | 137 | // BIN 138 | var bin = new Widgets.Bin (); 139 | 140 | bin_items = new Gtk.Button.from_icon_name ("user-trash", Gtk.IconSize.LARGE_TOOLBAR); 141 | bin_items.tooltip_text = _ ("Deleted Items"); 142 | var bin_popup = new Gtk.Popover (bin_items); 143 | bin_popup.add (bin); 144 | bin_items.clicked.connect ( 145 | () => { 146 | if (writer.current_project != null) { 147 | bin.show_content (writer.current_project); 148 | } 149 | bin_popup.show (); 150 | }); 151 | 152 | headerbar.pack_end (bin_items); 153 | 154 | content = new Gtk.Stack (); 155 | 156 | var welcome = new Widgets.Views.Welcome (); 157 | welcome.new_project_clicked.connect (create_project_action); 158 | welcome.open_project_clicked.connect (open_project_action); 159 | 160 | writer = new Widgets.Views.Writer (this); 161 | 162 | content.add_named (welcome, "welcome"); 163 | content.add_named (writer, "writer"); 164 | this.add (content); 165 | this.show_all (); 166 | new_proj.hide (); 167 | open_proj.hide (); 168 | notes_button.hide (); 169 | bin_items.hide (); 170 | } 171 | 172 | private void open_project_action () { 173 | var project = project_manager.open_project (); 174 | if (project != null) { 175 | open_project (project); 176 | } 177 | } 178 | 179 | private void create_project_action () { 180 | var new_project = new Dialogs.NewProject (this); 181 | if (new_project.run () == Gtk.ResponseType.ACCEPT) { 182 | var project = project_manager.create_new_project (new_project.project_title, new_project.project_kind); 183 | if (project != null) { 184 | open_project (project); 185 | } 186 | } 187 | new_project.destroy (); 188 | } 189 | 190 | public void new_chapter_action () { 191 | if (content.visible_child_name == "writer" && writer.current_project != null) { 192 | writer.current_project.generate_new_chapter (); 193 | } 194 | } 195 | 196 | public void new_scene_action () { 197 | if (content.visible_child_name == "writer" && writer.current_chapter != null) { 198 | writer.current_chapter.generate_new_scene (); 199 | } 200 | } 201 | 202 | private void open_project (Objects.Project project) { 203 | headerbar.title = project.title; 204 | writer.show_project (project); 205 | content.visible_child_name = "writer"; 206 | open_proj.show (); 207 | new_proj.show (); 208 | notes_button.show (); 209 | bin_items.show (); 210 | } 211 | 212 | private void load_last_project () { 213 | if (settings.remember_last_project && settings.last_project != "" && FileUtils.test (settings.last_project, FileTest.EXISTS)) { 214 | var project = new Objects.Project (settings.last_project); 215 | open_project (project); 216 | 217 | writer.select_chapter (settings.last_chapter); 218 | writer.select_scene (settings.last_scene); 219 | } 220 | } 221 | 222 | private void load_settings () { 223 | this.set_default_size (settings.window_width, settings.window_height); 224 | 225 | if (settings.window_x < 0 || settings.window_y < 0 ) { 226 | this.window_position = Gtk.WindowPosition.CENTER; 227 | } else { 228 | this.move (settings.window_x, settings.window_y); 229 | } 230 | 231 | Gtk.Settings.get_default ().gtk_application_prefer_dark_theme = settings.use_dark_theme; 232 | } 233 | 234 | private void save_settings () { 235 | int x, y; 236 | this.get_position (out x, out y); 237 | settings.window_x = x; 238 | settings.window_y = y; 239 | 240 | if (settings.remember_last_project && writer.current_project != null) { 241 | settings.last_project = writer.current_project.path; 242 | if (writer.current_chapter != null) { 243 | settings.last_chapter = writer.current_chapter.name; 244 | } else { 245 | settings.last_chapter = ""; 246 | } 247 | 248 | if (writer.current_scene != null) { 249 | settings.last_scene = writer.current_scene.name; 250 | } else { 251 | settings.last_scene = ""; 252 | } 253 | } else { 254 | settings.last_project = ""; 255 | settings.last_chapter = ""; 256 | settings.last_scene = ""; 257 | } 258 | } 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /src/Objects/BaseObject.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Objects { 29 | public class BaseObject : GLib.Object { 30 | public signal void content_saved (); 31 | public signal void title_saved (string title); 32 | public signal void bin_location_changed (bool bin); 33 | 34 | public string path { get; protected set; } 35 | public string title { get; protected set; } 36 | public string name { get; protected set; } 37 | public int order { get; protected set; default = 0; } 38 | public bool bin { get; protected set; default = false; } 39 | 40 | public string properties_path { get; protected set; } 41 | protected KeyFile properties; 42 | 43 | construct { 44 | properties = new KeyFile (); 45 | } 46 | 47 | protected void load_properties () { 48 | if (!FileUtils.test (properties_path, FileTest.EXISTS)) { 49 | try { 50 | if (this is Chapter) { 51 | FileUtils.set_contents (properties_path, Utils.get_new_chapter_property (name, order)); 52 | } else if (this is Scene) { 53 | FileUtils.set_contents (properties_path, Utils.get_new_scene_property (name, order)); 54 | } else if (this is Note) { 55 | FileUtils.set_contents (properties_path, Utils.get_new_note_property (name, order)); 56 | } 57 | } catch (Error err) { 58 | warning (err.message); 59 | return; 60 | } 61 | } 62 | 63 | try { 64 | properties.load_from_file (properties_path, KeyFileFlags.NONE); 65 | } catch (Error err) { 66 | warning (err.message); 67 | return; 68 | } 69 | 70 | var t = get_string_property ("General", "title"); 71 | if (t != "") { 72 | title = t; 73 | } 74 | if (!(this is Project)) { 75 | order = get_integer_property ("General", "order"); 76 | name = get_string_property ("General", "name"); 77 | bin = get_boolean_property ("General", "bin"); 78 | } 79 | } 80 | 81 | public void move_into_bin () { 82 | if (set_boolean_property ("General", "bin", true)) { 83 | bin = true; 84 | bin_location_changed (bin); 85 | } 86 | } 87 | 88 | public void restore_from_bin () { 89 | if (set_boolean_property ("General", "bin", false)) { 90 | bin = false; 91 | bin_location_changed (bin); 92 | } 93 | } 94 | 95 | protected string get_string_property (string group, string key) { 96 | try { 97 | return properties.get_string (group, key); 98 | } catch (Error err) { 99 | warning ("%s: %s\n", err.message, properties_path); 100 | } 101 | return ""; 102 | } 103 | 104 | protected int get_integer_property (string group, string key) { 105 | try { 106 | return properties.get_integer (group, key); 107 | } catch (Error err) { 108 | warning ("%s: %s\n", err.message, properties_path); 109 | } 110 | return 0; 111 | } 112 | 113 | protected bool get_boolean_property (string group, string key) { 114 | try { 115 | return properties.get_boolean (group, key); 116 | } catch (Error err) { 117 | warning ("%s: %s\n", err.message, properties_path); 118 | } 119 | return false; 120 | } 121 | 122 | protected bool set_string_property (string group, string key, string val) { 123 | properties.set_string (group, key, val); 124 | return save_property_file (); 125 | } 126 | 127 | protected bool set_boolean_property (string group, string key, bool val) { 128 | properties.set_boolean (group, key, val); 129 | return save_property_file (); 130 | } 131 | 132 | protected bool set_integer_property (string group, string key, int val) { 133 | properties.set_integer (group, key, val); 134 | return save_property_file (); 135 | } 136 | 137 | 138 | private bool save_property_file () { 139 | try { 140 | properties.save_to_file (properties_path); 141 | } catch (Error err) { 142 | warning (err.message); 143 | return false; 144 | } 145 | return true; 146 | } 147 | 148 | public void set_new_title (string new_title) { 149 | if (set_string_property ("General", "title", new_title)) { 150 | title = new_title; 151 | } 152 | title_saved (title); 153 | } 154 | 155 | public void set_new_order (int new_order) { 156 | if (set_integer_property ("General", "order", new_order)) { 157 | order = new_order; 158 | } 159 | } 160 | } 161 | } -------------------------------------------------------------------------------- /src/Objects/Chapter.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Objects { 29 | public class Chapter : BaseObject { 30 | public signal void scene_created (Scene scene); 31 | public signal void note_created (Note note); 32 | 33 | public Project parent { get; private set; } 34 | public string scenes_path { get; private set; } 35 | public string notes_path { get; private set; } 36 | 37 | GLib.List ? _scenes = null; 38 | public GLib.List scenes { 39 | get { 40 | if (_scenes == null) { 41 | _scenes = get_scene_collection (); 42 | } 43 | return _scenes; 44 | } 45 | } 46 | 47 | GLib.List ? _notes = null; 48 | public GLib.List notes { 49 | get { 50 | if (_notes == null) { 51 | _notes = get_note_collection (); 52 | } 53 | return _notes; 54 | } 55 | } 56 | 57 | public Chapter (Objects.Project project, string name = "", int order = 0) { 58 | this.parent = project; 59 | this.title = name; 60 | this.name = name; 61 | this.order = order; 62 | 63 | path = Path.build_filename (parent.chapters_path, name); 64 | properties_path = Path.build_filename (path, "properties"); 65 | scenes_path = Path.build_filename (path, _ ("Scenes")); 66 | notes_path = Path.build_filename (path, _ ("Notes")); 67 | 68 | init (); 69 | } 70 | 71 | private void init () { 72 | if (!FileUtils.test (scenes_path, FileTest.EXISTS)) { 73 | DirUtils.create_with_parents (scenes_path, 0755); 74 | } 75 | 76 | if (!FileUtils.test (notes_path, FileTest.EXISTS)) { 77 | DirUtils.create_with_parents (notes_path, 0755); 78 | } 79 | 80 | load_properties (); 81 | } 82 | 83 | public bool has_bin_children () { 84 | foreach (var note in notes) { 85 | if (note.bin) { 86 | return true; 87 | } 88 | } 89 | 90 | foreach (var scene in scenes) { 91 | if (scene.bin) { 92 | return true; 93 | } 94 | } 95 | 96 | return false; 97 | } 98 | 99 | private GLib.List get_scene_collection () { 100 | GLib.List return_value = new GLib.List (); 101 | 102 | var directory = File.new_for_path (scenes_path); 103 | try { 104 | var children = directory.enumerate_children ("standard::*," + FileAttribute.STANDARD_CONTENT_TYPE, GLib.FileQueryInfoFlags.NONE); 105 | FileInfo file_info = null; 106 | 107 | while ((file_info = children.next_file ()) != null) { 108 | if (file_info.get_file_type () == FileType.DIRECTORY) { 109 | var scene = new Scene (this, file_info.get_name ()); 110 | return_value.append (scene); 111 | } 112 | } 113 | } catch (Error err) { 114 | warning (err.message); 115 | } 116 | return return_value; 117 | } 118 | 119 | private GLib.List get_note_collection () { 120 | GLib.List return_value = new GLib.List (); 121 | 122 | var directory = File.new_for_path (notes_path); 123 | try { 124 | var children = directory.enumerate_children ("standard::*," + FileAttribute.STANDARD_CONTENT_TYPE, GLib.FileQueryInfoFlags.NONE); 125 | FileInfo file_info = null; 126 | 127 | while ((file_info = children.next_file ()) != null) { 128 | if (file_info.get_content_type () == "text/plain" && !file_info.get_name ().has_suffix ("properties")) { 129 | var note = new Note (this, file_info.get_name ()); 130 | return_value.append (note); 131 | } 132 | } 133 | } catch (Error err) { 134 | warning (err.message); 135 | } 136 | return return_value; 137 | } 138 | 139 | public Scene create_new_scene (string name, int order) { 140 | var new_scene = new Scene (this, name, order); 141 | return new_scene; 142 | } 143 | 144 | public Scene generate_new_scene () { 145 | int i = 1; 146 | string new_scene_name = ""; 147 | do { 148 | new_scene_name = _ ("Scene %d").printf (i); 149 | i++; 150 | } while (FileUtils.test (Path.build_filename (scenes_path, new_scene_name), FileTest.EXISTS)); 151 | 152 | var new_scene = create_new_scene (new_scene_name, i); 153 | _scenes.append (new_scene); 154 | scene_created (new_scene); 155 | return new_scene; 156 | } 157 | 158 | public Note create_new_note (string title) { 159 | var new_note = new Note (this, title); 160 | return new_note; 161 | } 162 | 163 | public Note generate_new_note () { 164 | int i = 1; 165 | string new_note_name = ""; 166 | do { 167 | new_note_name = _ ("Note %d").printf (i); 168 | i++; 169 | } while (FileUtils.test (Path.build_filename (notes_path, new_note_name), FileTest.EXISTS)); 170 | 171 | var new_note = create_new_note (new_note_name); 172 | _notes.append (new_note); 173 | note_created (new_note); 174 | return new_note; 175 | } 176 | 177 | public void reorder_scenes (int from, int to) { 178 | var from_path = ""; 179 | foreach (var scene in scenes) { 180 | if (scene.order == from) { 181 | from_path = scene.path; 182 | if (from > to) { 183 | scene.set_new_order (to); 184 | } else { 185 | scene.set_new_order (to - 1); 186 | } 187 | } 188 | } 189 | 190 | if (from > to) { 191 | foreach (var scene in scenes) { 192 | if (scene.order >= to && scene.order < from && scene.path != from_path) { 193 | scene.set_new_order (scene.order + 1); 194 | } 195 | } 196 | } else { 197 | foreach (var scene in scenes) { 198 | if (scene.order < to && scene.order >= from && scene.path != from_path) { 199 | scene.set_new_order (scene.order - 1); 200 | } 201 | } 202 | } 203 | } 204 | } 205 | } -------------------------------------------------------------------------------- /src/Objects/Note.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Objects { 29 | public class Note : BaseObject { 30 | public Chapter parent { get; private set; } 31 | 32 | string content_path; 33 | 34 | public Note (Chapter chapter, string title) { 35 | this.parent = chapter; 36 | this.title = title; 37 | this.name = title; 38 | 39 | content_path = Path.build_filename (parent.notes_path, title); 40 | properties_path = content_path + ".properties"; 41 | 42 | init (); 43 | } 44 | 45 | private void init () { 46 | if (!FileUtils.test (content_path, FileTest.EXISTS)) { 47 | try { 48 | FileUtils.set_contents (content_path, ""); 49 | } catch (Error err) { 50 | warning (err.message); 51 | return; 52 | } 53 | } 54 | load_properties (); 55 | } 56 | 57 | public string get_content () { 58 | string content = ""; 59 | try { 60 | FileUtils.get_contents (content_path, out content); 61 | } catch (Error err) { 62 | warning (err.message); 63 | } 64 | return content; 65 | } 66 | 67 | public bool save_content (string content) { 68 | try { 69 | FileUtils.set_contents (content_path, content); 70 | } catch (Error err) { 71 | warning (err.message); 72 | return false; 73 | } 74 | return true; 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /src/Objects/Project.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Objects { 29 | public class Project : BaseObject { 30 | public signal void chapter_created (Objects.Chapter chapter); 31 | 32 | public string kind { get; private set; } 33 | 34 | public string chapters_path { get; private set; } 35 | 36 | GLib.List ? _chapters = null; 37 | public GLib.List chapters { 38 | get { 39 | if (_chapters == null) { 40 | _chapters = get_chapter_collection (); 41 | } 42 | return _chapters; 43 | } 44 | } 45 | 46 | public Project (string path, string kind = "") { 47 | this.path = path; 48 | this.kind = kind; 49 | this.title = Path.get_basename (path); 50 | 51 | chapters_path = Path.build_filename (path, _ ("Chapters")); 52 | properties_path = Path.build_filename (path, title + ".td"); 53 | 54 | init (); 55 | } 56 | 57 | private void init () { 58 | if (!FileUtils.test (properties_path, FileTest.EXISTS)) { 59 | try { 60 | FileUtils.set_contents (properties_path, Utils.get_new_project_property (title, kind)); 61 | } catch (Error err) { 62 | warning (err.message); 63 | return; 64 | } 65 | } 66 | 67 | load_properties (); 68 | 69 | kind = get_string_property ("Metadata", "kind"); 70 | } 71 | 72 | private GLib.List get_chapter_collection () { 73 | GLib.List return_value = new GLib.List (); 74 | var directory = File.new_for_path (chapters_path); 75 | try { 76 | var children = directory.enumerate_children ("standard::*," + FileAttribute.STANDARD_CONTENT_TYPE, GLib.FileQueryInfoFlags.NONE); 77 | FileInfo file_info = null; 78 | 79 | while ((file_info = children.next_file ()) != null) { 80 | if (file_info.get_file_type () == FileType.DIRECTORY) { 81 | var chapter = new Chapter (this, file_info.get_name ()); 82 | return_value.append (chapter); 83 | } 84 | } 85 | } catch (Error err) { 86 | warning (err.message); 87 | } 88 | 89 | return return_value; 90 | } 91 | 92 | public Chapter create_new_chapter (string name, int order) { 93 | var new_chapter = new Chapter (this, name, order); 94 | new_chapter.create_new_scene (_ ("Scene %d").printf (1), 0); 95 | new_chapter.create_new_note (_ ("Notes")); 96 | return new_chapter; 97 | } 98 | 99 | public Chapter generate_new_chapter () { 100 | int i = 1; 101 | string new_chapter_name = ""; 102 | do { 103 | new_chapter_name = _ ("Chapter %d").printf (i); 104 | i++; 105 | } while (FileUtils.test (Path.build_filename (chapters_path, new_chapter_name), FileTest.EXISTS)); 106 | 107 | var new_chapter = create_new_chapter (new_chapter_name, i); 108 | chapter_created (new_chapter); 109 | return new_chapter; 110 | } 111 | 112 | public void reorder_chapters (int from, int to) { 113 | var from_path = ""; 114 | foreach (var chapter in chapters) { 115 | if (chapter.order == from) { 116 | from_path = chapter.path; 117 | if (from > to) { 118 | chapter.set_new_order (to); 119 | } else { 120 | chapter.set_new_order (to - 1); 121 | } 122 | } 123 | } 124 | 125 | if (from > to) { 126 | foreach (var chapter in chapters) { 127 | if (chapter.order >= to && chapter.order < from && chapter.path != from_path) { 128 | chapter.set_new_order (chapter.order + 1); 129 | } 130 | } 131 | } else { 132 | foreach (var chapter in chapters) { 133 | if (chapter.order < to && chapter.order >= from && chapter.path != from_path) { 134 | chapter.set_new_order (chapter.order - 1); 135 | } 136 | } 137 | } 138 | } 139 | } 140 | } -------------------------------------------------------------------------------- /src/Objects/Scene.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Objects { 29 | public class Scene : BaseObject { 30 | 31 | public Chapter parent { get; private set; } 32 | 33 | string content_path; 34 | 35 | public Scene (Chapter chapter, string name, int order = 0) { 36 | this.parent = chapter; 37 | this.title = name; 38 | this.order = order; 39 | this.name = name; 40 | 41 | path = Path.build_filename (parent.scenes_path, name); 42 | properties_path = Path.build_filename (path, "properties"); 43 | content_path = Path.build_filename (path, "content"); 44 | 45 | init (); 46 | } 47 | 48 | private void init () { 49 | if (!FileUtils.test (path, FileTest.EXISTS)) { 50 | DirUtils.create_with_parents (path, 0755); 51 | } 52 | 53 | if (!FileUtils.test (content_path, FileTest.EXISTS)) { 54 | try { 55 | FileUtils.set_contents (content_path, ""); 56 | } catch (Error err) { 57 | warning (err.message); 58 | return; 59 | } 60 | } 61 | 62 | load_properties (); 63 | } 64 | 65 | public string get_content () { 66 | string content = ""; 67 | try { 68 | FileUtils.get_contents (content_path, out content); 69 | } catch (Error err) { 70 | warning (err.message); 71 | } 72 | return content; 73 | } 74 | 75 | public bool save_content (string content) { 76 | try { 77 | FileUtils.set_contents (content_path, content); 78 | } catch (Error err) { 79 | warning (err.message); 80 | return false; 81 | } 82 | content_saved (); 83 | return true; 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /src/Services/ProjectManager.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Services { 29 | public class ProjectManager : GLib.Object { 30 | Settings settings; 31 | 32 | static ProjectManager _instance = null; 33 | public static ProjectManager instance { 34 | get { 35 | if (_instance == null) { 36 | _instance = new ProjectManager (); 37 | } 38 | return _instance; 39 | } 40 | } 41 | 42 | construct { 43 | settings = Settings.get_default (); 44 | } 45 | 46 | private ProjectManager() { 47 | } 48 | 49 | public bool project_name_exists (string title) { 50 | if (title.strip () == "") { 51 | return true; 52 | } 53 | 54 | var project_path = Path.build_filename (settings.projects_location, title); 55 | return FileUtils.test (project_path, FileTest.EXISTS); 56 | } 57 | 58 | public Objects.Project ? create_new_project (string title, string kind = "") { 59 | var project_path = Path.build_filename (settings.projects_location, title); 60 | if (!FileUtils.test (project_path, FileTest.EXISTS)) { 61 | var basic_struct = Path.build_filename (project_path, _("Chapters")); 62 | DirUtils.create_with_parents (basic_struct, 0755); 63 | 64 | var new_project = new Objects.Project (project_path, kind); 65 | new_project.create_new_chapter (_("Prologue"), 0); 66 | return new_project; 67 | } 68 | 69 | return null; 70 | } 71 | 72 | public Objects.Project ? open_project () { 73 | Objects.Project ? return_value = null; 74 | Gtk.FileChooserDialog chooser = new Gtk.FileChooserDialog ( 75 | _ ("Open a TrimDown project."), TrimDownApp.instance.mainwindow, Gtk.FileChooserAction.OPEN, 76 | _ ("_Cancel"), Gtk.ResponseType.CANCEL, 77 | _ ("_Open"), Gtk.ResponseType.ACCEPT); 78 | 79 | var filter = new Gtk.FileFilter (); 80 | filter.set_filter_name (_ ("TrimDown Project")); 81 | filter.add_pattern ("*.td"); 82 | 83 | chooser.add_filter (filter); 84 | 85 | if (chooser.run () == Gtk.ResponseType.ACCEPT) { 86 | var dir = Path.get_dirname (chooser.get_file ().get_path ()); 87 | return_value = new Objects.Project (dir); 88 | } 89 | 90 | chooser.destroy (); 91 | return return_value; 92 | } 93 | } 94 | } -------------------------------------------------------------------------------- /src/Settings.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown { 29 | public class Settings : Granite.Services.Settings { 30 | private static Settings settings; 31 | public static Settings get_default () { 32 | if (settings == null) { 33 | settings = new Settings (); 34 | } 35 | return settings; 36 | } 37 | public int window_width { get; set; } 38 | public int window_height { get; set; } 39 | public int window_x { get; set; } 40 | public int window_y { get; set; } 41 | public bool window_maximized { get; set; } 42 | public string projects_location { get; set; } 43 | public bool use_dark_theme { get; set; } 44 | public bool remember_last_project { get; set; } 45 | public string last_project { get; set; } 46 | public string last_chapter { get; set; } 47 | public string last_scene { get; set; } 48 | 49 | private Settings () { 50 | base ("com.github.artemanufrij.trimdown"); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Utils/Enums.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Enums { 29 | public enum ItemStyle { DEFAULT, BIN } 30 | } -------------------------------------------------------------------------------- /src/Utils/Lists.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Utils { 29 | public static int chapters_sort_func (Gtk.ListBoxRow child1, Gtk.ListBoxRow child2) { 30 | var item1 = (Widgets.Chapter)child1; 31 | var item2 = (Widgets.Chapter)child2; 32 | if (item1 != null && item2 != null) { 33 | if (item1.order != item2.order) { 34 | return item1.order - item2.order; 35 | } 36 | return item1.title.collate (item2.title); 37 | } 38 | return 0; 39 | } 40 | 41 | public static int scenes_sort_func (Gtk.ListBoxRow child1, Gtk.ListBoxRow child2) { 42 | var item1 = (Widgets.Scene)child1; 43 | var item2 = (Widgets.Scene)child2; 44 | if (item1 != null && item2 != null) { 45 | if (item1.order != item2.order) { 46 | return item1.order - item2.order; 47 | } 48 | return item1.name.collate (item2.name); 49 | } 50 | return 0; 51 | } 52 | 53 | public static int notes_sort_func (Gtk.ListBoxRow child1, Gtk.ListBoxRow child2) { 54 | var item1 = (Widgets.Note)child1; 55 | var item2 = (Widgets.Note)child2; 56 | if (item1 != null && item2 != null) { 57 | return item1.title.collate (item2.title); 58 | } 59 | return 0; 60 | } 61 | } -------------------------------------------------------------------------------- /src/Utils/Utils.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Utils { 29 | public static string get_new_project_property (string title, string kind) { 30 | return """[General] 31 | title=""" + title + """ 32 | [Metadata] 33 | kind=""" + kind + """ 34 | """; 35 | } 36 | 37 | public static string get_new_chapter_property (string title, int order) { 38 | return """[General] 39 | title=""" + title + """ 40 | name=""" + title + """ 41 | order=""" + order.to_string () + """ 42 | bin=false 43 | """; 44 | } 45 | 46 | public static string get_new_scene_property (string title, int order) { 47 | return """[General] 48 | title=""" + title + """ 49 | name=""" + title + """ 50 | order=""" + order.to_string () + """ 51 | bin=false 52 | """; 53 | } 54 | 55 | public static string get_new_note_property (string title, int order) { 56 | return """[General] 57 | title=""" + title + """ 58 | name=""" + title + """ 59 | order=""" + order.to_string () + """ 60 | bin=false 61 | """; 62 | } 63 | 64 | public static void set_custom_css_style (Gdk.Screen screen) { 65 | Granite.Widgets.Utils.set_theming_for_screen ( 66 | screen, 67 | """ 68 | .chapter-drag-begin { 69 | border-top: 1px solid #666666; 70 | } 71 | """, 72 | Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION 73 | ); 74 | } 75 | } -------------------------------------------------------------------------------- /src/Widgets/Bin.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Widgets { 29 | public class Bin : Gtk.Grid { 30 | Gtk.ListBox chapters; 31 | Gtk.ListBox scenes; 32 | Gtk.ListBox notes; 33 | Gtk.SourceView text; 34 | Gtk.Entry title; 35 | 36 | public Bin () { 37 | build_ui (); 38 | } 39 | 40 | private void build_ui () { 41 | this.expand = true; 42 | this.height_request = 320; 43 | this.width_request = 640; 44 | 45 | var chapter = build_chapter_content (); 46 | 47 | var scene = build_scene_content (); 48 | 49 | var note = build_note_content (); 50 | 51 | title = new Gtk.Entry (); 52 | title.get_style_context ().add_class ("h3"); 53 | title.xalign = 0.5f; 54 | title.has_frame = false; 55 | title.editable = false; 56 | 57 | var scroll = new Gtk.ScrolledWindow (null, null); 58 | text = new Gtk.SourceView (); 59 | text.expand = true; 60 | text.editable = false; 61 | 62 | scroll.add (text); 63 | 64 | var grid = new Gtk.Grid (); 65 | grid.attach (scene, 0, 0); 66 | grid.attach (new Gtk.Separator (Gtk.Orientation.HORIZONTAL), 0, 1); 67 | grid.attach (note, 0, 2); 68 | grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0, 1, 3); 69 | grid.attach (scroll, 2, 0, 3, 3); 70 | 71 | this.attach (chapter, 0, 0, 1, 4); 72 | this.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0, 1, 4); 73 | this.attach (title, 2, 0, 3, 1); 74 | this.attach (grid, 2, 1, 3, 1); 75 | 76 | this.show_all (); 77 | } 78 | 79 | private Gtk.Grid build_chapter_content () { 80 | var grid = new Gtk.Grid (); 81 | var scroll = new Gtk.ScrolledWindow (null, null); 82 | scroll.expand = true; 83 | 84 | chapters = new Gtk.ListBox (); 85 | chapters.set_filter_func (chapters_filter_func); 86 | chapters.set_sort_func (Utils.chapters_sort_func); 87 | scroll.add (chapters); 88 | chapters.selected_rows_changed.connect ( 89 | () => { 90 | reset_children (); 91 | if (chapters.get_selected_row () is Chapter) { 92 | var chapter = (chapters.get_selected_row () as Chapter).chapter; 93 | foreach (var note in chapter.notes) { 94 | var item = new Note (note); 95 | note.bin_location_changed.connect (refilter_bin_notes_content); 96 | notes.add (item); 97 | } 98 | 99 | foreach (var scene in chapter.scenes) { 100 | var item = new Scene (scene, Enums.ItemStyle.BIN); 101 | scene.bin_location_changed.connect (refilter_bin_scenes_content); 102 | scenes.add (item); 103 | } 104 | 105 | title.text = chapter.title; 106 | } 107 | }); 108 | 109 | grid.add (scroll); 110 | return grid; 111 | } 112 | 113 | private Gtk.Grid build_scene_content () { 114 | var grid = new Gtk.Grid (); 115 | var scroll = new Gtk.ScrolledWindow (null, null); 116 | scroll.expand = true; 117 | 118 | scenes = new Gtk.ListBox (); 119 | scenes.set_filter_func (scenes_filter_func); 120 | scenes.set_sort_func (Utils.scenes_sort_func); 121 | scenes.selected_rows_changed.connect ( 122 | () => { 123 | if (scenes.get_selected_row () is Scene) { 124 | notes.unselect_all (); 125 | text.buffer.text = (scenes.get_selected_row () as Scene).scene.get_content (); 126 | } 127 | }); 128 | scroll.add (scenes); 129 | 130 | grid.add (scroll); 131 | 132 | return grid; 133 | } 134 | 135 | private Gtk.Grid build_note_content () { 136 | var grid = new Gtk.Grid (); 137 | var scroll = new Gtk.ScrolledWindow (null, null); 138 | scroll.expand = true; 139 | 140 | notes = new Gtk.ListBox (); 141 | notes.set_filter_func (notes_filter_func); 142 | notes.set_sort_func (Utils.notes_sort_func); 143 | notes.selected_rows_changed.connect ( 144 | () => { 145 | if (notes.get_selected_row () is Note) { 146 | scenes.unselect_all (); 147 | text.buffer.text = (notes.get_selected_row () as Note).note.get_content (); 148 | } 149 | }); 150 | 151 | scroll.add (notes); 152 | 153 | grid.add (scroll); 154 | return grid; 155 | } 156 | 157 | public void show_content (Objects.Project project) { 158 | reset (); 159 | 160 | foreach (var chapter in project.chapters) { 161 | var item = new Chapter (chapter, Enums.ItemStyle.BIN); 162 | chapter.bin_location_changed.connect (refilter_bin_chapters_content); 163 | chapters.add (item); 164 | } 165 | } 166 | 167 | public void reset () { 168 | foreach (var child in chapters.get_children ()) { 169 | (child as Chapter).chapter.bin_location_changed.disconnect (refilter_bin_chapters_content); 170 | child.destroy (); 171 | } 172 | } 173 | 174 | public void reset_children () { 175 | foreach (var child in scenes.get_children ()) { 176 | (child as Scene).scene.bin_location_changed.disconnect (refilter_bin_scenes_content); 177 | child.destroy (); 178 | } 179 | foreach (var child in notes.get_children ()) { 180 | (child as Note).note.bin_location_changed.disconnect (refilter_bin_notes_content); 181 | child.destroy (); 182 | } 183 | text.buffer.text = ""; 184 | } 185 | 186 | private void refilter_bin_scenes_content () { 187 | scenes.invalidate_filter (); 188 | chapters.invalidate_filter (); 189 | text.buffer.text = ""; 190 | } 191 | 192 | private void refilter_bin_notes_content () { 193 | notes.invalidate_filter (); 194 | chapters.invalidate_filter (); 195 | text.buffer.text = ""; 196 | } 197 | 198 | private void refilter_bin_chapters_content () { 199 | chapters.invalidate_filter (); 200 | notes.invalidate_filter (); 201 | scenes.invalidate_filter (); 202 | text.buffer.text = ""; 203 | title.text = ""; 204 | } 205 | 206 | private bool scenes_filter_func (Gtk.ListBoxRow child) { 207 | var item = (Widgets.Scene)child; 208 | return item.scene.bin || item.scene.parent.bin; 209 | } 210 | 211 | private bool notes_filter_func (Gtk.ListBoxRow child) { 212 | var item = (Widgets.Note)child; 213 | return item.note.bin || item.note.parent.bin; 214 | } 215 | 216 | private bool chapters_filter_func (Gtk.ListBoxRow child) { 217 | var item = (Widgets.Chapter)child; 218 | return item.chapter.bin || item.chapter.has_bin_children (); 219 | } 220 | } 221 | } -------------------------------------------------------------------------------- /src/Widgets/Chapter.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Widgets { 29 | public class Chapter : Gtk.ListBoxRow { 30 | public signal void reorder_request (int from, int to); 31 | 32 | public Objects.Chapter chapter { get; private set; } 33 | 34 | public string title { get { return chapter.title; } } 35 | public int order { get { return chapter.order; } } 36 | 37 | Enums.ItemStyle item_style; 38 | 39 | Gtk.Label label; 40 | Gtk.Button action_button; 41 | Gtk.Image redo_img; 42 | Gtk.Image trash_img; 43 | 44 | const Gtk.TargetEntry[] targetentries = {{ "STRING", 0, 0 }}; 45 | 46 | public Chapter (Objects.Chapter chapter, Enums.ItemStyle item_style = Enums.ItemStyle.DEFAULT) { 47 | 48 | this.item_style = item_style; 49 | 50 | this.chapter = chapter; 51 | this.chapter.bin_location_changed.connect ( 52 | (bin) => { 53 | label.opacity = 1; 54 | if (bin) { 55 | action_button.set_image (redo_img); 56 | } else { 57 | if (item_style == Enums.ItemStyle.BIN) { 58 | label.opacity = 0.5; 59 | action_button.hide (); 60 | } else { 61 | action_button.set_image (trash_img); 62 | } 63 | } 64 | }); 65 | build_ui (); 66 | } 67 | 68 | private void build_ui () { 69 | label = new Gtk.Label (chapter.name); 70 | label.expand = true; 71 | label.xalign = 0; 72 | label.opacity = 1; 73 | label.margin = 12; 74 | 75 | var event_box = new Gtk.EventBox (); 76 | 77 | // DRAG DROP 78 | Gtk.drag_source_set (event_box, Gdk.ModifierType.BUTTON1_MASK, targetentries, Gdk.DragAction.MOVE); 79 | event_box.drag_data_get.connect (on_drag_data_get); 80 | 81 | Gtk.drag_dest_set (event_box, Gtk.DestDefaults.ALL, targetentries, Gdk.DragAction.MOVE); 82 | event_box.drag_leave.connect ( 83 | (context, time) => { 84 | label.margin_top = 12; 85 | this.get_style_context ().remove_class ("chapter-drag-begin"); 86 | }); 87 | event_box.drag_motion.connect ( 88 | (context, x, y, time) => { 89 | label.margin_top = 11; 90 | Gtk.drag_unhighlight (event_box); 91 | this.get_style_context ().add_class ("chapter-drag-begin"); 92 | return false; 93 | }); 94 | event_box.drag_data_received.connect ( 95 | (drag_context, x, y, data, info, time) => { 96 | on_drag_data_received (data.get_text ()); 97 | }); 98 | 99 | 100 | var content = new Gtk.Grid (); 101 | 102 | redo_img = new Gtk.Image.from_icon_name ("edit-redo-symbolic", Gtk.IconSize.BUTTON); 103 | redo_img.tooltip_text = _("Restore from Bin"); 104 | trash_img = new Gtk.Image.from_icon_name ("user-trash-symbolic", Gtk.IconSize.BUTTON); 105 | trash_img.tooltip_text = _("Move into Bin"); 106 | 107 | action_button = new Gtk.Button (); 108 | action_button.valign = Gtk.Align.CENTER; 109 | 110 | if (chapter.bin) { 111 | action_button.set_image (redo_img); 112 | } else { 113 | action_button.set_image (trash_img); 114 | if (item_style == Enums.ItemStyle.BIN) { 115 | label.opacity = 0.5; 116 | } 117 | } 118 | 119 | action_button.get_style_context ().add_class ("flat"); 120 | action_button.can_focus = false; 121 | action_button.halign = Gtk.Align.END; 122 | action_button.opacity = 0; 123 | 124 | action_button.clicked.connect ( 125 | () => { 126 | if (chapter.bin) { 127 | chapter.restore_from_bin (); 128 | } else { 129 | chapter.move_into_bin (); 130 | } 131 | }); 132 | action_button.enter_notify_event.connect ( 133 | (event) => { 134 | action_button.opacity = 1; 135 | return false; 136 | }); 137 | 138 | event_box.enter_notify_event.connect ( 139 | (event) => { 140 | action_button.opacity = 0.5; 141 | return false; 142 | }); 143 | event_box.leave_notify_event.connect ( 144 | (event) => { 145 | action_button.opacity = 0; 146 | return false; 147 | }); 148 | 149 | content.attach (action_button, 1, 0); 150 | content.attach (label, 0, 0); 151 | 152 | event_box.add (content); 153 | 154 | this.add (event_box); 155 | this.show_all (); 156 | 157 | if (!chapter.bin && item_style == Enums.ItemStyle.BIN) { 158 | action_button.hide (); 159 | } 160 | } 161 | 162 | private void on_drag_data_get (Gdk.DragContext context, Gtk.SelectionData selection_data, uint target_type, uint time) { 163 | this.activate (); 164 | selection_data.set_text ("Chapter:%d".printf (chapter.order), -1); 165 | } 166 | 167 | private void on_drag_data_received (string received) { 168 | Regex reg_chapter_order; 169 | try { 170 | reg_chapter_order = new Regex ("(?<=Chapter:)\\d*"); 171 | } catch (Error err) { 172 | return; 173 | } 174 | 175 | int source_chapter_order = chapter.order; 176 | 177 | MatchInfo match; 178 | 179 | if (reg_chapter_order.match (received, 0, out match)) { 180 | source_chapter_order = int.parse (match.fetch (0)); 181 | } 182 | 183 | if (source_chapter_order != chapter.order) { 184 | reorder_request (source_chapter_order, chapter.order); 185 | } 186 | } 187 | } 188 | } -------------------------------------------------------------------------------- /src/Widgets/ChapterList.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Widgets { 29 | public class ChapterList : Gtk.Grid { 30 | public signal void chapter_selected (Objects.Chapter chapter); 31 | 32 | Gtk.ListBox chapters; 33 | 34 | public Objects.Project ? current_project { get; private set; default = null; } 35 | 36 | public ChapterList () { 37 | build_ui (); 38 | } 39 | 40 | private void build_ui () { 41 | this.width_request = 200; 42 | chapters = new Gtk.ListBox (); 43 | chapters.set_sort_func (Utils.chapters_sort_func); 44 | chapters.set_filter_func (chapters_filter_func); 45 | chapters.selected_rows_changed.connect ( 46 | () => { 47 | if (chapters.get_selected_row () is Widgets.Chapter) { 48 | chapter_selected ((chapters.get_selected_row () as Widgets.Chapter).chapter); 49 | } 50 | }); 51 | 52 | var scroll = new Gtk.ScrolledWindow (null, null); 53 | scroll.expand = true; 54 | scroll.add (chapters); 55 | 56 | var action_toolbar = new Gtk.ActionBar (); 57 | action_toolbar.get_style_context ().add_class (Gtk.STYLE_CLASS_INLINE_TOOLBAR); 58 | var add_button = new Gtk.Button.from_icon_name ("document-new-symbolic"); 59 | add_button.tooltip_text = _ ("Add a Chapter"); 60 | add_button.clicked.connect ( 61 | () => { 62 | if (current_project != null) { 63 | current_project.generate_new_chapter (); 64 | } 65 | }); 66 | action_toolbar.pack_start (add_button); 67 | 68 | this.attach (scroll, 0, 0); 69 | this.attach (action_toolbar, 0, 1); 70 | } 71 | 72 | public void show_chapters (Objects.Project project) { 73 | if (current_project == project) { 74 | return; 75 | } 76 | 77 | if (current_project != null) { 78 | current_project.chapter_created.disconnect (add_chapter); 79 | } 80 | 81 | reset (); 82 | 83 | current_project = project; 84 | foreach (var chapter in project.chapters) { 85 | var item = new Chapter (chapter); 86 | item.reorder_request.connect (reorder); 87 | chapter.bin_location_changed.connect ( 88 | (bin) => { 89 | if (bin) { 90 | chapters.unselect_all (); 91 | } 92 | chapters.invalidate_filter (); 93 | if (!bin) { 94 | item.activate (); 95 | } 96 | }); 97 | chapters.add (item); 98 | } 99 | 100 | foreach (var item in chapters.get_children ()) { 101 | if (!(item as Chapter).chapter.bin) { 102 | item.activate (); 103 | break; 104 | } 105 | } 106 | current_project.chapter_created.connect (add_chapter); 107 | } 108 | 109 | public void add_chapter (Objects.Chapter chapter) { 110 | var item = new Chapter (chapter); 111 | item.reorder_request.connect (reorder); 112 | chapters.add (item); 113 | chapter.bin_location_changed.connect ( 114 | (bin) => { 115 | if (bin) { 116 | chapters.unselect_all (); 117 | } 118 | chapters.invalidate_filter (); 119 | if (!bin) { 120 | item.activate (); 121 | } 122 | }); 123 | item.activate (); 124 | } 125 | 126 | public void reset () { 127 | foreach (var child in chapters.get_children ()) { 128 | child.destroy (); 129 | } 130 | } 131 | 132 | public void select_chapter (string chapter_name) { 133 | foreach (var child in chapters.get_children ()) { 134 | if ((child as Chapter).chapter.name == chapter_name) { 135 | child.activate (); 136 | break; 137 | } 138 | } 139 | } 140 | 141 | public void unselect_all () { 142 | chapters.unselect_all (); 143 | } 144 | 145 | private void reorder (int from, int to) { 146 | if (current_project != null) { 147 | current_project.reorder_chapters (from, to); 148 | chapters.invalidate_sort (); 149 | } 150 | } 151 | 152 | private bool chapters_filter_func (Gtk.ListBoxRow child) { 153 | var item = (Chapter)child; 154 | return !item.chapter.bin; 155 | } 156 | } 157 | } -------------------------------------------------------------------------------- /src/Widgets/Note.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Widgets { 29 | public class Note : Gtk.ListBoxRow { 30 | public Objects.Note note { get; private set; } 31 | 32 | public string title { get { return note.title; } } 33 | 34 | Gtk.Label label; 35 | Gtk.Button action_button; 36 | Gtk.Image redo_img; 37 | Gtk.Image trash_img; 38 | 39 | public Note (Objects.Note note) { 40 | this.note = note; 41 | this.note.title_saved.connect ( 42 | (new_title) => { 43 | label.label = new_title; 44 | (this.parent as Gtk.ListBox).invalidate_sort (); 45 | }); 46 | this.note.bin_location_changed.connect ( 47 | (bin) => { 48 | if (bin) { 49 | action_button.set_image (redo_img); 50 | } else { 51 | action_button.set_image (trash_img); 52 | } 53 | }); 54 | this.note.parent.bin_location_changed.connect ( 55 | (bin) => { 56 | action_button.visible = bin; 57 | }); 58 | build_ui (); 59 | } 60 | 61 | private void build_ui () { 62 | label = new Gtk.Label (note.title); 63 | label.xalign = 0; 64 | label.expand = true; 65 | label.margin = 6; 66 | 67 | var event_box = new Gtk.EventBox (); 68 | var content = new Gtk.Grid (); 69 | 70 | redo_img = new Gtk.Image.from_icon_name ("edit-redo-symbolic", Gtk.IconSize.BUTTON); 71 | redo_img.tooltip_text = _("Restore from Bin"); 72 | trash_img = new Gtk.Image.from_icon_name ("user-trash-symbolic", Gtk.IconSize.BUTTON); 73 | trash_img.tooltip_text = _("Move into Bin"); 74 | 75 | action_button = new Gtk.Button (); 76 | action_button.valign = Gtk.Align.CENTER; 77 | 78 | if (note.bin) { 79 | action_button.set_image (redo_img); 80 | } else { 81 | action_button.set_image (trash_img); 82 | } 83 | action_button.get_style_context ().add_class ("flat"); 84 | action_button.can_focus = false; 85 | action_button.halign = Gtk.Align.END; 86 | action_button.opacity = 0; 87 | 88 | action_button.clicked.connect ( 89 | () => { 90 | if (note.bin) { 91 | note.restore_from_bin (); 92 | } else { 93 | note.move_into_bin (); 94 | } 95 | }); 96 | action_button.enter_notify_event.connect ( 97 | (event) => { 98 | action_button.opacity = 1; 99 | return false; 100 | }); 101 | 102 | event_box.enter_notify_event.connect ( 103 | (event) => { 104 | action_button.opacity = 0.5; 105 | return false; 106 | }); 107 | event_box.leave_notify_event.connect ( 108 | (event) => { 109 | action_button.opacity = 0; 110 | return false; 111 | }); 112 | content.attach (action_button, 1, 0); 113 | 114 | content.attach (label, 0, 0); 115 | event_box.add (content); 116 | 117 | this.add (event_box); 118 | this.show_all (); 119 | 120 | if (note.parent.bin) { 121 | action_button.hide (); 122 | } 123 | } 124 | } 125 | } -------------------------------------------------------------------------------- /src/Widgets/Notes.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Widgets { 29 | public class Notes : Gtk.Grid { 30 | public Objects.Chapter current_chapter { get; private set; default = null; } 31 | public Objects.Note current_note { get; private set; default = null; } 32 | 33 | Gtk.ListBox notes; 34 | Gtk.Entry title; 35 | Gtk.SourceView text; 36 | 37 | public Notes () { 38 | build_ui (); 39 | } 40 | 41 | private void build_ui () { 42 | this.width_request = 380; 43 | this.height_request = 320; 44 | 45 | notes = new Gtk.ListBox (); 46 | notes.set_sort_func (Utils.notes_sort_func); 47 | notes.set_filter_func (notes_filter_func); 48 | notes.selected_rows_changed.connect ( 49 | () => { 50 | save_note (); 51 | if (notes.get_selected_row () is Widgets.Note) { 52 | open_note ((notes.get_selected_row () as Widgets.Note).note); 53 | } 54 | }); 55 | var scroll = new Gtk.ScrolledWindow (null, null); 56 | scroll.width_request = 120; 57 | scroll.vexpand = true; 58 | scroll.add (notes); 59 | 60 | title = new Gtk.Entry (); 61 | title.xalign = 0.5f; 62 | title.has_frame = false; 63 | title.get_style_context ().add_class ("h3"); 64 | title.focus_out_event.connect ( 65 | () => { 66 | save_title (); 67 | return false; 68 | }); 69 | 70 | text = new Gtk.SourceView (); 71 | text.expand = true; 72 | text.top_margin = text.bottom_margin = text.left_margin = text.right_margin = 6; 73 | 74 | var note = new Gtk.Grid (); 75 | note.attach (title, 0, 0); 76 | note.attach (text, 0, 1); 77 | 78 | var action_toolbar = new Gtk.ActionBar (); 79 | var add_button = new Gtk.Button.from_icon_name ("list-add-symbolic"); 80 | add_button.tooltip_text = _ ("Add a Note"); 81 | add_button.clicked.connect ( 82 | () => { 83 | current_chapter.generate_new_note (); 84 | }); 85 | action_toolbar.pack_start (add_button); 86 | 87 | this.attach (scroll, 0, 0); 88 | this.attach (action_toolbar, 0, 1); 89 | this.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0, 1, 2); 90 | this.attach (note, 2, 0, 1, 2); 91 | 92 | this.show_all (); 93 | } 94 | 95 | public void show_notes (Objects.Chapter chapter) { 96 | if (current_chapter == chapter) { 97 | return; 98 | } 99 | 100 | if (current_chapter != null) { 101 | current_chapter.note_created.disconnect (add_note); 102 | } 103 | 104 | reset (); 105 | foreach (var note in chapter.notes) { 106 | var item = new Widgets.Note (note); 107 | note.bin_location_changed.connect (refilter_note); 108 | notes.add (item); 109 | } 110 | refilter_note (); 111 | 112 | current_chapter = chapter; 113 | 114 | current_chapter.note_created.connect (add_note); 115 | } 116 | 117 | public void reset () { 118 | current_chapter = null; 119 | current_note = null; 120 | foreach (var child in notes.get_children ()) { 121 | child.destroy (); 122 | } 123 | } 124 | 125 | private void add_note (Objects.Note note) { 126 | var item = new Widgets.Note (note); 127 | notes.add (item); 128 | note.bin_location_changed.connect (refilter_note); 129 | item.activate (); 130 | title.grab_focus (); 131 | } 132 | 133 | private void open_note (Objects.Note note) { 134 | if (current_note == note) { 135 | return; 136 | } 137 | 138 | if (current_note != null) { 139 | current_note.title_saved.disconnect (set_new_title); 140 | } 141 | 142 | current_note = note; 143 | title.text = note.title; 144 | text.buffer.text = note.get_content (); 145 | current_note.title_saved.connect (set_new_title); 146 | } 147 | 148 | public void save_note () { 149 | if (current_note != null) { 150 | current_note.save_content (text.buffer.text); 151 | save_title (); 152 | } 153 | } 154 | 155 | private void save_title () { 156 | if (current_note != null) { 157 | var note_title = title.text.strip (); 158 | if (current_note.title != note_title) { 159 | current_note.set_new_title (note_title); 160 | } 161 | } 162 | } 163 | 164 | private void refilter_note () { 165 | save_note (); 166 | notes.invalidate_filter (); 167 | current_note = null; 168 | title.text = ""; 169 | text.buffer.text = ""; 170 | } 171 | 172 | private void set_new_title (string new_title) { 173 | title.text = new_title; 174 | } 175 | 176 | private bool notes_filter_func (Gtk.ListBoxRow child) { 177 | var item = (Widgets.Note)child; 178 | return !item.note.bin; 179 | } 180 | } 181 | } -------------------------------------------------------------------------------- /src/Widgets/Scene.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Widgets { 29 | public class Scene : Gtk.ListBoxRow { 30 | public signal void reorder_request (int from, int to); 31 | 32 | public Objects.Scene scene { get; private set; } 33 | 34 | public new string name { get { return scene.name; } } 35 | public int order { get { return scene.order; } } 36 | 37 | Enums.ItemStyle item_style; 38 | 39 | Gtk.Label label; 40 | Gtk.Button action_button; 41 | Gtk.Image redo_img; 42 | Gtk.Image trash_img; 43 | 44 | const Gtk.TargetEntry[] targetentries = {{ "STRING", 0, 0 }}; 45 | 46 | public Scene (Objects.Scene scene, Enums.ItemStyle item_style = Enums.ItemStyle.DEFAULT) { 47 | this.scene = scene; 48 | this.scene.bin_location_changed.connect ( 49 | (bin) => { 50 | if (bin) { 51 | action_button.set_image (redo_img); 52 | } else { 53 | action_button.set_image (trash_img); 54 | } 55 | }); 56 | this.scene.parent.bin_location_changed.connect ( 57 | (bin) => { 58 | action_button.visible = bin; 59 | }); 60 | this.item_style = item_style; 61 | 62 | build_ui (); 63 | } 64 | 65 | private void build_ui () { 66 | label = new Gtk.Label (scene.name); 67 | label.expand = true; 68 | label.xalign = 0; 69 | label.margin = 12; 70 | 71 | var event_box = new Gtk.EventBox (); 72 | 73 | // DRAG DROP 74 | Gtk.drag_source_set (event_box, Gdk.ModifierType.BUTTON1_MASK, targetentries, Gdk.DragAction.MOVE); 75 | event_box.drag_data_get.connect (on_drag_data_get); 76 | 77 | Gtk.drag_dest_set (event_box, Gtk.DestDefaults.ALL, targetentries, Gdk.DragAction.MOVE); 78 | event_box.drag_leave.connect ( 79 | (context, time) => { 80 | label.margin_top = 12; 81 | this.get_style_context ().remove_class ("chapter-drag-begin"); 82 | }); 83 | event_box.drag_motion.connect ( 84 | (context, x, y, time) => { 85 | label.margin_top = 11; 86 | Gtk.drag_unhighlight (event_box); 87 | this.get_style_context ().add_class ("chapter-drag-begin"); 88 | return false; 89 | }); 90 | event_box.drag_data_received.connect ( 91 | (drag_context, x, y, data, info, time) => { 92 | on_drag_data_received (data.get_text ()); 93 | }); 94 | 95 | var content = new Gtk.Grid (); 96 | 97 | redo_img = new Gtk.Image.from_icon_name ("edit-redo-symbolic", Gtk.IconSize.BUTTON); 98 | redo_img.tooltip_text = _ ("Restore from Bin"); 99 | trash_img = new Gtk.Image.from_icon_name ("user-trash-symbolic", Gtk.IconSize.BUTTON); 100 | trash_img.tooltip_text = _ ("Move into Bin"); 101 | 102 | action_button = new Gtk.Button (); 103 | action_button.valign = Gtk.Align.CENTER; 104 | 105 | if (scene.bin) { 106 | action_button.set_image (redo_img); 107 | } else { 108 | action_button.set_image (trash_img); 109 | } 110 | action_button.get_style_context ().add_class ("flat"); 111 | action_button.can_focus = false; 112 | action_button.halign = Gtk.Align.END; 113 | action_button.opacity = 0; 114 | 115 | action_button.clicked.connect ( 116 | () => { 117 | if (scene.bin) { 118 | scene.restore_from_bin (); 119 | } else { 120 | scene.move_into_bin (); 121 | } 122 | }); 123 | action_button.enter_notify_event.connect ( 124 | (event) => { 125 | action_button.opacity = 1; 126 | return false; 127 | }); 128 | 129 | event_box.enter_notify_event.connect ( 130 | (event) => { 131 | action_button.opacity = 0.5; 132 | return false; 133 | }); 134 | event_box.leave_notify_event.connect ( 135 | (event) => { 136 | action_button.opacity = 0; 137 | return false; 138 | }); 139 | content.attach (action_button, 1, 0); 140 | 141 | if (item_style == Enums.ItemStyle.BIN) { 142 | label.margin = 6; 143 | } 144 | 145 | content.margin_right = 0; 146 | content.attach (label, 0, 0); 147 | event_box.add (content); 148 | 149 | this.add (event_box); 150 | this.show_all (); 151 | 152 | if (scene.parent.bin) { 153 | action_button.hide (); 154 | } 155 | } 156 | 157 | private void on_drag_data_get (Gdk.DragContext context, Gtk.SelectionData selection_data, uint target_type, uint time) { 158 | this.activate (); 159 | selection_data.set_text ("Scene:%d".printf (scene.order), -1); 160 | } 161 | 162 | private void on_drag_data_received (string received) { 163 | Regex reg_scene_order; 164 | try { 165 | reg_scene_order = new Regex ("(?<=Scene:)\\d*"); 166 | } catch (Error err) { 167 | return; 168 | } 169 | 170 | int source_scene_order = scene.order; 171 | 172 | MatchInfo match; 173 | 174 | if (reg_scene_order.match (received, 0, out match)) { 175 | source_scene_order = int.parse (match.fetch (0)); 176 | } 177 | 178 | if (source_scene_order != scene.order) { 179 | reorder_request (source_scene_order, scene.order); 180 | } 181 | } 182 | } 183 | } -------------------------------------------------------------------------------- /src/Widgets/SceneList.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Widgets { 29 | public class SceneList : Gtk.Grid { 30 | public signal void scene_selected (Objects.Scene scene); 31 | 32 | public Objects.Chapter ? current_chapter { get; private set; default = null; } 33 | 34 | Gtk.ListBox scenes; 35 | 36 | public SceneList () { 37 | build_ui (); 38 | } 39 | 40 | private void build_ui () { 41 | this.width_request = 150; 42 | this.expand = false; 43 | this.margin = 24; 44 | this.margin_left = 0; 45 | 46 | scenes = new Gtk.ListBox (); 47 | scenes.set_sort_func (Utils.scenes_sort_func); 48 | scenes.set_filter_func (scenes_filter_func); 49 | scenes.selected_rows_changed.connect ( 50 | () => { 51 | if (scenes.get_selected_row () is Widgets.Scene) { 52 | scene_selected ((scenes.get_selected_row () as Widgets.Scene).scene); 53 | } 54 | }); 55 | 56 | var scroll = new Gtk.ScrolledWindow (null, null); 57 | scroll.expand = true; 58 | scroll.add (scenes); 59 | 60 | var action_toolbar = new Gtk.ActionBar (); 61 | action_toolbar.get_style_context ().add_class (Gtk.STYLE_CLASS_INLINE_TOOLBAR); 62 | var add_button = new Gtk.Button.from_icon_name ("accessories-text-editor-symbolic"); 63 | add_button.tooltip_text = _ ("Add a Scene"); 64 | add_button.clicked.connect ( 65 | () => { 66 | if (current_chapter != null) { 67 | current_chapter.generate_new_scene (); 68 | } 69 | }); 70 | action_toolbar.pack_start (add_button); 71 | 72 | var frame = new Gtk.Frame (null); 73 | 74 | var grid = new Gtk.Grid (); 75 | grid.attach (scroll, 0, 0); 76 | grid.attach (action_toolbar, 0, 1); 77 | 78 | frame.add (grid); 79 | 80 | this.attach (frame, 0, 0); 81 | } 82 | 83 | public void show_scenes (Objects.Chapter chapter) { 84 | if (current_chapter == chapter) { 85 | return; 86 | } 87 | 88 | if (current_chapter != null) { 89 | current_chapter.scene_created.disconnect (add_scene); 90 | } 91 | 92 | reset (); 93 | 94 | current_chapter = chapter; 95 | foreach (var scene in chapter.scenes) { 96 | var item = new Scene (scene); 97 | item.reorder_request.connect (reorder); 98 | scene.bin_location_changed.connect ( 99 | () => { 100 | scenes.invalidate_filter (); 101 | }); 102 | scenes.add (item); 103 | } 104 | 105 | foreach (var item in scenes.get_children ()) { 106 | if (!(item as Scene).scene.bin) { 107 | item.activate (); 108 | break; 109 | } 110 | } 111 | 112 | current_chapter.scene_created.connect (add_scene); 113 | } 114 | 115 | public void reset () { 116 | current_chapter = null; 117 | foreach (var child in scenes.get_children ()) { 118 | (child as Scene).reorder_request.disconnect (reorder); 119 | child.destroy (); 120 | } 121 | } 122 | 123 | public void select_scene (string scene_name) { 124 | foreach (var child in scenes.get_children ()) { 125 | if ((child as Scene).scene.name == scene_name) { 126 | child.activate (); 127 | break; 128 | } 129 | } 130 | } 131 | 132 | public void add_scene (Objects.Scene scene) { 133 | var item = new Scene (scene); 134 | item.reorder_request.connect (reorder); 135 | scenes.add (item); 136 | scene.bin_location_changed.connect ( 137 | () => { 138 | scenes.invalidate_filter (); 139 | }); 140 | item.activate (); 141 | } 142 | 143 | public void unselect_all () { 144 | scenes.unselect_all (); 145 | } 146 | 147 | private void reorder (int from, int to) { 148 | if (current_chapter != null) { 149 | current_chapter.reorder_scenes (from, to); 150 | scenes.invalidate_sort (); 151 | } 152 | } 153 | 154 | private bool scenes_filter_func (Gtk.ListBoxRow child) { 155 | var item = (Scene)child; 156 | return !item.scene.bin; 157 | } 158 | } 159 | } -------------------------------------------------------------------------------- /src/Widgets/Views/Welcome.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Widgets.Views { 29 | public class Welcome : Gtk.Grid { 30 | public signal void new_project_clicked (); 31 | public signal void open_project_clicked (); 32 | 33 | public Welcome () { 34 | build_ui (); 35 | } 36 | 37 | private void build_ui () { 38 | var welcome = new Granite.Widgets.Welcome (_ ("Title"), _ ("Subtitle.")); 39 | welcome.append ("document-new", _ ("Create a new Project"), _ ("Write your next best seller.")); 40 | welcome.append ("folder-documents", _ ("Open a Project"), _ ("Open an exists project from your library.")); 41 | welcome.activated.connect ( 42 | (index) => { 43 | switch (index) { 44 | case 0 : 45 | new_project_clicked (); 46 | break; 47 | case 1 : 48 | open_project_clicked (); 49 | break; 50 | } 51 | }); 52 | 53 | this.add (welcome); 54 | this.show_all (); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Widgets/Views/Writer.vala: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 2018-2018 Artem Anufrij 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 2 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public License 15 | * along with this program. If not, see . 16 | * 17 | * The Noise authors hereby grant permission for non-GPL compatible 18 | * GStreamer plugins to be used and distributed together with GStreamer 19 | * and Noise. This permission is above and beyond the permissions granted 20 | * by the GPL license by which Noise is covered. If you modify this code 21 | * you may extend this exception to your version of the code, but you are not 22 | * obligated to do so. If you do not wish to do so, delete this exception 23 | * statement from your version. 24 | * 25 | * Authored by: Artem Anufrij 26 | */ 27 | 28 | namespace TrimDown.Widgets.Views { 29 | public class Writer : Gtk.Grid { 30 | public Objects.Project ? current_project { get; private set; default = null; } 31 | public Objects.Chapter ? current_chapter { get; private set; default = null; } 32 | public Objects.Scene ? current_scene { get; private set; default = null; } 33 | 34 | Widgets.ChapterList chapters; 35 | Widgets.SceneList scenes; 36 | Gtk.Entry title; 37 | Gtk.SourceView body; 38 | 39 | public Writer (MainWindow mainwindow) { 40 | mainwindow.delete_event.connect ( 41 | () => { 42 | if (current_scene != null) { 43 | current_scene.save_content (body.buffer.text.strip ()); 44 | } 45 | return false; 46 | }); 47 | 48 | build_ui (); 49 | } 50 | 51 | private void build_ui () { 52 | var chapter_paned = new Gtk.Paned (Gtk.Orientation.HORIZONTAL); 53 | var writer = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); 54 | 55 | chapters = new Widgets.ChapterList (); 56 | chapters.chapter_selected.connect (show_chapter); 57 | 58 | chapter_paned.add1 (chapters); 59 | chapter_paned.add2 (writer); 60 | 61 | var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); 62 | box.get_style_context ().add_class ("card"); 63 | box.margin = 24; 64 | box.expand = true; 65 | 66 | title = new Gtk.Entry (); 67 | title.has_frame = false; 68 | title.get_style_context ().add_class ("h2"); 69 | title.xalign = 0.5f; 70 | title.changed.connect ( 71 | () => { 72 | if (current_chapter != null) { 73 | current_chapter.set_new_title (title.text); 74 | } 75 | }); 76 | box.pack_start (title, false, false); 77 | 78 | var body_scroll = new Gtk.ScrolledWindow (null, null); 79 | body_scroll.expand = true; 80 | 81 | body = new Gtk.SourceView (); 82 | body.wrap_mode = Gtk.WrapMode.WORD_CHAR; 83 | body.top_margin = body.bottom_margin = 24; 84 | body.left_margin = body.right_margin = 48; 85 | body_scroll.add (body); 86 | 87 | box.pack_end (body_scroll, true, true); 88 | 89 | scenes = new Widgets.SceneList (); 90 | scenes.scene_selected.connect (show_scene); 91 | 92 | writer.pack_start (box, true, true); 93 | writer.pack_start (scenes, false, false); 94 | 95 | this.add (chapter_paned); 96 | this.show_all (); 97 | } 98 | 99 | public void show_project (Objects.Project project) { 100 | if (current_project == project) { 101 | return; 102 | } 103 | if (current_project != null) { 104 | current_project.chapter_created.disconnect (chapter_created); 105 | } 106 | current_project = project; 107 | chapters.show_chapters (project); 108 | 109 | current_project.chapter_created.connect_after (chapter_created); 110 | } 111 | 112 | private void show_chapter (Objects.Chapter chapter) { 113 | if (current_chapter == chapter) { 114 | return; 115 | } 116 | 117 | if (current_chapter != null) { 118 | current_chapter.bin_location_changed.disconnect (clear); 119 | } 120 | 121 | current_chapter = chapter; 122 | scenes.show_scenes (chapter); 123 | title.text = chapter.title; 124 | current_chapter.bin_location_changed.connect (clear); 125 | } 126 | 127 | private void show_scene (Objects.Scene scene) { 128 | if (current_scene != null) { 129 | current_scene.save_content (body.buffer.text.strip ()); 130 | current_scene.bin_location_changed.disconnect (clear_scene); 131 | } 132 | 133 | current_scene = scene; 134 | body.buffer.text = scene.get_content (); 135 | 136 | current_scene.bin_location_changed.connect (clear_scene); 137 | } 138 | 139 | private void chapter_created (Objects.Chapter chapter) { 140 | title.grab_focus (); 141 | title.select_region (0, chapter.title.length); 142 | } 143 | 144 | private void clear () { 145 | if (current_chapter.bin) { 146 | current_chapter = null; 147 | current_scene = null; 148 | 149 | title.text = ""; 150 | body.buffer.text = ""; 151 | scenes.reset (); 152 | chapters.unselect_all (); 153 | } 154 | } 155 | 156 | private void clear_scene () { 157 | if (current_scene.bin) { 158 | current_scene.save_content (body.buffer.text.strip ()); 159 | current_scene = null; 160 | 161 | body.buffer.text = ""; 162 | scenes.unselect_all (); 163 | } 164 | } 165 | 166 | public void select_chapter (string chapter_name) { 167 | chapters.select_chapter (chapter_name); 168 | } 169 | 170 | public void select_scene (string scene_name) { 171 | scenes.select_scene (scene_name); 172 | } 173 | } 174 | } -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | sources = files( 2 | 'Application.vala', 3 | 'MainWindow.vala', 4 | 'Settings.vala', 5 | 'Objects/BaseObject.vala', 6 | 'Objects/Scene.vala', 7 | 'Objects/Note.vala', 8 | 'Objects/Chapter.vala', 9 | 'Objects/Project.vala', 10 | 'Widgets/Scene.vala', 11 | 'Widgets/SceneList.vala', 12 | 'Widgets/Note.vala', 13 | 'Widgets/Notes.vala', 14 | 'Widgets/Chapter.vala', 15 | 'Widgets/ChapterList.vala', 16 | 'Widgets/Bin.vala', 17 | 'Widgets/Views/Writer.vala', 18 | 'Widgets/Views/Welcome.vala', 19 | 'Dialogs/NewProject.vala', 20 | 'Dialogs/Preferences.vala', 21 | 'Services/ProjectManager.vala', 22 | 'Utils/Utils.vala', 23 | 'Utils/Enums.vala', 24 | 'Utils/Lists.vala' 25 | ) 26 | --------------------------------------------------------------------------------