diff --git a/LICENSE.md b/LICENSE.md index 7aab016207a3260e8fd41b70884fd24041090745..330581e58985051752ba469a1dacf62692fef9b1 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -641,7 +641,7 @@ the exclusion of warranty; and each file should have at least the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. + along with this program. If not, see <https://www.gnu.org/licenses/>. Also add information on how to contact you by electronic and paper mail. @@ -657,4 +657,4 @@ the specific requirements. You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow -the GNU AGPL, see <http://www.gnu.org/licenses/>. +the GNU AGPL, see <https://www.gnu.org/licenses/>. diff --git a/res/app.briar.gtk.appdata.xml.in b/data/app.briar.gtk.appdata.xml.in similarity index 80% rename from res/app.briar.gtk.appdata.xml.in rename to data/app.briar.gtk.appdata.xml.in index e76d950a81644e261131abd1569cfb9c8de79443..2ec7c3580ac47c521a9786b14e34d34353d1042a 100644 --- a/res/app.briar.gtk.appdata.xml.in +++ b/data/app.briar.gtk.appdata.xml.in @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <component type="desktop"> <id>app.briar.gtk.desktop</id> - <metadata_license>CC0-1.0</metadata_license> + <metadata_license>CC-BY-4.0</metadata_license> <project_license>GPL-3.0-or-later</project_license> <description> </description> diff --git a/res/app.briar.gtk.desktop.in b/data/app.briar.gtk.desktop.in similarity index 86% rename from res/app.briar.gtk.desktop.in rename to data/app.briar.gtk.desktop.in index f7db2e4471ff43becf9356730fa05efed1879fa3..114a89d47852270da599198180de10f1d7175fcc 100644 --- a/res/app.briar.gtk.desktop.in +++ b/data/app.briar.gtk.desktop.in @@ -1,5 +1,5 @@ [Desktop Entry] -Name=Briar GTK +Name=Briar Exec=briar-gtk Terminal=false Type=Application diff --git a/res/app.briar.gtk.gschema.xml b/data/app.briar.gtk.gschema.xml similarity index 100% rename from res/app.briar.gtk.gschema.xml rename to data/app.briar.gtk.gschema.xml diff --git a/res/meson.build b/data/meson.build similarity index 97% rename from res/meson.build rename to data/meson.build index a8cb8c3e1bb4eb5e830c8fc4ea2ccbc79c964c50..6d580f9ec84e65026085285da9726e90273b5eeb 100644 --- a/res/meson.build +++ b/data/meson.build @@ -44,8 +44,8 @@ pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), meson.proje gnome = import('gnome') gnome.compile_resources('briar-gtk', - 'ui/gresource.xml', + 'ui/app.briar.gtk.gresource.xml', gresource_bundle: true, install: true, install_dir: pkgdatadir, -) \ No newline at end of file +) diff --git a/data/ui/app.briar.gtk.gresource.xml b/data/ui/app.briar.gtk.gresource.xml new file mode 100644 index 0000000000000000000000000000000000000000..8cd9fae29a6e9965fd2e37e2d3ae6f37d5277ae2 --- /dev/null +++ b/data/ui/app.briar.gtk.gresource.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<gresources> + <gresource prefix="/app/briar/gtk"> + <file compressed="true">ui/application.css</file> + <file compressed="true" preprocess="xml-stripblanks">ui/login.ui</file> + <file compressed="true" preprocess="xml-stripblanks">ui/setup.ui</file> + </gresource> +</gresources> diff --git a/data/ui/application.css b/data/ui/application.css new file mode 100644 index 0000000000000000000000000000000000000000..6446ebfd427495a708d3740324ba3e383dfcbbe9 --- /dev/null +++ b/data/ui/application.css @@ -0,0 +1,3 @@ +.test { + color: red; +} diff --git a/data/ui/login.ui b/data/ui/login.ui new file mode 100644 index 0000000000000000000000000000000000000000..c7896cc6ed6225c3e486023906c90d080c2bed04 --- /dev/null +++ b/data/ui/login.ui @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <requires lib="gtk+" version="3.20"/> + <object class="GtkGrid" id="login"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="margin_left">18</property> + <property name="margin_right">18</property> + <property name="margin_top">18</property> + <property name="margin_bottom">18</property> + <child> + <object class="GtkGrid" id="password_grid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">6</property> + <property name="column_spacing">12</property> + <child> + <object class="GtkLabel" id="password_label"> + <property name="visible">True</property> + <property name="halign">center</property> + <property name="label" translatable="yes">Password</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="password_entry"> + <property name="visible">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="login_button"> + <property name="visible">True</property> + <property name="halign">center</property> + <property name="label" translatable="yes">Sign in</property> + <signal name="clicked" handler="on_login_pressed"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + </object> + </child> + </object> +</interface> + + diff --git a/data/ui/setup.ui b/data/ui/setup.ui new file mode 100644 index 0000000000000000000000000000000000000000..336fcfe4ed117e5d333ba511a225433278c0bcc6 --- /dev/null +++ b/data/ui/setup.ui @@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <requires lib="gtk+" version="3.20"/> + <object class="GtkGrid" id="setup"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="valign">center</property> + <property name="margin_left">18</property> + <property name="margin_right">18</property> + <property name="margin_top">18</property> + <property name="margin_bottom">18</property> + <child> + <object class="GtkGrid" id="username_grid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="row_spacing">6</property> + <property name="column_spacing">12</property> + <child> + <object class="GtkLabel" id="username_label"> + <property name="visible">True</property> + <property name="halign">center</property> + <property name="label" translatable="yes">Nickname</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="username_entry"> + <property name="visible">True</property> + <property name="placeholder_text" translatable="yes">Choose your nickname</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="username_next"> + <property name="visible">True</property> + <property name="halign">center</property> + <property name="label" translatable="yes">Next</property> + <signal name="clicked" handler="on_username_button_clicked"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + </object> + </child> + <child> + <object class="GtkGrid" id="password_grid"> + <property name="visible">False</property> + <property name="can_focus">False</property> + <property name="row_spacing">6</property> + <property name="column_spacing">12</property> + <child> + <object class="GtkLabel" id="password_label"> + <property name="visible">True</property> + <property name="halign">center</property> + <property name="label" translatable="yes">Password</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="password_entry"> + <property name="visible">True</property> + <property name="placeholder_text" translatable="yes">Choose your password</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="password_confirm_entry"> + <property name="visible">True</property> + <property name="placeholder_text" translatable="yes">Confirm your password</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkButton" id="password_next"> + <property name="visible">True</property> + <property name="halign">center</property> + <property name="label" translatable="yes">Next</property> + <signal name="clicked" handler="on_password_button_clicked"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + </packing> + </child> + </object> + </child> + </object> +</interface> + + diff --git a/meson.build b/meson.build index 63ef097ca63326ba094d827ac6c2f9cb7f255a31..32d5132b448361ce36c3d18bd4ba944b90c72b31 100644 --- a/meson.build +++ b/meson.build @@ -6,8 +6,8 @@ project( i18n = import('i18n') -subdir('res') +subdir('data') subdir('src') subdir('po') -meson.add_install_script('build-aux/meson/postinstall.py') \ No newline at end of file +meson.add_install_script('src/meson_post_install.py') diff --git a/po/LINGUAS b/po/LINGUAS index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..173f97890ea02c007bd74eb217cd31447f671450 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -0,0 +1,2 @@ +de +es diff --git a/po/briar-gtk.pot b/po/briar-gtk.pot new file mode 100644 index 0000000000000000000000000000000000000000..387553498505aa52a00a5bba609dd3c21b619136 --- /dev/null +++ b/po/briar-gtk.pot @@ -0,0 +1,46 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-03-24 23:15+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../data/ui/login.ui:23 ../data/ui/setup.ui:64 +msgid "Password" +msgstr "" + +#: ../data/ui/login.ui:43 +msgid "Sign in" +msgstr "" + +#: ../data/ui/setup.ui:23 +msgid "Nickname" +msgstr "" + +#: ../data/ui/setup.ui:33 +msgid "Choose your nickname" +msgstr "" + +#: ../data/ui/setup.ui:44 ../data/ui/setup.ui:95 +msgid "Next" +msgstr "" + +#: ../data/ui/setup.ui:74 +msgid "Choose your password" +msgstr "" + +#: ../data/ui/setup.ui:84 +msgid "Confirm your password" +msgstr "" diff --git a/po/de.po b/po/de.po new file mode 100644 index 0000000000000000000000000000000000000000..d520b1760030115619e7246ba3e0049413947c93 --- /dev/null +++ b/po/de.po @@ -0,0 +1,27 @@ +#: ../data/ui/login.ui:23 ../data/ui/setup.ui:64 +msgid "Password" +msgstr "Passwort" + +#: ../data/ui/login.ui:43 +msgid "Sign in" +msgstr "" + +#: ../data/ui/setup.ui:23 +msgid "Nickname" +msgstr "Nutzername" + +#: ../data/ui/setup.ui:33 +msgid "Choose your nickname" +msgstr "" + +#: ../data/ui/setup.ui:44 ../data/ui/setup.ui:95 +msgid "Next" +msgstr "" + +#: ../data/ui/setup.ui:74 +msgid "Choose your password" +msgstr "" + +#: ../data/ui/setup.ui:84 +msgid "Confirm your password" +msgstr "" diff --git a/po/es.po b/po/es.po new file mode 100644 index 0000000000000000000000000000000000000000..b5f69b2135861ceba6c8d0c3b539e138078259b2 --- /dev/null +++ b/po/es.po @@ -0,0 +1,27 @@ +#: ../data/ui/login.ui:23 ../data/ui/setup.ui:64 +msgid "Password" +msgstr "" + +#: ../data/ui/login.ui:43 +msgid "Sign in" +msgstr "" + +#: ../data/ui/setup.ui:23 +msgid "Nickname" +msgstr "" + +#: ../data/ui/setup.ui:33 +msgid "Choose your nickname" +msgstr "" + +#: ../data/ui/setup.ui:44 ../data/ui/setup.ui:95 +msgid "Next" +msgstr "Seguir" + +#: ../data/ui/setup.ui:74 +msgid "Choose your password" +msgstr "" + +#: ../data/ui/setup.ui:84 +msgid "Confirm your password" +msgstr "" diff --git a/po/meson.build b/po/meson.build index f7a303ad72409efd40bdb5cd08d673dc4ff46762..14702a5e07eeac51b806c0da62c37604f5d6dd41 100644 --- a/po/meson.build +++ b/po/meson.build @@ -1 +1 @@ -i18n.gettext('briar-gtk', preset: 'glib') \ No newline at end of file +i18n.gettext('briar-gtk', preset: 'glib') diff --git a/res/ui/gresource.xml b/res/ui/gresource.xml deleted file mode 100644 index 3e2b68907e2f1c08c951d16c704dc6c2333ba422..0000000000000000000000000000000000000000 --- a/res/ui/gresource.xml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<gresources> - <gresource prefix="/app/briar/gtk"> - <file preprocess="xml-stripblanks" compressed="true">ui/setup.ui</file> - </gresource> -</gresources> diff --git a/res/ui/setup.ui b/res/ui/setup.ui deleted file mode 100644 index 59da619951063815cff4cd558a8ba79485bf584b..0000000000000000000000000000000000000000 --- a/res/ui/setup.ui +++ /dev/null @@ -1,121 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<interface> - <requires lib="gtk+" version="3.20"/> - <template class="BriarGtkWindow" parent="GtkApplicationWindow"> - <property name="default-width">600</property> - <property name="default-height">300</property> - <child type="titlebar"> - <object class="GtkHeaderBar" id="header_bar"> - <property name="visible">True</property> - <property name="show-close-button">True</property> - <property name="title">Welcome to Briar</property> - </object> - </child> - <child> - <object class="GtkGrid"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="halign">center</property> - <property name="valign">center</property> - <property name="margin_left">18</property> - <property name="margin_right">18</property> - <property name="margin_top">18</property> - <property name="margin_bottom">18</property> - <child> - <object class="GtkGrid" id="username_grid"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> - <child> - <object class="GtkLabel" id="username_label"> - <property name="visible">True</property> - <property name="halign">center</property> - <property name="label" translatable="yes">Nickname</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">0</property> - </packing> - </child> - <child> - <object class="GtkEntry" id="username_entry"> - <property name="visible">True</property> - <property name="placeholder_text" translatable="yes">Choose your nickname</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">1</property> - </packing> - </child> - <child> - <object class="GtkButton" id="username_next"> - <property name="visible">True</property> - <property name="halign">center</property> - <property name="label" translatable="yes">Next</property> - <signal name="clicked" handler="on_username_button_clicked"/> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">2</property> - </packing> - </child> - </object> - </child> - <child> - <object class="GtkGrid" id="password_grid"> - <property name="visible">False</property> - <property name="can_focus">False</property> - <property name="row_spacing">6</property> - <property name="column_spacing">12</property> - <child> - <object class="GtkLabel" id="password_label"> - <property name="visible">True</property> - <property name="halign">center</property> - <property name="label" translatable="yes">Password</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">0</property> - </packing> - </child> - <child> - <object class="GtkEntry" id="password_entry"> - <property name="visible">True</property> - <property name="placeholder_text" translatable="yes">Choose your password</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">1</property> - </packing> - </child> - <child> - <object class="GtkEntry" id="password_confirm_entry"> - <property name="visible">True</property> - <property name="placeholder_text" translatable="yes">Confirm your password</property> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">2</property> - </packing> - </child> - <child> - <object class="GtkButton" id="password_next"> - <property name="visible">True</property> - <property name="halign">center</property> - <property name="label" translatable="yes">Next</property> - <signal name="clicked" handler="on_password_button_clicked"/> - </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">3</property> - </packing> - </child> - </object> - </child> - </object> - </child> - </template> -</interface> - - diff --git a/src/__init__.py b/src/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/briar-gtk.in b/src/briar-gtk.in index b64d27e396ad0d52ae0b7f1c20cef5fda7163795..e29cffa37a7081f7c221d04673d4ec0520a3672c 100755 --- a/src/briar-gtk.in +++ b/src/briar-gtk.in @@ -1,7 +1,5 @@ #!@PYTHON@ -# briar-gtk.in -# # Copyright 2019 Nico Alt # # This program is free software: you can redistribute it and/or modify @@ -15,27 +13,34 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# +# Initial version based on GNOME Lollypop +# https://gitlab.gnome.org/World/lollypop/blob/1.0.2/lollypop.in +import gettext +import locale import os -import sys import signal -import gettext +import sys -VERSION = '@VERSION@' pkgdatadir = '@pkgdatadir@' localedir = '@localedir@' sys.path.insert(1, pkgdatadir) signal.signal(signal.SIGINT, signal.SIG_DFL) -gettext.install('briar-gtk', localedir) if __name__ == '__main__': + locale.bindtextdomain('briar-gtk', localedir) + locale.textdomain('briar-gtk') + gettext.bindtextdomain('briar-gtk', localedir) + gettext.textdomain('briar-gtk') + import gi from gi.repository import Gio resource = Gio.Resource.load(os.path.join(pkgdatadir, 'briar-gtk.gresource')) resource._register() - from briar_gtk import main - sys.exit(main.main(VERSION)) + from briar.gtk.application import Application + sys.exit(Application("@VERSION@").run(sys.argv)) diff --git a/src/briar/api/api.py b/src/briar/api/api.py new file mode 100644 index 0000000000000000000000000000000000000000..7e613ce609f694aa4bdb18a830d383c884753978 --- /dev/null +++ b/src/briar/api/api.py @@ -0,0 +1,42 @@ +# Copyright (c) 2019 Nico Alt +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +from subprocess import Popen, PIPE + + +class Api: + + def __init__(self, headless_jar, debug=False): + self.headless_jar = headless_jar + + def has_account(self): + from pathlib import Path + home = str(Path.home()) + from os.path import isdir, join + return isdir(join(home, ".briar", "db")) + + def login(self, password): + p = Popen(['java', '-jar', self.headless_jar, '-v'], + stdin=PIPE, universal_newlines=True) + p.communicate(password + '\n') + + def register(self, credentials): + p = Popen(['java', '-jar', self.headless_jar, '-v'], + stdin=PIPE, universal_newlines=True) + p.communicate(credentials[0] + '\n' + credentials[1] + + '\n' + credentials[1] + '\n') + + def stop(self): + pass diff --git a/src/briar/briar.py b/src/briar/api/briar.py similarity index 97% rename from src/briar/briar.py rename to src/briar/api/briar.py index 4a3c68e879fa788c1330480135e74740271cd702..5d947b37dedbc6334e4f0d8d62ba74caebac64a5 100644 --- a/src/briar/briar.py +++ b/src/briar/api/briar.py @@ -11,7 +11,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. # # Originally coming from # https://code.briarproject.org/grote/briar-cli-python-demo/blob/master/briar-cli.py diff --git a/src/briar/gtk/application.py b/src/briar/gtk/application.py new file mode 100644 index 0000000000000000000000000000000000000000..342db900e1cbf18a76e6821531718785f7aa932a --- /dev/null +++ b/src/briar/gtk/application.py @@ -0,0 +1,68 @@ +# Copyright (c) 2019 Nico Alt +# Copyright (c) 2014-2018 Cedric Bellegarde <cedric.bellegarde@adishatz.org> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# +# Initial version based on GNOME Lollypop +# https://gitlab.gnome.org/World/lollypop/blob/1.0.2/lollypop/application.py + +from briar.api.api import Api + +from briar.gtk.window import Window + +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gdk, Gio, GLib, Gtk + + +class Application(Gtk.Application): + + def __init__(self, version): + super().__init__(application_id='app.briar.gtk', + flags=Gio.ApplicationFlags.FLAGS_NONE) + self.__version = version + self.set_property("register-session", True) + self.window = None + self.debug = True # TODO: Change this in production + GLib.set_application_name("Briar") + GLib.set_prgname("briar-gtk") + self.api = Api('/app/briar/briar-headless.jar', self.debug) + self.connect("activate", self.__on_activate) + self.register(None) + + def init(self): + cssProviderFile = Gio.File.new_for_uri( + "resource:///app/briar/gtk/ui/application.css") + cssProvider = Gtk.CssProvider() + cssProvider.load_from_file(cssProviderFile) + screen = Gdk.Screen.get_default() + styleContext = Gtk.StyleContext() + styleContext.add_provider_for_screen(screen, cssProvider, + Gtk.STYLE_PROVIDER_PRIORITY_USER) + + def do_startup(self): + Gtk.Application.do_startup(self) + if self.window is None: + self.init() + self.window = Window() + self.window.show() + + def quit(self): + self.api.stop() + self.window.hide() + Gio.Application.quit(self) + + def __on_activate(self, application): + pass + diff --git a/src/briar/gtk/container.py b/src/briar/gtk/container.py new file mode 100644 index 0000000000000000000000000000000000000000..e9770b0cc5634c5ab7d91aa26a3ddbc9526f9272 --- /dev/null +++ b/src/briar/gtk/container.py @@ -0,0 +1,52 @@ +# Copyright (c) 2019 Nico Alt +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +from briar.gtk.define import App +from briar.gtk.logger import Logger + +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk + + +class Container(Gtk.Overlay): + + def __init__(self): + Gtk.Overlay.__init__(self) + self.__setup_view() + + def __setup_view(self): + Logger.debug("Api has account: %s", App().api.has_account()) + self.builder = Gtk.Builder() + if not App().api.has_account(): + self.builder.add_from_resource("/app/briar/gtk/ui/setup.ui") + self.add(self.builder.get_object("setup")) + else: + self.builder.add_from_resource("/app/briar/gtk/ui/login.ui") + self.add(self.builder.get_object("login")) + self.builder.connect_signals(self) + + def on_username_button_clicked(self, button): + self.builder.get_object("username_grid").set_visible(False) + self.builder.get_object("password_grid").set_visible(True) + self.username = self.builder.get_object("username_entry").get_text() + + def on_password_button_clicked(self, button): + password = self.builder.get_object("password_entry").get_text() + App().api.register((self.username, password)) # TODO: callback + + def on_login_pressed(self, button): + password = self.builder.get_object("password_entry").get_text() + App().api.login(password) # TODO: callback diff --git a/src/briar/gtk/define.py b/src/briar/gtk/define.py new file mode 100644 index 0000000000000000000000000000000000000000..509123617dc969a975f515d5f714f9175b5ef80f --- /dev/null +++ b/src/briar/gtk/define.py @@ -0,0 +1,22 @@ +# Copyright (c) 2019 Nico Alt +# Copyright (c) 2014-2018 Cedric Bellegarde <cedric.bellegarde@adishatz.org> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# +# Initial version based on GNOME Lollypop +# https://gitlab.gnome.org/World/lollypop/blob/1.0.2/lollypop/define.py + +from gi.repository import Gio + +App = Gio.Application.get_default diff --git a/src/briar/gtk/logger.py b/src/briar/gtk/logger.py new file mode 100644 index 0000000000000000000000000000000000000000..b4a8839020181dec8c3130c480a76528a2440396 --- /dev/null +++ b/src/briar/gtk/logger.py @@ -0,0 +1,63 @@ +# Copyright (c) 2019 Nico Alt +# Copyright (c) 2014-2018 Cedric Bellegarde <cedric.bellegarde@adishatz.org> +# Copyright (c) 2017 Bilal Elmoussaoui <bil.elmoussaoui@gmail.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# +# Initial version based on GNOME Lollypop +# https://gitlab.gnome.org/World/lollypop/blob/1.0.2/lollypop/logger.py + +import logging +import sys + +from briar.gtk.define import App + + +class Logger: + + FORMAT = "[%(levelname)-s] %(asctime)s %(message)s" + DATE = "%Y-%m-%d %H:%M:%S" + __log = None + APP = "app.briar.gtk" + + @staticmethod + def get_default(): + if Logger.__log is None: + logger = logging.getLogger(Logger.APP) + + handler = logging.StreamHandler(sys.stdout) + formater = logging.Formatter(Logger.FORMAT, Logger.DATE) + handler.setFormatter(formater) + logger.addHandler(handler) + logger.setLevel(logging.DEBUG) + + Logger.__log = logging.getLogger(Logger.APP) + return Logger.__log + + @staticmethod + def warning(msg, *args): + Logger.get_default().warning(msg, *args) + + @staticmethod + def debug(msg, *args): + if App().debug: + Logger.get_default().debug(msg, *args) + + @staticmethod + def info(msg, *args): + Logger.get_default().info(msg, *args) + + @staticmethod + def error(msg, *args): + Logger.get_default().error(msg, *args) diff --git a/src/briar/gtk/window.py b/src/briar/gtk/window.py new file mode 100644 index 0000000000000000000000000000000000000000..82448943d1a70f00287721ee77b7e0ad7ecf0aa8 --- /dev/null +++ b/src/briar/gtk/window.py @@ -0,0 +1,44 @@ +# Copyright (c) 2019 Nico Alt +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +from briar.gtk.container import Container +from briar.gtk.define import App + +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk, Gdk, GLib + + +class Window(Gtk.ApplicationWindow): + + def __init__(self): + Gtk.ApplicationWindow.__init__(self, + application=App(), + title="Briar", + icon_name="app.briar.gtk") + self.__setup_content() + + @property + def container(self): + return self.__container + + def __setup_content(self): + self.__container = Container() + self.__container.show() + self.__vgrid = Gtk.Grid() + self.__vgrid.set_orientation(Gtk.Orientation.VERTICAL) + self.__vgrid.show() + self.__vgrid.add(self.__container) + self.add(self.__vgrid) diff --git a/src/main.py b/src/main.py deleted file mode 100644 index 96e76a502208c68bb4c4a7143a5038f01f83c9d3..0000000000000000000000000000000000000000 --- a/src/main.py +++ /dev/null @@ -1,42 +0,0 @@ -# main.py -# -# Copyright 2019 Nico Alt -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -import sys -import gi - -gi.require_version('Gtk', '3.0') - -from gi.repository import Gtk, Gio - -from .setup import BriarSetupWindow - - -class Application(Gtk.Application): - def __init__(self): - super().__init__(application_id='app.briar.gtk', - flags=Gio.ApplicationFlags.FLAGS_NONE) - - def do_activate(self): - win = self.props.active_window - if not win: - win = BriarSetupWindow(application=self) - win.present() - - -def main(version): - app = Application() - return app.run(sys.argv) diff --git a/src/meson.build b/src/meson.build index 7faa3ba4cc0195e76d7112bcf7efe2d2d90b21b0..7d0bdbfd1054640ca027ed90c6a01ce050040b71 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,5 +1,5 @@ pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), meson.project_name()) -moduledir = join_paths(pkgdatadir, 'briar_gtk') +moduledir = join_paths(pkgdatadir, 'briar') python3 = import('python3') @@ -17,11 +17,5 @@ configure_file( install_dir: get_option('bindir') ) -briar_gtk_sources = [ - '__init__.py', - 'main.py', - 'ui/gi_composites.py', - 'ui/setup.py', -] - -install_data(briar_gtk_sources, install_dir: moduledir) +install_subdir('briar/api', install_dir: moduledir) +install_subdir('briar/gtk', install_dir: moduledir) diff --git a/build-aux/meson/postinstall.py b/src/meson_post_install.py similarity index 100% rename from build-aux/meson/postinstall.py rename to src/meson_post_install.py diff --git a/src/ui/gi_composites.py b/src/ui/gi_composites.py deleted file mode 100644 index c68402b2144a4c6dc1b846a652c8df66284bebd6..0000000000000000000000000000000000000000 --- a/src/ui/gi_composites.py +++ /dev/null @@ -1,268 +0,0 @@ -# -# Copyright 2015 Dustin Spicuzza <dustin@virtualroadside.com> -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 -# USA - -from os.path import abspath, join - -import inspect -import warnings - -from gi.repository import Gio -from gi.repository import GLib -from gi.repository import GObject -from gi.repository import Gtk - -__all__ = ['GtkTemplate'] - - -class GtkTemplateWarning(UserWarning): - pass - - -def _connect_func(builder, obj, signal_name, handler_name, - connect_object, flags, cls): - '''Handles GtkBuilder signal connect events''' - - if connect_object is None: - extra = () - else: - extra = (connect_object,) - - # The handler name refers to an attribute on the template instance, - # so ask GtkBuilder for the template instance - template_inst = builder.get_object(cls.__gtype_name__) - - if template_inst is None: # This should never happen - errmsg = "Internal error: cannot find template instance! obj: %s; " \ - "signal: %s; handler: %s; connect_obj: %s; class: %s" % \ - (obj, signal_name, handler_name, connect_object, cls) - warnings.warn(errmsg, GtkTemplateWarning) - return - - handler = getattr(template_inst, handler_name) - - if flags == GObject.ConnectFlags.AFTER: - obj.connect_after(signal_name, handler, *extra) - else: - obj.connect(signal_name, handler, *extra) - - template_inst.__connected_template_signals__.add(handler_name) - - -def _register_template(cls, template_bytes): - '''Registers the template for the widget and hooks init_template''' - - # This implementation won't work if there are nested templates, but - # we can't do that anyways due to PyGObject limitations so it's ok - - if not hasattr(cls, 'set_template'): - raise TypeError("Requires PyGObject 3.13.2 or greater") - - cls.set_template(template_bytes) - - bound_methods = set() - bound_widgets = set() - - # Walk the class, find marked callbacks and child attributes - for name in dir(cls): - - o = getattr(cls, name, None) - - if inspect.ismethod(o): - if hasattr(o, '_gtk_callback'): - bound_methods.add(name) - # Don't need to call this, as connect_func always gets called - # cls.bind_template_callback_full(name, o) - elif isinstance(o, _Child): - cls.bind_template_child_full(name, True, 0) - bound_widgets.add(name) - - # Have to setup a special connect function to connect at template init - # because the methods are not bound yet - cls.set_connect_func(_connect_func, cls) - - cls.__gtemplate_methods__ = bound_methods - cls.__gtemplate_widgets__ = bound_widgets - - base_init_template = cls.init_template - cls.init_template = lambda s: _init_template(s, cls, base_init_template) - - -def _init_template(self, cls, base_init_template): - '''This would be better as an override for Gtk.Widget''' - - # TODO: could disallow using a metaclass.. but this is good enough - # .. if you disagree, feel free to fix it and issue a PR :) - if self.__class__ is not cls: - raise TypeError("Inheritance from classes with @GtkTemplate decorators" - " is not allowed at this time") - - connected_signals = set() - self.__connected_template_signals__ = connected_signals - - base_init_template(self) - - for name in self.__gtemplate_widgets__: - widget = self.get_template_child(cls, name) - self.__dict__[name] = widget - - if widget is None: - # Bug: if you bind a template child, and one of them was - # not present, then the whole template is broken (and - # it's not currently possible for us to know which - # one is broken either -- but the stderr should show - # something useful with a Gtk-CRITICAL message) - raise AttributeError("A missing child widget was set using " - "GtkTemplate.Child and the entire " - "template is now broken (widgets: %s)" % - ', '.join(self.__gtemplate_widgets__)) - - for name in self.__gtemplate_methods__.difference(connected_signals): - errmsg = ("Signal '%s' was declared with @GtkTemplate.Callback " + - "but was not present in template") % name - warnings.warn(errmsg, GtkTemplateWarning) - - -# TODO: Make it easier for IDE to introspect this -class _Child(object): - ''' - Assign this to an attribute in your class definition and it will - be replaced with a widget defined in the UI file when init_template - is called - ''' - - __slots__ = [] - - @staticmethod - def widgets(count): - ''' - Allows declaring multiple widgets with less typing:: - - button \ - label1 \ - label2 = GtkTemplate.Child.widgets(3) - ''' - return [_Child() for _ in range(count)] - - -class _GtkTemplate(object): - ''' - Use this class decorator to signify that a class is a composite - widget which will receive widgets and connect to signals as - defined in a UI template. You must call init_template to - cause the widgets/signals to be initialized from the template:: - - @GtkTemplate(ui='foo.ui') - class Foo(Gtk.Box): - - def __init__(self): - super(Foo, self).__init__() - self.init_template() - - The 'ui' parameter can either be a file path or a GResource resource - path:: - - @GtkTemplate(ui='/org/example/foo.ui') - class Foo(Gtk.Box): - pass - - To connect a signal to a method on your instance, do:: - - @GtkTemplate.Callback - def on_thing_happened(self, widget): - pass - - To create a child attribute that is retrieved from your template, - add this to your class definition:: - - @GtkTemplate(ui='foo.ui') - class Foo(Gtk.Box): - - widget = GtkTemplate.Child() - - - Note: This is implemented as a class decorator, but if it were - included with PyGI I suspect it might be better to do this - in the GObject metaclass (or similar) so that init_template - can be called automatically instead of forcing the user to do it. - - .. note:: Due to limitations in PyGObject, you may not inherit from - python objects that use the GtkTemplate decorator. - ''' - - __ui_path__ = None - - @staticmethod - def Callback(f): - ''' - Decorator that designates a method to be attached to a signal from - the template - ''' - f._gtk_callback = True - return f - - Child = _Child - - @staticmethod - def set_ui_path(*path): - ''' - If using file paths instead of resources, call this *before* - loading anything that uses GtkTemplate, or it will fail to load - your template file - - :param path: one or more path elements, will be joined together - to create the final path - - TODO: Alternatively, could wait until first class instantiation - before registering templates? Would need a metaclass... - ''' - _GtkTemplate.__ui_path__ = abspath(join(*path)) - - def __init__(self, ui): - self.ui = ui - - def __call__(self, cls): - - if not issubclass(cls, Gtk.Widget): - raise TypeError("Can only use @GtkTemplate on Widgets") - - # Nested templates don't work - if hasattr(cls, '__gtemplate_methods__'): - raise TypeError("Cannot nest template classes") - - # Load the template either from a resource path or a file - # - Prefer the resource path first - - try: - template_bytes = \ - Gio.resources_lookup_data(self.ui, Gio.ResourceLookupFlags.NONE) - except GLib.GError: - ui = self.ui - if isinstance(ui, (list, tuple)): - ui = join(ui) - - if _GtkTemplate.__ui_path__ is not None: - ui = join(_GtkTemplate.__ui_path__, ui) - - with open(ui, 'rb') as fp: - template_bytes = GLib.Bytes.new(fp.read()) - - _register_template(cls, template_bytes) - return cls - - -GtkTemplate = _GtkTemplate diff --git a/src/ui/setup.py b/src/ui/setup.py deleted file mode 100644 index 58e37e773672d764015fc85f3aee3cab82da3b77..0000000000000000000000000000000000000000 --- a/src/ui/setup.py +++ /dev/null @@ -1,43 +0,0 @@ -# window.py -# -# Copyright 2019 Nico Alt -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -from gi.repository import Gtk -from .gi_composites import GtkTemplate - - -@GtkTemplate(ui='/app/briar/gtk/ui/setup.ui') -class BriarSetupWindow(Gtk.ApplicationWindow): - __gtype_name__ = 'BriarGtkWindow' - - username_grid = GtkTemplate.Child() - username_entry = GtkTemplate.Child() - - password_grid = GtkTemplate.Child() - password_entry = GtkTemplate.Child() - password_confirm_entry = GtkTemplate.Child() - - def __init__(self, **kwargs): - super().__init__(**kwargs) - self.init_template() - - def on_username_button_clicked(self, button): - self.username_grid.set_visible(False) - self.password_grid.set_visible(True) - self.username = self.username_entry.get_text() - - def on_password_button_clicked(self, button): - self.password = self.password_entry.get_text() diff --git a/tools/generate_data.sh b/tools/generate_data.sh new file mode 100755 index 0000000000000000000000000000000000000000..4a65b4ee83168954fec51f4ffabda6999973a003 --- /dev/null +++ b/tools/generate_data.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# Initial version from GNOME Lollypop +# https://gitlab.gnome.org/World/lollypop/blob/1.0.2/generate_data.sh + +function generate_resource() +{ + echo '<?xml version="1.0" encoding="UTF-8"?>' + echo '<gresources>' + echo ' <gresource prefix="/app/briar/gtk">' + for file in data/ui/*.css + do + echo -n ' <file compressed="true">' + echo -n 'ui/' + echo -n $(basename $file) + echo '</file>' + done + for file in data/ui/*.ui + do + echo -n ' <file compressed="true" preprocess="xml-stripblanks">' + echo -n 'ui/' + echo -n $(basename $file) + echo '</file>' + done + echo ' </gresource>' + echo '</gresources>' +} + +function generate_po() +{ + cd po + # git pull https://www.transifex.com/otf/briar/ + >briar-gtk.pot + for file in ../data/app.briar.gtk.gschema.xml ../data/ui/*.ui $(find "../src/briar" -name '*.py'); + do + xgettext --from-code=UTF-8 -j $file -o briar-gtk.pot + done + >LINGUAS + for po in *.po + do + msgmerge -N $po briar-gtk.pot > /tmp/$$language_new.po + mv /tmp/$$language_new.po $po + language=${po%.po} + echo $language >>LINGUAS + done +} + +generate_resource > data/ui/app.briar.gtk.gresource.xml +generate_po