diff --git a/build-aux/meson/postinstall.py b/build-aux/meson/postinstall.py
new file mode 100644
index 0000000..6a3ea97
--- /dev/null
+++ b/build-aux/meson/postinstall.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python3
+
+from os import environ, path
+from subprocess import call
+
+prefix = environ.get('MESON_INSTALL_PREFIX', '/usr/local')
+datadir = path.join(prefix, 'share')
+destdir = environ.get('DESTDIR', '')
+
+# Package managers set this so we don't need to run
+if not destdir:
+ print('Updating icon cache...')
+ call(['gtk-update-icon-cache', '-qtf', path.join(datadir, 'icons', 'hicolor')])
+
+ print('Updating desktop database...')
+ call(['update-desktop-database', '-q', path.join(datadir, 'applications')])
+
+ print('Compiling GSettings schemas...')
+ call(['glib-compile-schemas', path.join(datadir, 'glib-2.0', 'schemas')])
+
+
diff --git a/data/meson.build b/data/meson.build
new file mode 100644
index 0000000..974b626
--- /dev/null
+++ b/data/meson.build
@@ -0,0 +1,41 @@
+desktop_file = i18n.merge_file(
+ input: 'org.gnome.Ddgtk.desktop.in',
+ output: 'org.gnome.Ddgtk.desktop',
+ type: 'desktop',
+ po_dir: '../po',
+ install: true,
+ install_dir: join_paths(get_option('datadir'), 'applications')
+)
+
+desktop_utils = find_program('desktop-file-validate', required: false)
+if desktop_utils.found()
+ test('Validate desktop file', desktop_utils,
+ args: [desktop_file]
+ )
+endif
+
+appstream_file = i18n.merge_file(
+ input: 'org.gnome.Ddgtk.appdata.xml.in',
+ output: 'org.gnome.Ddgtk.appdata.xml',
+ po_dir: '../po',
+ install: true,
+ install_dir: join_paths(get_option('datadir'), 'appdata')
+)
+
+appstream_util = find_program('appstream-util', required: false)
+if appstream_util.found()
+ test('Validate appstream file', appstream_util,
+ args: ['validate', appstream_file]
+ )
+endif
+
+install_data('org.gnome.Ddgtk.gschema.xml',
+ install_dir: join_paths(get_option('datadir'), 'glib-2.0/schemas')
+)
+
+compile_schemas = find_program('glib-compile-schemas', required: false)
+if compile_schemas.found()
+ test('Validate schema file', compile_schemas,
+ args: ['--strict', '--dry-run', meson.current_source_dir()]
+ )
+endif
diff --git a/data/org.gnome.Ddgtk.appdata.xml.in b/data/org.gnome.Ddgtk.appdata.xml.in
new file mode 100644
index 0000000..116a8b1
--- /dev/null
+++ b/data/org.gnome.Ddgtk.appdata.xml.in
@@ -0,0 +1,7 @@
+
+
+ org.gnome.Ddgtk.desktop
+ CC0
+
+
+
diff --git a/data/org.gnome.Ddgtk.desktop.in b/data/org.gnome.Ddgtk.desktop.in
new file mode 100644
index 0000000..3e10bd0
--- /dev/null
+++ b/data/org.gnome.Ddgtk.desktop.in
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=ddgtk
+Exec=ddgtk
+Terminal=false
+Type=Application
+Categories=GTK;
+StartupNotify=true
diff --git a/data/org.gnome.Ddgtk.gschema.xml b/data/org.gnome.Ddgtk.gschema.xml
new file mode 100644
index 0000000..7653ce4
--- /dev/null
+++ b/data/org.gnome.Ddgtk.gschema.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..34bad8a
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,11 @@
+project('ddgtk',
+ version: '0.1.0',
+ meson_version: '>= 0.40.0',
+)
+i18n = import('i18n')
+
+
+subdir('data')
+subdir('src')
+subdir('po')
+meson.add_install_script('build-aux/meson/postinstall.py')
diff --git a/po/POTFILES b/po/POTFILES
new file mode 100644
index 0000000..c771413
--- /dev/null
+++ b/po/POTFILES
@@ -0,0 +1,9 @@
+data/org.gnome.Ddgtk.desktop.in
+data/org.gnome.Ddgtk.appdata.xml.in
+data/org.gnome.Ddgtk.gschema.xml
+src/window.ui
+
+
+
+src/main.py
+src/window.py
diff --git a/po/meson.build b/po/meson.build
new file mode 100644
index 0000000..0e8688b
--- /dev/null
+++ b/po/meson.build
@@ -0,0 +1 @@
+i18n.gettext('ddgtk', preset: 'glib')
diff --git a/src/ddgtk.gresource.xml b/src/ddgtk.gresource.xml
new file mode 100644
index 0000000..3adab00
--- /dev/null
+++ b/src/ddgtk.gresource.xml
@@ -0,0 +1,6 @@
+
+
+
+ window.ui
+
+
diff --git a/src/ddgtk.in b/src/ddgtk.in
new file mode 100644
index 0000000..61130a9
--- /dev/null
+++ b/src/ddgtk.in
@@ -0,0 +1,41 @@
+#!@PYTHON@
+
+# ddgtk.in
+#
+# Copyright (C) 2017 Alessandro
+#
+# 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 .
+
+import os
+import sys
+import signal
+import gettext
+
+VERSION = '@VERSION@'
+pkgdatadir = '@pkgdatadir@'
+localedir = '@localedir@'
+
+sys.path.insert(1, pkgdatadir)
+signal.signal(signal.SIGINT, signal.SIG_DFL)
+gettext.install('ddgtk', localedir)
+
+if __name__ == '__main__':
+ import gi
+
+ from gi.repository import Gio
+ resource = Gio.Resource.load(os.path.join(pkgdatadir, 'ddgtk.gresource'))
+ resource._register()
+
+ from ddgtk import main
+ sys.exit(main.main())
diff --git a/src/gi_composites.py b/src/gi_composites.py
new file mode 100644
index 0000000..857e584
--- /dev/null
+++ b/src/gi_composites.py
@@ -0,0 +1,273 @@
+#
+# Copyright (C) 2015 Dustin Spicuzza
+#
+# 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
+
+
+
+# Future shim support if this makes it into PyGI?
+#if hasattr(Gtk, 'GtkTemplate'):
+# GtkTemplate = lambda c: c
+#else:
+GtkTemplate = _GtkTemplate
+
diff --git a/ddgtk.py b/src/main.py
similarity index 86%
rename from ddgtk.py
rename to src/main.py
index cf9457d..5e76611 100644
--- a/ddgtk.py
+++ b/src/main.py
@@ -1,7 +1,22 @@
-#!/usr/bin/python
+# main.py
+#
+# Copyright (C) 2017 Alessandro
+#
+# 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 .
import gi
-gi.require_version('Gtk', '3.0')
+gi.require_version('Gtk', '3.0')
gi.require_version('Vte', '2.91')
from gi.repository import Gtk, Vte, GLib
@@ -21,21 +36,16 @@ def get_data():
for i in range(len(now)):
new_list.append(i)
my_dict=dict(zip(new_list,now))
-
+
return my_dict
-class launcher:
- def __init__(self):
-
- self.terminal = Vte.Terminal()
+class Application():
+ def __init__(self):
self.builder = Gtk.Builder()
- #GObject.type_register(Vte.Terminal)
-
- self.builder.add_from_file("/home/alessandro/Projects/ddgtk/ddgtk.glade")
-
+ self.builder.add_from_resource('/org/gnome/Ddgtk/window.ui')
self.builder.connect_signals(self)
-
+ self.terminal = Vte.Terminal()
self.window = self.builder.get_object('window')
self.window.connect('destroy', lambda w: Gtk.main_quit())
icontheme = Gtk.IconTheme.get_default()
@@ -74,7 +84,6 @@ def __init__(self):
None,
None,
)
- #self.terminal.show()
def on_file_set(self,widget):
print(self.file.get_filename())
self.filename=self.file.get_filename()
@@ -91,7 +100,7 @@ def on_combo_changed(self,widget):
self.device=self.device.split(' ')[0]
call(["lsblk",self.device])
def on_start_clicked(self,widget):
-
+
if (self.file.get_filename()) == None:
print("No file selected")
self.no_file_message.show()
@@ -112,18 +121,20 @@ def dd(self):
wait="echo 'Writing to disk please wait!'\n"
self.umount= "umount " + self.device+"*" + " &>/dev/null \n"
self.command = "pkexec dd if="+self.filename+" of="+self.device+" status=progress && sync;exit \n"
+
self.terminal.feed_child(clear,-1)
self.terminal.feed_child(wait,-1)
self.terminal.feed_child(self.umount,-1)
#self.terminal.feed_child(cmd,-1)
+ self.terminal.unselect_all()
self.terminal.feed_child(self.command,-1)
-
+
#self.terminal.set_input_enabled(False)
-
+
def on_expander_activate(self,widget):
self.terminal.set_rewrap_on_resize(True)
self.terminal.show()
-
+
def on_no_file_button_clicked(self,widget):
self.no_file_message.hide()
def on_done_button_clicked(self,widget):
@@ -144,7 +155,7 @@ def on_confirm_ok_clicked(self,widget):
def on_confirm_cancel_clicked(self,widget):
self.confirm.hide()
return
-
+
def done (self,terminal,a):
if a is not 0:
print("Authentication error or command error")
@@ -154,13 +165,9 @@ def done (self,terminal,a):
print("All done")
self.done_button.set_visible(True)
self.create_disk_label.set_text("Finshed!\n Click the done Button :)")
-
-
-def main():
- launcher()
- Gtk.main()
-if __name__ == '__main__':
- main()
+def main():
+ Application()
+ Gtk.main()
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 0000000..24120fb
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,38 @@
+pkgdatadir = join_paths(get_option('prefix'), get_option('datadir'), meson.project_name())
+moduledir = join_paths(pkgdatadir, 'ddgtk')
+gnome = import('gnome')
+
+gnome.compile_resources('ddgtk',
+ 'ddgtk.gresource.xml',
+ gresource_bundle: true,
+ install: true,
+ install_dir: pkgdatadir,
+)
+
+python3 = import('python3')
+
+conf = configuration_data()
+conf.set('PYTHON', python3.find_python().path())
+conf.set('VERSION', meson.project_version())
+conf.set('localedir', join_paths(get_option('prefix'), get_option('localedir')))
+conf.set('pkgdatadir', pkgdatadir)
+r= run_command('chmod','755','ddgtk.in')
+if r.returncode() != 0
+ # it failed
+endif
+configure_file(
+ input: 'ddgtk.in',
+ output: 'ddgtk',
+ configuration: conf,
+ install: true,
+ install_dir: get_option('bindir'),
+
+)
+
+
+ddgtk_sources = [
+ 'gi_composites.py',
+ 'main.py',
+]
+
+install_data(ddgtk_sources, install_dir: moduledir)
diff --git a/ddgtk.glade b/src/window.ui
similarity index 100%
rename from ddgtk.glade
rename to src/window.ui