From ce894c33ed985e8bd307d0bf097d32d2753ab5ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas?= Date: Sun, 13 Jul 2014 19:14:25 +0200 Subject: [PATCH 01/18] Started new development branch --- src/jsoninspector.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jsoninspector.py b/src/jsoninspector.py index ecd541d..31ccbdd 100644 --- a/src/jsoninspector.py +++ b/src/jsoninspector.py @@ -25,7 +25,7 @@ class MainWindowMethods(object): principal """ self.builder = gtk.Builder() - self.builder.add_from_file(resource_filename(__name__,'../../src/jsoninspector.glade')) + self.builder.add_from_file(resource_filename(__name__,'jsoninspector.glade')) self.builder.connect_signals(self) # Prepara los renderizados de columna y las asigna a los valores From cb9fb1891124368d0a870b50ea21a7195b454b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas=20Albadalejo?= Date: Mon, 14 Jul 2014 08:16:19 +0200 Subject: [PATCH 02/18] Started updating setup.py file --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 8f94989..fb4bf7a 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ distribute_setup.use_setuptools() from setuptools import setup, find_packages setup( name = "jsoninspector", - version = "1.3", + version = "1.5", packages = find_packages('src', exclude=['distribute_setup']), scripts = ['src/jsoninspector.py'], entry_points = { @@ -23,5 +23,5 @@ setup( description = "JSON Inspector is a simple application to study JSON code", license = "GPLv3", keywords = "json inspect gtk gnome", - url = "", # project home page, if any + url = "https://github.com/resetreboot/jsoninspector", # project home page, if any ) From c8140f5abe4965208548d8c0fbb09fb5d76ec63b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas=20Albadalejo?= Date: Mon, 14 Jul 2014 10:37:32 +0200 Subject: [PATCH 03/18] Updated to GTK3. --- src/jsoninspector.glade | 285 ++++++++++++++++++++++++++-------------- src/jsoninspector.py | 123 ++++++++--------- 2 files changed, 241 insertions(+), 167 deletions(-) diff --git a/src/jsoninspector.glade b/src/jsoninspector.glade index 949469e..69a574f 100644 --- a/src/jsoninspector.glade +++ b/src/jsoninspector.glade @@ -1,7 +1,117 @@ - + + - - + + + False + Introducir texto JSON + True + center + 200 + 180 + + + + + True + False + vertical + + + True + True + in + + + 200 + 140 + True + True + char + + + + + True + True + 0 + + + + + True + False + + + gtk-cancel + True + True + True + True + + + + False + True + 5 + end + 0 + + + + + gtk-ok + True + True + True + True + + + + False + True + 5 + end + 1 + + + + + + + + + + + + + + False + True + 1 + + + + + + + 100 + 1 + 10 + 10 + + + 100 + 1 + 10 + 10 + + + True + False + gtk-copy + + @@ -15,53 +125,64 @@ 400 400 + False JSON Inspector center - + - + True + False + vertical True + False True - _Archivo + False + _File True True + False gtk-open True + False True True - + - Copiar JSON + Cop_y JSON True + False + True image1 False - + True + False gtk-quit True + False True True - + @@ -71,17 +192,21 @@ True - Ay_uda + False + _Help True True + False gtk-about True + False True True + @@ -91,6 +216,7 @@ False + True 0 @@ -100,22 +226,23 @@ True adjustment1 adjustment2 - automatic - automatic 300 300 True True - treestore1 adjustment1 adjustment2 + treestore1 False treeviewcolumn1 0 1 both + + + True @@ -143,125 +270,87 @@ + True + True 1 True + False 2 True + False No hay JSON cargado + False + True 0 False + True 2 - - 100 - 1 - 10 - 10 - - - - 100 - 1 - 10 - 10 - - - Introducir texto JSON - True - center - 200 - 180 - - + + True + True + adjustment1 + adjustment2 - + + 300 + 300 True - - - 200 - 140 - True - True - char - - - 5 - 0 - + True + adjustment1 + adjustment2 + treestore1 + False + treeviewcolumn1 + 0 + 1 + both + + - - True - - - - - - gtk-ok - True - True - True - True - - - - False - 5 - 1 - - - - - - - - gtk-cancel - True - True - True - True - - - - False - 5 - 3 - - - - - + + True + Nodo + True + True + 0 + + + + + True + Valor + True + + + + + True + Tipo + True - - False - 5 - 1 - - - True - gtk-copy - diff --git a/src/jsoninspector.py b/src/jsoninspector.py index 31ccbdd..fd027a4 100644 --- a/src/jsoninspector.py +++ b/src/jsoninspector.py @@ -4,78 +4,73 @@ from pkg_resources import resource_filename import json -import sys -import pygtk -try: - pygtk.require("2.0") -except: - print "Versión de PyGTK incorrecta!\n" - sys.exit(1) +from gi.repository import Gtk, Gdk, Gio -import gtk - -class MainWindowMethods(object): +class MainWindowMethods(Gtk.Application): """ - Clase que contiene los métodos de la ventana principal + Main Application object with the main window signals """ def __init__(self, logic): + Gtk.Application.__init__(self, application_id = "apps.gnome.stevedore", + flags = Gio.ApplicationFlags.FLAGS_NONE) + + # We store the reference to the app logic + self.logicObj = logic + + self.connect("activate", self.on_app_start) + + def on_app_start(self, data = None): """ - Carga y conecta el XML de gtkBuilder, además de mostrar la ventana - principal + Loads the MainWindow widgets, shows it up and starts the main loop """ - self.builder = gtk.Builder() + self.builder = Gtk.Builder() self.builder.add_from_file(resource_filename(__name__,'jsoninspector.glade')) self.builder.connect_signals(self) - # Prepara los renderizados de columna y las asigna a los valores - cell = gtk.CellRendererText() + # Prepares the renders of columns and assigns the values + cell = Gtk.CellRendererText() columns = self.builder.get_object("treeviewcolumn1") - columns.pack_start(cell) + columns.pack_start(cell, True) columns.add_attribute(cell, 'text', 0) treeview = self.builder.get_object("treeview1") - # Esta columna es la que tiene los nodos de apertura y cierre + # This column has the open and collapse nodes treeview.set_expander_column(columns) - cell = gtk.CellRendererText() + cell = Gtk.CellRendererText() columns = self.builder.get_object("treeviewcolumn2") - columns.pack_start(cell) + columns.pack_start(cell, True) columns.add_attribute(cell, 'text', 1) - cell = gtk.CellRendererText() + cell = Gtk.CellRendererText() columns = self.builder.get_object("treeviewcolumn3") - columns.pack_start(cell) + columns.pack_start(cell, True) columns.add_attribute(cell, 'text', 2) - # Obtenemos la ventana y la mostramos completamente + # We get the window and show it self.window = self.builder.get_object("MainWindow") + self.add_window(self.window) self.window.show_all() - # Obtenemos un enlace al objeto de lógica de aplicación - self.logicObj = logic - def onOpenMenuClicked(self, event): """ - El usuario ha presionado Abrir en el menu + User has pressed Open in the menu """ - # Creamos el dialogo de abrir fichero - chooser = gtk.FileChooserDialog(title=None, - action=gtk.FILE_CHOOSER_ACTION_OPEN, - buttons=(gtk.STOCK_CANCEL, - gtk.RESPONSE_CANCEL, - gtk.STOCK_OPEN, - gtk.RESPONSE_OK)) - chooser.set_default_response(gtk.RESPONSE_OK) + # Create the FileChooser Dialog + chooser = Gtk.FileChooserDialog("Open JSON text file", self.window, + Gtk.FileChooserAction.OPEN, + (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, + Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) - # Lo lanzamos + # Launch it response = chooser.run() - # Si hemos seleccionado un fichero, lo cargamos - if response == gtk.RESPONSE_OK: + # If we choose a file, we load it + if response == Gtk.ResponseType.OK: filename = chooser.get_filename() label = self.builder.get_object("StatusLabel") - # Según todo haya ido, actualizamos la barra de estado + # We update the statusbar accordingly to what has happened if self.logicObj.loadjson(filename): label.set_text(filename) @@ -87,20 +82,20 @@ class MainWindowMethods(object): label.set_text("No hay JSON cargado") - # Nos deshacemos del dialogo + # We finish the dialog chooser.destroy() def onCopyJSONClicked(self, widget): """ - Se ha pulsado Copiar JSON + User asked to paste a JSON code """ - # Mostrar la ventana de texto + # Show up the TextWindow textWindow = self.builder.get_object("TextWindow") textWindow.show_all() def onCopyJSONDelete(self, widget, event): """ - Se ha dado a cerrar la ventana de copiar texto + We've been told to close the CopyJSON Window """ textWindow = self.builder.get_object("TextWindow") textWindow.hide() @@ -109,7 +104,7 @@ class MainWindowMethods(object): def onCopyJSONDestroy(self, widget): """ - Se ha cerrado la ventana + We've been tasked with removing the CopyJSON window """ textWindow = self.builder.get_object("TextWindow") textWindow.hide() @@ -118,12 +113,12 @@ class MainWindowMethods(object): def onCopyJSONAcceptClicked(self, widget): """ - Se ha aceptado el código + The input is finished and accepted. """ textView = self.builder.get_object("textview1") jsonBuffer = textView.get_buffer() jsonText = jsonBuffer.get_text(jsonBuffer.get_start_iter(), - jsonBuffer.get_end_iter()) + jsonBuffer.get_end_iter(), True) textWindow = self.builder.get_object("TextWindow") textWindow.hide() @@ -138,24 +133,25 @@ class MainWindowMethods(object): def onCopyJSONCancelClicked(self, widget): """ - Se ha cancelado + The user changed its minds and pressed cancel """ textWindow = self.builder.get_object("TextWindow") textWindow.hide() def onExitMenuClicked(self, widget): """ - Se ha pulsado salir + Menu option Exit has been clicked """ - gtk.main_quit() - sys.exit(0) + self.quit() + + def onAboutMenuActivate(self, widget): + pass def onMainWindowDelete(self, widget, event): """ - Se ha destruido o mandado cerrar la ventana principal + Our MainWindow has been deleted or closed """ - gtk.main_quit() - sys.exit(0) + pass class LogicObject(object): @@ -246,21 +242,10 @@ class LogicObject(object): str(type(elems[key_val]))]) -class MainApp(object): - """ - Clase principal - """ - @staticmethod - def start(): - logicObject = LogicObject() - mainWindow = MainWindowMethods(logicObject) - - gtk.main() - - -# Ejecucion del programa principal - +# Main procedure if __name__ == "__main__": - app = MainApp() - app.start() + logicObject = LogicObject() + + mainWindow = MainWindowMethods(logicObject) + mainWindow.run(None) From ea6a221f6ceb250185440efd4e4f849fa50d9977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas=20Albadalejo?= Date: Mon, 14 Jul 2014 10:47:15 +0200 Subject: [PATCH 04/18] Added desktop entry file --- src/jsoninspector.desktop | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/jsoninspector.desktop diff --git a/src/jsoninspector.desktop b/src/jsoninspector.desktop new file mode 100644 index 0000000..5f94e0b --- /dev/null +++ b/src/jsoninspector.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=2.0 +Name[en_US]=JSON Inspector +GenericName=JSON Inspector +Exec=jsoninspector +Terminal=false +Icon[en_US]=/usr/share/icons/ +Type=Application +Categories=Application;Programming +Comment[en_US]=JSON Inspector From 1f36bcdbc1f79012aee9847d7f3c37e38e758358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas=20Albadalejo?= Date: Mon, 14 Jul 2014 12:30:46 +0200 Subject: [PATCH 05/18] Added internationalization support, updated the glade file to gtk 3.6 --- locale/es.mo | Bin 0 -> 1152 bytes locale/es.po | 76 ++++++++++++++++++++++ locale/messages.pot | 74 +++++++++++++++++++++ locale/po/es/LC_MESSAGES/jsoninspector.mo | Bin 0 -> 1152 bytes src/jsoninspector.glade | 16 +++-- src/jsoninspector.py | 35 ++++++++-- util/gen_pot.sh | 5 ++ 7 files changed, 192 insertions(+), 14 deletions(-) create mode 100644 locale/es.mo create mode 100644 locale/es.po create mode 100644 locale/messages.pot create mode 100644 locale/po/es/LC_MESSAGES/jsoninspector.mo create mode 100755 util/gen_pot.sh diff --git a/locale/es.mo b/locale/es.mo new file mode 100644 index 0000000000000000000000000000000000000000..9b6b1a199cc94ce3258f08ae08080bd5ec9bb089 GIT binary patch literal 1152 zcmZva&2H2%5XTLa0%`du2rBWVDHlLh%I>PDRZ0=dvMpQsv1*r!+saL*yQ$JRva>77 z8Sw(Z10ZqXg2V%G>VXp%4jhqq1tjkLodgOkR_vc=Job#8|F^RPuLas^^vme4&_~gS z4`D#-f({shHYNp6fzQE<;LE~(U#x!w2jKr)_`iT>V1EbCfj^4%!NWovg*{Yoq~Iv{ z0x?&>VXVJBBE)&{18DPp00_-6qwRx{$uytMsN5CoY64(Io3C3XaZh^wInwfJc&tdknCN!U-77K=&-9MGm#+mv>h{3uK|l+?k5SXTMAC=1zV+U0;Tq|}#D z805+RHOCyWl5m`#k|H^6h7pU_PQqecMm-koIqPUY-E*O#>%p@%8AmcyJR|H;NI_bjN4KkIn9-pThlC4Y;qsSls&4H%9Czs$}LY) zx#CsIUdf{cWp>|DP3lM)s`a=p4c*af zIK3AsUq)SJ(!1CecY3nJZj0r%M{9|UL(~1^_K1zM)L5$TU9db+a%u{{C`LZKi%0gI zZY7Zn;~Db1QX|Feqy!n%T+> z<dFPNUqX15 zjtmq9Yyu{Z$o?al$b=&{nT!lmSCU`EWwM004tg_Dsr>v{QGfRhly$&{tg0J2)KHV( eWo;AxU0o|ol$966-L7iC8}^l`ws(4g6u$r#y%Zz> literal 0 HcmV?d00001 diff --git a/locale/es.po b/locale/es.po new file mode 100644 index 0000000..4f43435 --- /dev/null +++ b/locale/es.po @@ -0,0 +1,76 @@ +# Spanish translations for PACKAGE package +# Traducciones al español para el paquete PACKAGE. +# Copyright (C) 2014 THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# José Carlos Cuevas , 2014. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-07-14 12:21+0200\n" +"PO-Revision-Date: 2014-07-14 12:24+0100\n" +"Last-Translator: José Carlos Cuevas \n" +"Language-Team: Spanish\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.5.4\n" + +#: jsoninspector.py:81 +msgid "Open JSON text file" +msgstr "Abrir fichero de texto JSON" + +#: jsoninspector.py:104 +msgid "No JSON loaded." +msgstr "No se ha cargado JSON." + +#: jsoninspector.py:152 +msgid "Loaded from the clipboard." +msgstr "Cargado desde el portapapeles." + +#: jsoninspector.py:194 +msgid "Not valid JSON!\n" +msgstr "JSON no válido!\n" + +#: jsoninspector.py:210 +msgid "Not valid JSON" +msgstr "JSON no válido" + +#: jsoninspector.glade.h:1 +msgid "Enter JSON Text" +msgstr "Introduzca texto JSON" + +#: jsoninspector.glade.h:2 +msgid "JSON Inspector" +msgstr "JSON Inspector" + +#: jsoninspector.glade.h:3 +msgid "_File" +msgstr "_Archivo" + +#: jsoninspector.glade.h:4 +msgid "Cop_y JSON" +msgstr "Cop_iar JSON" + +#: jsoninspector.glade.h:5 +msgid "_Help" +msgstr "A_yuda" + +#: jsoninspector.glade.h:6 +msgid "Node" +msgstr "Nodo" + +#: jsoninspector.glade.h:7 +msgid "Value" +msgstr "Valor" + +#: jsoninspector.glade.h:8 +msgid "Type" +msgstr "Tipo" + +#: jsoninspector.glade.h:9 +msgid "No JSON loaded" +msgstr "No se ha cargado JSON" diff --git a/locale/messages.pot b/locale/messages.pot new file mode 100644 index 0000000..a26cba8 --- /dev/null +++ b/locale/messages.pot @@ -0,0 +1,74 @@ +# 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 , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-07-14 12:21+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: jsoninspector.py:81 +msgid "Open JSON text file" +msgstr "" + +#: jsoninspector.py:104 +msgid "No JSON loaded." +msgstr "" + +#: jsoninspector.py:152 +msgid "Loaded from the clipboard." +msgstr "" + +#: jsoninspector.py:194 +msgid "Not valid JSON!\n" +msgstr "" + +#: jsoninspector.py:210 +msgid "Not valid JSON" +msgstr "" + +#: jsoninspector.glade.h:1 +msgid "Enter JSON Text" +msgstr "" + +#: jsoninspector.glade.h:2 +msgid "JSON Inspector" +msgstr "" + +#: jsoninspector.glade.h:3 +msgid "_File" +msgstr "" + +#: jsoninspector.glade.h:4 +msgid "Cop_y JSON" +msgstr "" + +#: jsoninspector.glade.h:5 +msgid "_Help" +msgstr "" + +#: jsoninspector.glade.h:6 +msgid "Node" +msgstr "" + +#: jsoninspector.glade.h:7 +msgid "Value" +msgstr "" + +#: jsoninspector.glade.h:8 +msgid "Type" +msgstr "" + +#: jsoninspector.glade.h:9 +msgid "No JSON loaded" +msgstr "" diff --git a/locale/po/es/LC_MESSAGES/jsoninspector.mo b/locale/po/es/LC_MESSAGES/jsoninspector.mo new file mode 100644 index 0000000000000000000000000000000000000000..9b6b1a199cc94ce3258f08ae08080bd5ec9bb089 GIT binary patch literal 1152 zcmZva&2H2%5XTLa0%`du2rBWVDHlLh%I>PDRZ0=dvMpQsv1*r!+saL*yQ$JRva>77 z8Sw(Z10ZqXg2V%G>VXp%4jhqq1tjkLodgOkR_vc=Job#8|F^RPuLas^^vme4&_~gS z4`D#-f({shHYNp6fzQE<;LE~(U#x!w2jKr)_`iT>V1EbCfj^4%!NWovg*{Yoq~Iv{ z0x?&>VXVJBBE)&{18DPp00_-6qwRx{$uytMsN5CoY64(Io3C3XaZh^wInwfJc&tdknCN!U-77K=&-9MGm#+mv>h{3uK|l+?k5SXTMAC=1zV+U0;Tq|}#D z805+RHOCyWl5m`#k|H^6h7pU_PQqecMm-koIqPUY-E*O#>%p@%8AmcyJR|H;NI_bjN4KkIn9-pThlC4Y;qsSls&4H%9Czs$}LY) zx#CsIUdf{cWp>|DP3lM)s`a=p4c*af zIK3AsUq)SJ(!1CecY3nJZj0r%M{9|UL(~1^_K1zM)L5$TU9db+a%u{{C`LZKi%0gI zZY7Zn;~Db1QX|Feqy!n%T+> z<dFPNUqX15 zjtmq9Yyu{Z$o?al$b=&{nT!lmSCU`EWwM004tg_Dsr>v{QGfRhly$&{tg0J2)KHV( eWo;AxU0o|ol$966-L7iC8}^l`ws(4g6u$r#y%Zz> literal 0 HcmV?d00001 diff --git a/src/jsoninspector.glade b/src/jsoninspector.glade index 69a574f..1d71168 100644 --- a/src/jsoninspector.glade +++ b/src/jsoninspector.glade @@ -1,10 +1,10 @@ - - + + False - Introducir texto JSON + Enter JSON Text True center 200 @@ -48,6 +48,7 @@ True True True + True @@ -65,6 +66,7 @@ True True True + True @@ -246,7 +248,7 @@ True - Nodo + Node True True 0 @@ -255,14 +257,14 @@ True - Valor + Value True True - Tipo + Type True @@ -284,7 +286,7 @@ True False - No hay JSON cargado + No JSON loaded diff --git a/src/jsoninspector.py b/src/jsoninspector.py index fd027a4..efbc4d3 100644 --- a/src/jsoninspector.py +++ b/src/jsoninspector.py @@ -2,17 +2,37 @@ # -*- coding: utf-8 -*- from pkg_resources import resource_filename +from gi.repository import Gtk, Gdk, Gio import json -from gi.repository import Gtk, Gdk, Gio +# Internationalization support +import gettext +import locale + +APP = "jsoninspector" +DIR = "po" + +locale.setlocale(locale.LC_ALL, '') + +try: + gettext.bindtextdomain(APP, DIR) + locale.bindtextdomain(APP, DIR) + +except: + gettext.bindtextdomain(APP, "../locale/") + locale.bindtextdomain(APP, "../locale/") + +gettext.textdomain(APP) +_ = gettext.gettext + class MainWindowMethods(Gtk.Application): """ Main Application object with the main window signals """ def __init__(self, logic): - Gtk.Application.__init__(self, application_id = "apps.gnome.stevedore", + Gtk.Application.__init__(self, application_id = "apps.gnome.jsoninspector", flags = Gio.ApplicationFlags.FLAGS_NONE) # We store the reference to the app logic @@ -25,6 +45,7 @@ class MainWindowMethods(Gtk.Application): Loads the MainWindow widgets, shows it up and starts the main loop """ self.builder = Gtk.Builder() + self.builder.set_translation_domain(APP) self.builder.add_from_file(resource_filename(__name__,'jsoninspector.glade')) self.builder.connect_signals(self) @@ -57,7 +78,7 @@ class MainWindowMethods(Gtk.Application): User has pressed Open in the menu """ # Create the FileChooser Dialog - chooser = Gtk.FileChooserDialog("Open JSON text file", self.window, + chooser = Gtk.FileChooserDialog(_("Open JSON text file"), self.window, Gtk.FileChooserAction.OPEN, (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) @@ -80,7 +101,7 @@ class MainWindowMethods(Gtk.Application): else: - label.set_text("No hay JSON cargado") + label.set_text(_("No JSON loaded.")) # We finish the dialog chooser.destroy() @@ -128,7 +149,7 @@ class MainWindowMethods(Gtk.Application): if self.logicObj.loadJSONText(jsonText): status_label = self.builder.get_object("StatusLabel") - status_label.set_text("Cargado desde portapapeles.") + status_label.set_text(_("Loaded from the clipboard.")) self.logicObj.loadTree(treestore) def onCopyJSONCancelClicked(self, widget): @@ -170,7 +191,7 @@ class LogicObject(object): try: self.json = json.loads(f.read()) except ValueError: - print "JSON no válido!\n" + print _("Not valid JSON!\n") self.json = None f.close() @@ -186,7 +207,7 @@ class LogicObject(object): try: self.json = json.loads(text) except ValueError: - print "JSON no válido" + print _("Not valid JSON") self.json = None return False diff --git a/util/gen_pot.sh b/util/gen_pot.sh new file mode 100755 index 0000000..6bcfabf --- /dev/null +++ b/util/gen_pot.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +intltool-extract --type="gettext/glade" *.glade +xgettext -k_ -kN_ -o messages.pot *.py *.h + From a86164e9ba565026914c4f7bc852ef23258bfeeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas=20Albadalejo?= Date: Mon, 14 Jul 2014 12:55:35 +0200 Subject: [PATCH 06/18] Fixed troubles with glade file, added About dialog and started some translations. --- locale/es.mo | Bin 1152 -> 1184 bytes locale/es.po | 30 ++++---- locale/messages.pot | 22 +++--- locale/po/es/LC_MESSAGES/jsoninspector.mo | Bin 1152 -> 1184 bytes src/jsoninspector.glade | 83 +++++++++------------- 5 files changed, 65 insertions(+), 70 deletions(-) diff --git a/locale/es.mo b/locale/es.mo index 9b6b1a199cc94ce3258f08ae08080bd5ec9bb089..cda698625c031b0bb8fe2a1689e471a01646015a 100644 GIT binary patch delta 439 zcmXxgzb^xE7{~GFdp*_jqm-0{Mpzgc3+W$F27iGVrB0J}sx$~OoQ0uNlZ$~E#Dck- zx&MIJEe8GqR`1W{>q(w_eSh6O&wVeWhbZ}&32%&;CM)DUIj^zfL7d?Tp5quMIE6hd z;vFvFi=Pku{yT=OfBN-rRE=Mp#X^wnCstvg0xRA%?>b&{coQS`Uvp*?IK(o(p&IzY zCH(R0Wvb3Guc8{*;-Q9ju!MWKh;0llF}q@*26|Y)KIZWjsc)m?IQbuHW|Gudh0ZEe zM4?;a)hy^K`?e-(o`1=1L5*AepmXAm2Q61}L2Vd*1<%1~UGQFoI3~;F3t1$yhC+1UA?!lE^9XZr3`;O} z^TM5fLJxiA^dFdK-oO+1=gxgAav(C2aMwuWScDTURbZ9}^OVRbe22RD3s&K;)BoWa zbI4X*d_hs8H5kEbcn+J8Pg)cfOAltGC(@_!5eAUGNw0srj|`0(NjpIwYp5BGfW$)* wcutn+5GKmb%n|)^Xd+`9SMk(dn#S_OTI1c^_iy9x)SKV#-gR0J@sn5I0>XJAlmGw# diff --git a/locale/es.po b/locale/es.po index 4f43435..e5c7fb0 100644 --- a/locale/es.po +++ b/locale/es.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-14 12:21+0200\n" -"PO-Revision-Date: 2014-07-14 12:24+0100\n" +"POT-Creation-Date: 2014-07-14 12:52+0200\n" +"PO-Revision-Date: 2014-07-14 12:54+0100\n" "Last-Translator: José Carlos Cuevas \n" "Language-Team: Spanish\n" "Language: es\n" @@ -21,7 +21,7 @@ msgstr "" #: jsoninspector.py:81 msgid "Open JSON text file" -msgstr "Abrir fichero de texto JSON" +msgstr "Abrir archivo de texto JSON" #: jsoninspector.py:104 msgid "No JSON loaded." @@ -40,37 +40,41 @@ msgid "Not valid JSON" msgstr "JSON no válido" #: jsoninspector.glade.h:1 +msgid "About" +msgstr "Acerca de" + +#: jsoninspector.glade.h:2 msgid "Enter JSON Text" msgstr "Introduzca texto JSON" -#: jsoninspector.glade.h:2 +#: jsoninspector.glade.h:3 msgid "JSON Inspector" msgstr "JSON Inspector" -#: jsoninspector.glade.h:3 +#: jsoninspector.glade.h:4 msgid "_File" msgstr "_Archivo" -#: jsoninspector.glade.h:4 -msgid "Cop_y JSON" -msgstr "Cop_iar JSON" - #: jsoninspector.glade.h:5 +msgid "Cop_y JSON" +msgstr "_Copiar JSON" + +#: jsoninspector.glade.h:6 msgid "_Help" msgstr "A_yuda" -#: jsoninspector.glade.h:6 +#: jsoninspector.glade.h:7 msgid "Node" msgstr "Nodo" -#: jsoninspector.glade.h:7 +#: jsoninspector.glade.h:8 msgid "Value" msgstr "Valor" -#: jsoninspector.glade.h:8 +#: jsoninspector.glade.h:9 msgid "Type" msgstr "Tipo" -#: jsoninspector.glade.h:9 +#: jsoninspector.glade.h:10 msgid "No JSON loaded" msgstr "No se ha cargado JSON" diff --git a/locale/messages.pot b/locale/messages.pot index a26cba8..6b8f0a1 100644 --- a/locale/messages.pot +++ b/locale/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-14 12:21+0200\n" +"POT-Creation-Date: 2014-07-14 12:52+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -38,37 +38,41 @@ msgid "Not valid JSON" msgstr "" #: jsoninspector.glade.h:1 -msgid "Enter JSON Text" +msgid "About" msgstr "" #: jsoninspector.glade.h:2 -msgid "JSON Inspector" +msgid "Enter JSON Text" msgstr "" #: jsoninspector.glade.h:3 -msgid "_File" +msgid "JSON Inspector" msgstr "" #: jsoninspector.glade.h:4 -msgid "Cop_y JSON" +msgid "_File" msgstr "" #: jsoninspector.glade.h:5 -msgid "_Help" +msgid "Cop_y JSON" msgstr "" #: jsoninspector.glade.h:6 -msgid "Node" +msgid "_Help" msgstr "" #: jsoninspector.glade.h:7 -msgid "Value" +msgid "Node" msgstr "" #: jsoninspector.glade.h:8 -msgid "Type" +msgid "Value" msgstr "" #: jsoninspector.glade.h:9 +msgid "Type" +msgstr "" + +#: jsoninspector.glade.h:10 msgid "No JSON loaded" msgstr "" diff --git a/locale/po/es/LC_MESSAGES/jsoninspector.mo b/locale/po/es/LC_MESSAGES/jsoninspector.mo index 9b6b1a199cc94ce3258f08ae08080bd5ec9bb089..cda698625c031b0bb8fe2a1689e471a01646015a 100644 GIT binary patch delta 439 zcmXxgzb^xE7{~GFdp*_jqm-0{Mpzgc3+W$F27iGVrB0J}sx$~OoQ0uNlZ$~E#Dck- zx&MIJEe8GqR`1W{>q(w_eSh6O&wVeWhbZ}&32%&;CM)DUIj^zfL7d?Tp5quMIE6hd z;vFvFi=Pku{yT=OfBN-rRE=Mp#X^wnCstvg0xRA%?>b&{coQS`Uvp*?IK(o(p&IzY zCH(R0Wvb3Guc8{*;-Q9ju!MWKh;0llF}q@*26|Y)KIZWjsc)m?IQbuHW|Gudh0ZEe zM4?;a)hy^K`?e-(o`1=1L5*AepmXAm2Q61}L2Vd*1<%1~UGQFoI3~;F3t1$yhC+1UA?!lE^9XZr3`;O} z^TM5fLJxiA^dFdK-oO+1=gxgAav(C2aMwuWScDTURbZ9}^OVRbe22RD3s&K;)BoWa zbI4X*d_hs8H5kEbcn+J8Pg)cfOAltGC(@_!5eAUGNw0srj|`0(NjpIwYp5BGfW$)* wcutn+5GKmb%n|)^Xd+`9SMk(dn#S_OTI1c^_iy9x)SKV#-gR0J@sn5I0>XJAlmGw# diff --git a/src/jsoninspector.glade b/src/jsoninspector.glade index 1d71168..c67f838 100644 --- a/src/jsoninspector.glade +++ b/src/jsoninspector.glade @@ -2,6 +2,41 @@ + + False + popup + About + dialog + JSON Inspector + 2.0 + https://github.com/resetreboot/jsoninspector + https://github.com/resetreboot/jsoninspector + José Carlos Cuevas Albadalejo + José Carlos Cuevas Albadalejo + gpl-3-0 + + + False + vertical + 2 + + + False + end + + + False + True + end + 0 + + + + + + + + False Enter JSON Text @@ -307,52 +342,4 @@ - - True - True - adjustment1 - adjustment2 - - - 300 - 300 - True - True - adjustment1 - adjustment2 - treestore1 - False - treeviewcolumn1 - 0 - 1 - both - - - - - - True - Nodo - True - True - 0 - - - - - True - Valor - True - - - - - True - Tipo - True - - - - - From 5b76874a2c0e287cf3f55064cfcaba75b0cc6ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas=20Albadalejo?= Date: Mon, 14 Jul 2014 14:55:21 +0200 Subject: [PATCH 07/18] Added some hooks for the about dialog --- src/jsoninspector.glade | 2 ++ src/jsoninspector.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/jsoninspector.glade b/src/jsoninspector.glade index c67f838..6ed2bf5 100644 --- a/src/jsoninspector.glade +++ b/src/jsoninspector.glade @@ -14,6 +14,8 @@ José Carlos Cuevas Albadalejo José Carlos Cuevas Albadalejo gpl-3-0 + + False diff --git a/src/jsoninspector.py b/src/jsoninspector.py index efbc4d3..9ce1a65 100644 --- a/src/jsoninspector.py +++ b/src/jsoninspector.py @@ -154,7 +154,7 @@ class MainWindowMethods(Gtk.Application): def onCopyJSONCancelClicked(self, widget): """ - The user changed its minds and pressed cancel + The user changed its mind and pressed cancel """ textWindow = self.builder.get_object("TextWindow") textWindow.hide() From d7d13654c0fc09000fc7bac979f7b0820696c830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas=20Albadalejo?= Date: Mon, 14 Jul 2014 14:59:00 +0200 Subject: [PATCH 08/18] Added the about dialog hooks to the code --- src/jsoninspector.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/jsoninspector.py b/src/jsoninspector.py index 9ce1a65..5a24458 100644 --- a/src/jsoninspector.py +++ b/src/jsoninspector.py @@ -174,6 +174,14 @@ class MainWindowMethods(Gtk.Application): """ pass + def onAboutDialogClose(self, widget, event = None): + pass + + def onAboutDialogDeleteEvent(self, widget, evenr = None): + pass + + + class LogicObject(object): """ From d9accdd5110896c266da09dcfb5343614d099e60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas=20Albadalejo?= Date: Tue, 15 Jul 2014 09:24:59 +0200 Subject: [PATCH 09/18] Updated the installation file, we added the new About Dialog and fixed some problems with the testing of translations --- distribute_setup.py | 481 ---------------------------------------- ez_setup.py | 332 +++++++++++++++++++++++++++ setup.py | 18 +- src/jsoninspector.glade | 10 +- src/jsoninspector.py | 34 +-- 5 files changed, 370 insertions(+), 505 deletions(-) delete mode 100644 distribute_setup.py create mode 100644 ez_setup.py diff --git a/distribute_setup.py b/distribute_setup.py deleted file mode 100644 index 4f7bd08..0000000 --- a/distribute_setup.py +++ /dev/null @@ -1,481 +0,0 @@ -#!python -"""Bootstrap distribute installation - -If you want to use setuptools in your package's setup.py, just include this -file in the same directory with it, and add this to the top of your setup.py:: - - from distribute_setup import use_setuptools - use_setuptools() - -If you want to require a specific version of setuptools, set a download -mirror, or use an alternate download directory, you can do so by supplying -the appropriate options to ``use_setuptools()``. - -This file can also be run as a script to install or upgrade setuptools. -""" -import os -import sys -import time -import fnmatch -import tempfile -import tarfile -from distutils import log - -try: - from site import USER_SITE -except ImportError: - USER_SITE = None - -try: - import subprocess - - def _python_cmd(*args): - args = (sys.executable,) + args - return subprocess.call(args) == 0 - -except ImportError: - # will be used for python 2.3 - def _python_cmd(*args): - args = (sys.executable,) + args - # quoting arguments if windows - if sys.platform == 'win32': - def quote(arg): - if ' ' in arg: - return '"%s"' % arg - return arg - args = [quote(arg) for arg in args] - return os.spawnl(os.P_WAIT, sys.executable, *args) == 0 - -DEFAULT_VERSION = "0.6.12" -DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/" -SETUPTOOLS_FAKED_VERSION = "0.6c11" - -SETUPTOOLS_PKG_INFO = """\ -Metadata-Version: 1.0 -Name: setuptools -Version: %s -Summary: xxxx -Home-page: xxx -Author: xxx -Author-email: xxx -License: xxx -Description: xxx -""" % SETUPTOOLS_FAKED_VERSION - - -def _install(tarball): - # extracting the tarball - tmpdir = tempfile.mkdtemp() - log.warn('Extracting in %s', tmpdir) - old_wd = os.getcwd() - try: - os.chdir(tmpdir) - tar = tarfile.open(tarball) - _extractall(tar) - tar.close() - - # going in the directory - subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) - os.chdir(subdir) - log.warn('Now working in %s', subdir) - - # installing - log.warn('Installing Distribute') - if not _python_cmd('setup.py', 'install'): - log.warn('Something went wrong during the installation.') - log.warn('See the error message above.') - finally: - os.chdir(old_wd) - - -def _build_egg(egg, tarball, to_dir): - # extracting the tarball - tmpdir = tempfile.mkdtemp() - log.warn('Extracting in %s', tmpdir) - old_wd = os.getcwd() - try: - os.chdir(tmpdir) - tar = tarfile.open(tarball) - _extractall(tar) - tar.close() - - # going in the directory - subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) - os.chdir(subdir) - log.warn('Now working in %s', subdir) - - # building an egg - log.warn('Building a Distribute egg in %s', to_dir) - _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) - - finally: - os.chdir(old_wd) - # returning the result - log.warn(egg) - if not os.path.exists(egg): - raise IOError('Could not build the egg.') - - -def _do_download(version, download_base, to_dir, download_delay): - egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg' - % (version, sys.version_info[0], sys.version_info[1])) - if not os.path.exists(egg): - tarball = download_setuptools(version, download_base, - to_dir, download_delay) - _build_egg(egg, tarball, to_dir) - sys.path.insert(0, egg) - import setuptools - setuptools.bootstrap_install_from = egg - - -def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, - to_dir=os.curdir, download_delay=15, no_fake=True): - # making sure we use the absolute path - to_dir = os.path.abspath(to_dir) - was_imported = 'pkg_resources' in sys.modules or \ - 'setuptools' in sys.modules - try: - try: - import pkg_resources - if not hasattr(pkg_resources, '_distribute'): - if not no_fake: - _fake_setuptools() - raise ImportError - except ImportError: - return _do_download(version, download_base, to_dir, download_delay) - try: - pkg_resources.require("distribute>="+version) - return - except pkg_resources.VersionConflict: - e = sys.exc_info()[1] - if was_imported: - sys.stderr.write( - "The required version of distribute (>=%s) is not available,\n" - "and can't be installed while this script is running. Please\n" - "install a more recent version first, using\n" - "'easy_install -U distribute'." - "\n\n(Currently using %r)\n" % (version, e.args[0])) - sys.exit(2) - else: - del pkg_resources, sys.modules['pkg_resources'] # reload ok - return _do_download(version, download_base, to_dir, - download_delay) - except pkg_resources.DistributionNotFound: - return _do_download(version, download_base, to_dir, - download_delay) - finally: - if not no_fake: - _create_fake_setuptools_pkg_info(to_dir) - -def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, - to_dir=os.curdir, delay=15): - """Download distribute from a specified location and return its filename - - `version` should be a valid distribute version number that is available - as an egg for download under the `download_base` URL (which should end - with a '/'). `to_dir` is the directory where the egg will be downloaded. - `delay` is the number of seconds to pause before an actual download - attempt. - """ - # making sure we use the absolute path - to_dir = os.path.abspath(to_dir) - try: - from urllib.request import urlopen - except ImportError: - from urllib2 import urlopen - tgz_name = "distribute-%s.tar.gz" % version - url = download_base + tgz_name - saveto = os.path.join(to_dir, tgz_name) - src = dst = None - if not os.path.exists(saveto): # Avoid repeated downloads - try: - log.warn("Downloading %s", url) - src = urlopen(url) - # Read/write all in one block, so we don't create a corrupt file - # if the download is interrupted. - data = src.read() - dst = open(saveto, "wb") - dst.write(data) - finally: - if src: - src.close() - if dst: - dst.close() - return os.path.realpath(saveto) - -def _no_sandbox(function): - def __no_sandbox(*args, **kw): - try: - from setuptools.sandbox import DirectorySandbox - if not hasattr(DirectorySandbox, '_old'): - def violation(*args): - pass - DirectorySandbox._old = DirectorySandbox._violation - DirectorySandbox._violation = violation - patched = True - else: - patched = False - except ImportError: - patched = False - - try: - return function(*args, **kw) - finally: - if patched: - DirectorySandbox._violation = DirectorySandbox._old - del DirectorySandbox._old - - return __no_sandbox - -@_no_sandbox -def _patch_file(path, content): - """Will backup the file then patch it""" - existing_content = open(path).read() - if existing_content == content: - # already patched - log.warn('Already patched.') - return False - log.warn('Patching...') - _rename_path(path) - f = open(path, 'w') - try: - f.write(content) - finally: - f.close() - return True - - -def _same_content(path, content): - return open(path).read() == content - -def _rename_path(path): - new_name = path + '.OLD.%s' % time.time() - log.warn('Renaming %s into %s', path, new_name) - os.rename(path, new_name) - return new_name - -@_no_sandbox -def _remove_flat_installation(placeholder): - if not os.path.isdir(placeholder): - log.warn('Unkown installation at %s', placeholder) - return False - found = False - for file in os.listdir(placeholder): - if fnmatch.fnmatch(file, 'setuptools*.egg-info'): - found = True - break - if not found: - log.warn('Could not locate setuptools*.egg-info') - return - - log.warn('Removing elements out of the way...') - pkg_info = os.path.join(placeholder, file) - if os.path.isdir(pkg_info): - patched = _patch_egg_dir(pkg_info) - else: - patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO) - - if not patched: - log.warn('%s already patched.', pkg_info) - return False - # now let's move the files out of the way - for element in ('setuptools', 'pkg_resources.py', 'site.py'): - element = os.path.join(placeholder, element) - if os.path.exists(element): - _rename_path(element) - else: - log.warn('Could not find the %s element of the ' - 'Setuptools distribution', element) - return True - - -def _after_install(dist): - log.warn('After install bootstrap.') - placeholder = dist.get_command_obj('install').install_purelib - _create_fake_setuptools_pkg_info(placeholder) - -@_no_sandbox -def _create_fake_setuptools_pkg_info(placeholder): - if not placeholder or not os.path.exists(placeholder): - log.warn('Could not find the install location') - return - pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1]) - setuptools_file = 'setuptools-%s-py%s.egg-info' % \ - (SETUPTOOLS_FAKED_VERSION, pyver) - pkg_info = os.path.join(placeholder, setuptools_file) - if os.path.exists(pkg_info): - log.warn('%s already exists', pkg_info) - return - - log.warn('Creating %s', pkg_info) - f = open(pkg_info, 'w') - try: - f.write(SETUPTOOLS_PKG_INFO) - finally: - f.close() - - pth_file = os.path.join(placeholder, 'setuptools.pth') - log.warn('Creating %s', pth_file) - f = open(pth_file, 'w') - try: - f.write(os.path.join(os.curdir, setuptools_file)) - finally: - f.close() - -@_no_sandbox -def _patch_egg_dir(path): - # let's check if it's already patched - pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO') - if os.path.exists(pkg_info): - if _same_content(pkg_info, SETUPTOOLS_PKG_INFO): - log.warn('%s already patched.', pkg_info) - return False - _rename_path(path) - os.mkdir(path) - os.mkdir(os.path.join(path, 'EGG-INFO')) - pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO') - f = open(pkg_info, 'w') - try: - f.write(SETUPTOOLS_PKG_INFO) - finally: - f.close() - return True - - -def _before_install(): - log.warn('Before install bootstrap.') - _fake_setuptools() - - -def _under_prefix(location): - if 'install' not in sys.argv: - return True - args = sys.argv[sys.argv.index('install')+1:] - for index, arg in enumerate(args): - for option in ('--root', '--prefix'): - if arg.startswith('%s=' % option): - top_dir = arg.split('root=')[-1] - return location.startswith(top_dir) - elif arg == option: - if len(args) > index: - top_dir = args[index+1] - return location.startswith(top_dir) - elif option == '--user' and USER_SITE is not None: - return location.startswith(USER_SITE) - return True - - -def _fake_setuptools(): - log.warn('Scanning installed packages') - try: - import pkg_resources - except ImportError: - # we're cool - log.warn('Setuptools or Distribute does not seem to be installed.') - return - ws = pkg_resources.working_set - try: - setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools', - replacement=False)) - except TypeError: - # old distribute API - setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools')) - - if setuptools_dist is None: - log.warn('No setuptools distribution found') - return - # detecting if it was already faked - setuptools_location = setuptools_dist.location - log.warn('Setuptools installation detected at %s', setuptools_location) - - # if --root or --preix was provided, and if - # setuptools is not located in them, we don't patch it - if not _under_prefix(setuptools_location): - log.warn('Not patching, --root or --prefix is installing Distribute' - ' in another location') - return - - # let's see if its an egg - if not setuptools_location.endswith('.egg'): - log.warn('Non-egg installation') - res = _remove_flat_installation(setuptools_location) - if not res: - return - else: - log.warn('Egg installation') - pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO') - if (os.path.exists(pkg_info) and - _same_content(pkg_info, SETUPTOOLS_PKG_INFO)): - log.warn('Already patched.') - return - log.warn('Patching...') - # let's create a fake egg replacing setuptools one - res = _patch_egg_dir(setuptools_location) - if not res: - return - log.warn('Patched done.') - _relaunch() - - -def _relaunch(): - log.warn('Relaunching...') - # we have to relaunch the process - args = [sys.executable] + sys.argv - sys.exit(subprocess.call(args)) - - -def _extractall(self, path=".", members=None): - """Extract all members from the archive to the current working - directory and set owner, modification time and permissions on - directories afterwards. `path' specifies a different directory - to extract to. `members' is optional and must be a subset of the - list returned by getmembers(). - """ - import copy - import operator - from tarfile import ExtractError - directories = [] - - if members is None: - members = self - - for tarinfo in members: - if tarinfo.isdir(): - # Extract directories with a safe mode. - directories.append(tarinfo) - tarinfo = copy.copy(tarinfo) - tarinfo.mode = 448 # decimal for oct 0700 - self.extract(tarinfo, path) - - # Reverse sort directories. - if sys.version_info < (2, 4): - def sorter(dir1, dir2): - return cmp(dir1.name, dir2.name) - directories.sort(sorter) - directories.reverse() - else: - directories.sort(key=operator.attrgetter('name'), reverse=True) - - # Set correct owner, mtime and filemode on directories. - for tarinfo in directories: - dirpath = os.path.join(path, tarinfo.name) - try: - self.chown(tarinfo, dirpath) - self.utime(tarinfo, dirpath) - self.chmod(tarinfo, dirpath) - except ExtractError: - e = sys.exc_info()[1] - if self.errorlevel > 1: - raise - else: - self._dbg(1, "tarfile: %s" % e) - - -def main(argv, version=DEFAULT_VERSION): - """Install or upgrade setuptools and EasyInstall""" - tarball = download_setuptools() - _install(tarball) - - -if __name__ == '__main__': - main(sys.argv[1:]) diff --git a/ez_setup.py b/ez_setup.py new file mode 100644 index 0000000..f9be432 --- /dev/null +++ b/ez_setup.py @@ -0,0 +1,332 @@ +#!/usr/bin/env python +"""Bootstrap setuptools installation + +To use setuptools in your package's setup.py, include this +file in the same directory and add this to the top of your setup.py:: + + from ez_setup import use_setuptools + use_setuptools() + +To require a specific version of setuptools, set a download +mirror, or use an alternate download directory, simply supply +the appropriate options to ``use_setuptools()``. + +This file can also be run as a script to install or upgrade setuptools. +""" +import os +import shutil +import sys +import tempfile +import zipfile +import optparse +import subprocess +import platform +import textwrap +import contextlib + +from distutils import log + +try: + from urllib.request import urlopen +except ImportError: + from urllib2 import urlopen + +try: + from site import USER_SITE +except ImportError: + USER_SITE = None + +DEFAULT_VERSION = "5.4.1" +DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/" + +def _python_cmd(*args): + """ + Return True if the command succeeded. + """ + args = (sys.executable,) + args + return subprocess.call(args) == 0 + + +def _install(archive_filename, install_args=()): + with archive_context(archive_filename): + # installing + log.warn('Installing Setuptools') + if not _python_cmd('setup.py', 'install', *install_args): + log.warn('Something went wrong during the installation.') + log.warn('See the error message above.') + # exitcode will be 2 + return 2 + + +def _build_egg(egg, archive_filename, to_dir): + with archive_context(archive_filename): + # building an egg + log.warn('Building a Setuptools egg in %s', to_dir) + _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) + # returning the result + log.warn(egg) + if not os.path.exists(egg): + raise IOError('Could not build the egg.') + + +class ContextualZipFile(zipfile.ZipFile): + """ + Supplement ZipFile class to support context manager for Python 2.6 + """ + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.close() + + def __new__(cls, *args, **kwargs): + """ + Construct a ZipFile or ContextualZipFile as appropriate + """ + if hasattr(zipfile.ZipFile, '__exit__'): + return zipfile.ZipFile(*args, **kwargs) + return super(ContextualZipFile, cls).__new__(cls) + + +@contextlib.contextmanager +def archive_context(filename): + # extracting the archive + tmpdir = tempfile.mkdtemp() + log.warn('Extracting in %s', tmpdir) + old_wd = os.getcwd() + try: + os.chdir(tmpdir) + with ContextualZipFile(filename) as archive: + archive.extractall() + + # going in the directory + subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) + os.chdir(subdir) + log.warn('Now working in %s', subdir) + yield + + finally: + os.chdir(old_wd) + shutil.rmtree(tmpdir) + + +def _do_download(version, download_base, to_dir, download_delay): + egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg' + % (version, sys.version_info[0], sys.version_info[1])) + if not os.path.exists(egg): + archive = download_setuptools(version, download_base, + to_dir, download_delay) + _build_egg(egg, archive, to_dir) + sys.path.insert(0, egg) + + # Remove previously-imported pkg_resources if present (see + # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details). + if 'pkg_resources' in sys.modules: + del sys.modules['pkg_resources'] + + import setuptools + setuptools.bootstrap_install_from = egg + + +def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, + to_dir=os.curdir, download_delay=15): + to_dir = os.path.abspath(to_dir) + rep_modules = 'pkg_resources', 'setuptools' + imported = set(sys.modules).intersection(rep_modules) + try: + import pkg_resources + except ImportError: + return _do_download(version, download_base, to_dir, download_delay) + try: + pkg_resources.require("setuptools>=" + version) + return + except pkg_resources.DistributionNotFound: + return _do_download(version, download_base, to_dir, download_delay) + except pkg_resources.VersionConflict as VC_err: + if imported: + msg = textwrap.dedent(""" + The required version of setuptools (>={version}) is not available, + and can't be installed while this script is running. Please + install a more recent version first, using + 'easy_install -U setuptools'. + + (Currently using {VC_err.args[0]!r}) + """).format(VC_err=VC_err, version=version) + sys.stderr.write(msg) + sys.exit(2) + + # otherwise, reload ok + del pkg_resources, sys.modules['pkg_resources'] + return _do_download(version, download_base, to_dir, download_delay) + +def _clean_check(cmd, target): + """ + Run the command to download target. If the command fails, clean up before + re-raising the error. + """ + try: + subprocess.check_call(cmd) + except subprocess.CalledProcessError: + if os.access(target, os.F_OK): + os.unlink(target) + raise + +def download_file_powershell(url, target): + """ + Download the file at url to target using Powershell (which will validate + trust). Raise an exception if the command cannot complete. + """ + target = os.path.abspath(target) + ps_cmd = ( + "[System.Net.WebRequest]::DefaultWebProxy.Credentials = " + "[System.Net.CredentialCache]::DefaultCredentials; " + "(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)" + % vars() + ) + cmd = [ + 'powershell', + '-Command', + ps_cmd, + ] + _clean_check(cmd, target) + +def has_powershell(): + if platform.system() != 'Windows': + return False + cmd = ['powershell', '-Command', 'echo test'] + with open(os.path.devnull, 'wb') as devnull: + try: + subprocess.check_call(cmd, stdout=devnull, stderr=devnull) + except Exception: + return False + return True + +download_file_powershell.viable = has_powershell + +def download_file_curl(url, target): + cmd = ['curl', url, '--silent', '--output', target] + _clean_check(cmd, target) + +def has_curl(): + cmd = ['curl', '--version'] + with open(os.path.devnull, 'wb') as devnull: + try: + subprocess.check_call(cmd, stdout=devnull, stderr=devnull) + except Exception: + return False + return True + +download_file_curl.viable = has_curl + +def download_file_wget(url, target): + cmd = ['wget', url, '--quiet', '--output-document', target] + _clean_check(cmd, target) + +def has_wget(): + cmd = ['wget', '--version'] + with open(os.path.devnull, 'wb') as devnull: + try: + subprocess.check_call(cmd, stdout=devnull, stderr=devnull) + except Exception: + return False + return True + +download_file_wget.viable = has_wget + +def download_file_insecure(url, target): + """ + Use Python to download the file, even though it cannot authenticate the + connection. + """ + src = urlopen(url) + try: + # Read all the data in one block. + data = src.read() + finally: + src.close() + + # Write all the data in one block to avoid creating a partial file. + with open(target, "wb") as dst: + dst.write(data) + +download_file_insecure.viable = lambda: True + +def get_best_downloader(): + downloaders = ( + download_file_powershell, + download_file_curl, + download_file_wget, + download_file_insecure, + ) + viable_downloaders = (dl for dl in downloaders if dl.viable()) + return next(viable_downloaders, None) + +def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, + to_dir=os.curdir, delay=15, downloader_factory=get_best_downloader): + """ + Download setuptools from a specified location and return its filename + + `version` should be a valid setuptools version number that is available + as an egg for download under the `download_base` URL (which should end + with a '/'). `to_dir` is the directory where the egg will be downloaded. + `delay` is the number of seconds to pause before an actual download + attempt. + + ``downloader_factory`` should be a function taking no arguments and + returning a function for downloading a URL to a target. + """ + # making sure we use the absolute path + to_dir = os.path.abspath(to_dir) + zip_name = "setuptools-%s.zip" % version + url = download_base + zip_name + saveto = os.path.join(to_dir, zip_name) + if not os.path.exists(saveto): # Avoid repeated downloads + log.warn("Downloading %s", url) + downloader = downloader_factory() + downloader(url, saveto) + return os.path.realpath(saveto) + +def _build_install_args(options): + """ + Build the arguments to 'python setup.py install' on the setuptools package + """ + return ['--user'] if options.user_install else [] + +def _parse_args(): + """ + Parse the command line for options + """ + parser = optparse.OptionParser() + parser.add_option( + '--user', dest='user_install', action='store_true', default=False, + help='install in user site package (requires Python 2.6 or later)') + parser.add_option( + '--download-base', dest='download_base', metavar="URL", + default=DEFAULT_URL, + help='alternative URL from where to download the setuptools package') + parser.add_option( + '--insecure', dest='downloader_factory', action='store_const', + const=lambda: download_file_insecure, default=get_best_downloader, + help='Use internal, non-validating downloader' + ) + parser.add_option( + '--version', help="Specify which version to download", + default=DEFAULT_VERSION, + ) + options, args = parser.parse_args() + # positional arguments are ignored + return options + +def main(): + """Install or upgrade setuptools and EasyInstall""" + options = _parse_args() + archive = download_setuptools( + version=options.version, + download_base=options.download_base, + downloader_factory=options.downloader_factory, + ) + return _install(archive, _build_install_args(options)) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/setup.py b/setup.py index fb4bf7a..2f65984 100644 --- a/setup.py +++ b/setup.py @@ -1,17 +1,14 @@ -import distribute_setup -distribute_setup.use_setuptools() +import ez_setup, sys, shutils +ez_setup.use_setuptools() from setuptools import setup, find_packages + setup( name = "jsoninspector", - version = "1.5", + version = "2.0", packages = find_packages('src', exclude=['distribute_setup']), - scripts = ['src/jsoninspector.py'], - entry_points = { - 'gui_scripts': [ - 'jsoninspector = jsoninspector:MainApp.start', - ] - }, + scripts = ['jsoninspector.py'], + include_package_data = True, package_data = { # If any package contains *.glade files, include them: '': ['*.glade'], @@ -25,3 +22,6 @@ setup( keywords = "json inspect gtk gnome", url = "https://github.com/resetreboot/jsoninspector", # project home page, if any ) + +# if sys.path != 'win32' and sys.path != 'darwin': +# shutils.copytree('locale/po/', '/usr/share/locale/') diff --git a/src/jsoninspector.glade b/src/jsoninspector.glade index 6ed2bf5..6c34472 100644 --- a/src/jsoninspector.glade +++ b/src/jsoninspector.glade @@ -4,11 +4,17 @@ False - popup About + False + True + center-on-parent + True dialog + False + center + False JSON Inspector - 2.0 + v2.0 https://github.com/resetreboot/jsoninspector https://github.com/resetreboot/jsoninspector José Carlos Cuevas Albadalejo diff --git a/src/jsoninspector.py b/src/jsoninspector.py index 5a24458..d52432c 100644 --- a/src/jsoninspector.py +++ b/src/jsoninspector.py @@ -2,26 +2,31 @@ # -*- coding: utf-8 -*- from pkg_resources import resource_filename -from gi.repository import Gtk, Gdk, Gio +from gi.repository import Gtk, Gio -import json +import json, sys, os.path # Internationalization support import gettext import locale APP = "jsoninspector" -DIR = "po" + +if os.path.exists('../locale/po'): + # We're in the development tree + DIR = "../locale/po/" + +elif sys.platform != 'win32' and sys.platform != 'darwin': + DIR = "/usr/share/locale/" + +else: + DIR = "po" locale.setlocale(locale.LC_ALL, '') -try: - gettext.bindtextdomain(APP, DIR) - locale.bindtextdomain(APP, DIR) +gettext.bindtextdomain(APP, DIR) +locale.bindtextdomain(APP, DIR) -except: - gettext.bindtextdomain(APP, "../locale/") - locale.bindtextdomain(APP, "../locale/") gettext.textdomain(APP) _ = gettext.gettext @@ -166,7 +171,12 @@ class MainWindowMethods(Gtk.Application): self.quit() def onAboutMenuActivate(self, widget): - pass + """ + About option clicked + """ + about_dialog = self.builder.get_object("AboutDialog") + about_dialog.run() + about_dialog.hide() def onMainWindowDelete(self, widget, event): """ @@ -177,12 +187,10 @@ class MainWindowMethods(Gtk.Application): def onAboutDialogClose(self, widget, event = None): pass - def onAboutDialogDeleteEvent(self, widget, evenr = None): + def onAboutDialogDeleteEvent(self, widget, event = None): pass - - class LogicObject(object): """ Esta clase define un objeto que mantiene la lógica interna del programa y From f13c0302a344d0d204bad1f9ae2173b874b41b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas=20Albadalejo?= Date: Tue, 15 Jul 2014 11:39:52 +0200 Subject: [PATCH 10/18] Trying to get icons and such working. Setup is almost there. --- .gitignore | 2 + {src => res}/jsoninspector.desktop | 4 +- {src => res}/jsoninspector.glade | 3 +- res/jsoninspector128x128.png | Bin 0 -> 18648 bytes res/jsoninspector16x16.png | Bin 0 -> 1010 bytes res/jsoninspector32x32.png | Bin 0 -> 2601 bytes res/jsoninspector64x64.png | Bin 0 -> 6990 bytes setup.py | 57 +++++++++++++++++++++++++---- src/jsoninspector.py | 8 ++-- 9 files changed, 61 insertions(+), 13 deletions(-) rename {src => res}/jsoninspector.desktop (82%) rename {src => res}/jsoninspector.glade (99%) create mode 100644 res/jsoninspector128x128.png create mode 100644 res/jsoninspector16x16.png create mode 100644 res/jsoninspector32x32.png create mode 100644 res/jsoninspector64x64.png diff --git a/.gitignore b/.gitignore index d78e1b2..ce85a3d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ *.o *.so *.pyc +*.egg +*.egg-info # Packages # ############ diff --git a/src/jsoninspector.desktop b/res/jsoninspector.desktop similarity index 82% rename from src/jsoninspector.desktop rename to res/jsoninspector.desktop index 5f94e0b..2b6e906 100644 --- a/src/jsoninspector.desktop +++ b/res/jsoninspector.desktop @@ -3,9 +3,9 @@ Encoding=UTF-8 Version=2.0 Name[en_US]=JSON Inspector GenericName=JSON Inspector -Exec=jsoninspector +Exec=jsoninspector.py Terminal=false -Icon[en_US]=/usr/share/icons/ +Icon[en_US]=/usr/local/share/jsoninspector/ Type=Application Categories=Application;Programming Comment[en_US]=JSON Inspector diff --git a/src/jsoninspector.glade b/res/jsoninspector.glade similarity index 99% rename from src/jsoninspector.glade rename to res/jsoninspector.glade index 6c34472..9970013 100644 --- a/src/jsoninspector.glade +++ b/res/jsoninspector.glade @@ -19,6 +19,7 @@ https://github.com/resetreboot/jsoninspector José Carlos Cuevas Albadalejo José Carlos Cuevas Albadalejo + jsoninspector gpl-3-0 @@ -173,6 +174,7 @@ False JSON Inspector center + jsoninspector.png @@ -284,7 +286,6 @@ treeviewcolumn1 0 1 - both diff --git a/res/jsoninspector128x128.png b/res/jsoninspector128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..b7b8e2985b03d15dfd2ece96f01f6d939189dd57 GIT binary patch literal 18648 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 Ef&r(9cK`qY literal 0 HcmV?d00001 diff --git a/res/jsoninspector16x16.png b/res/jsoninspector16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..b1247fddd16d47ceaea2e35110772c01b8556d95 GIT binary patch literal 1010 zcmV@DOFZ$L&16h z2?tG#NsU~L2?t{g9@>ONOz_~%*u;y<&5KqK^g?0L;xjQ1+F^q0J}BiPTP7%4}|+|Fgo{(jTa*%HZIjJ2W(u zN+c2&c`7yk!9FX}dXJNn{z|l!k|AS7B}#69p7>cF{Win={JdlsMtgU6w=*y>(Am<` zvH~Cj2w(l3Lb=kP+&g6L?;Un__s|daDG8l?T^pCKbP)&y$Y!&oQYmR-Vq$rHef>=U zDVNL1pMQ7nq^`Y_CtDhtmchtpacqH7A43W@(q7pl|M($3pAS`4@%elxio*E#xW`i{ z6v~yzGjhhPl1^t32U+~G!^=1N@JCy*oDgR`Wn_JiKp=qE>!nyMa&&aW@$vC(kEUs# zHMMn+EuLT=9uTirxq71?M~U#4_saKK`MK>ES#5WWeS*Otp-_l?K93NBWHRZMB}t;B zrLgij{F1}vS6)Rgd(ms++xxl{@}5+V`?@Zy)z#Gz4u?@y70a?PO_N+Mha3n5*m$(a z^WiENJG&^9JRFw1Jj{k3E7cNTU%ngbIdlKpXf%qds`&kWOw+_L40K(mCL9h^TU*Q4 z(gN=$I>}bkgdHE}o4voj*Yd^9rf8_cDL;GRT+AeI1<*7NUDvTJ3){AlRaGS%4igLp z5ZOK0UBbUL!yB=q*JGYv=3FU>Q+wEa{gQ$jQkb2cMF@dqSyU<&bnxh0t!4_qlpBn~mp8ktN6+qSVR3&(NrjEs!jN~hDc!C(+smMIpC zSe8XDm*eM!%~7-ZQtP?q70K(9INQ=eW_yR<|Jfa_9!0szL8ghf-~W=-uFd-Tx<>{W9v;3HkH-mxLZ^B{2!s&m zy3UXHO@6w&jVmQ-h!y$t!`GOan);}rp}~>pz0=dvGmDFhtgfyigupb-)3vLW zV}AImk!m?c^Z5_%ywLN`#{jslds-occX@evVQg&7NhA_(TU(nOi^beXB;rOQ5%=a> gebxNxH_Fq@zX(0bB+<+co&W#<07*qoM6N<$g0+X*5&!@I literal 0 HcmV?d00001 diff --git a/res/jsoninspector32x32.png b/res/jsoninspector32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..cc768a52900c9f8d4da6a29313e7bb26c3d5fcbb GIT binary patch literal 2601 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 LNkvXXu0mjfB8;D6 literal 0 HcmV?d00001 diff --git a/res/jsoninspector64x64.png b/res/jsoninspector64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..d002999b3f6fb357f08d4ced10fd5d02061f4a9d GIT binary patch literal 6990 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 literal 0 HcmV?d00001 diff --git a/setup.py b/setup.py index 2f65984..fb4748e 100644 --- a/setup.py +++ b/setup.py @@ -1,17 +1,62 @@ -import ez_setup, sys, shutils +import ez_setup, sys, shutil, os ez_setup.use_setuptools() from setuptools import setup, find_packages +from setuptools.command.install import install +from distutils.dir_util import copy_tree + +class CustomInstall(install): + """ + We subclass the install command to add some more mojo + """ + def run(self): + install.run(self) # Do the usual setuptools magic + # Now we do our own magic + if sys.platform != 'win32' and sys.platform != 'darwin': + try: + os.mkdir("/usr/local/share/jsoninspector", mode = 0755) + + except: + print "Warning: Couldn't create /usr/local/share/jsoninspector" + + # Copy the translations + try: + copy_tree('locale/po/', '/usr/share/locale/') + + except: + print "Warning: error copying translation files." + + # Copy the icons + for icon_size in ['16x16', '32x32', '64x64', '128x128']: + try: + shutil.copyfile('res/jsoninspector' + icon_size + ".png", + '/usr/share/icons/hicolor/' + icon_size + "/apps/jsoninspector.png") + + except: + print "Warning: error copying icon {size}.".format(icon_size) + + try: + shutil.copyfile('res/jsoninspector.glade', '/usr/local/share/jsoninspector/jsoninspector.desktop') + + except: + print "Warning: error copyin .glade file." + + try: + shutil.copyfile('res/jsoninspector.desktop', '/usr/share/applications/jsoninspector.desktop') + + except: + print "Warning: error copying .desktop entry." + setup( name = "jsoninspector", version = "2.0", - packages = find_packages('src', exclude=['distribute_setup']), - scripts = ['jsoninspector.py'], + packages = find_packages('src', exclude=['ez_setup']), + scripts = ['src/jsoninspector.py'], include_package_data = True, package_data = { # If any package contains *.glade files, include them: - '': ['*.glade'], + 'src': ['*.glade'], }, # metadata for upload to PyPI @@ -21,7 +66,5 @@ setup( license = "GPLv3", keywords = "json inspect gtk gnome", url = "https://github.com/resetreboot/jsoninspector", # project home page, if any + cmdclass = { 'install' : CustomInstall } ) - -# if sys.path != 'win32' and sys.path != 'darwin': -# shutils.copytree('locale/po/', '/usr/share/locale/') diff --git a/src/jsoninspector.py b/src/jsoninspector.py index d52432c..42a5f23 100644 --- a/src/jsoninspector.py +++ b/src/jsoninspector.py @@ -1,7 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -from pkg_resources import resource_filename from gi.repository import Gtk, Gio import json, sys, os.path @@ -12,15 +11,18 @@ import locale APP = "jsoninspector" -if os.path.exists('../locale/po'): +if os.path.exists('../locale/po') and os.path.exists('../res'): # We're in the development tree DIR = "../locale/po/" + RESOURCES = "../res/" elif sys.platform != 'win32' and sys.platform != 'darwin': DIR = "/usr/share/locale/" + RESOURCES = "/usr/local/share/jsoninspector" else: DIR = "po" + RESOURCES = "res/" locale.setlocale(locale.LC_ALL, '') @@ -51,7 +53,7 @@ class MainWindowMethods(Gtk.Application): """ self.builder = Gtk.Builder() self.builder.set_translation_domain(APP) - self.builder.add_from_file(resource_filename(__name__,'jsoninspector.glade')) + self.builder.add_from_file(os.path.join(RESOURCES, 'jsoninspector.glade')) self.builder.connect_signals(self) # Prepares the renders of columns and assigns the values From 4495a27d6d5bd5eb919711df545b6e10ac8a5866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas=20Albadalejo?= Date: Tue, 15 Jul 2014 11:55:16 +0200 Subject: [PATCH 11/18] Added default icon size and improved a bit more the setup.py installation file --- res/jsoninspector.glade | 1 - res/jsoninspector48x48.png | Bin 0 -> 5462 bytes setup.py | 14 ++++++++++---- 3 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 res/jsoninspector48x48.png diff --git a/res/jsoninspector.glade b/res/jsoninspector.glade index 9970013..57b7344 100644 --- a/res/jsoninspector.glade +++ b/res/jsoninspector.glade @@ -174,7 +174,6 @@ False JSON Inspector center - jsoninspector.png diff --git a/res/jsoninspector48x48.png b/res/jsoninspector48x48.png new file mode 100644 index 0000000000000000000000000000000000000000..f7f74f2652ea5b42518acfc88a812102475de371 GIT binary patch literal 5462 zcmV-c6{+fpP)KU`2q71wb4$4iZ?16euzxEvaNvq%E>sw!k_}Eipw=kw8KqA>krGAPX!25+Fcadt%Rb&6}B? z?w-ycZ|C9dE=k!_HPy4PYTx_5{(Zl%zn&R_UveBda*PZN?9l*l_UPf|wTP|vBl;<3 z7=2pnPY5B>oCmjv);CMDQ)|u-ogH}dt;1w=bd*p^VHgH-xg0ib+^Bc#*iq^3?mp1h z*EinY-agD2JKWjXIZ6nb1As$^4q^B1-AJWUD3{B~<#N9a9>_<4#=yWH96xfzx_@9G zJag2olZ};wzj_7)z$S+wrw8*fJ&vpve~SvR;$Ql zGXF9HP2lPM0|U|VqeuTsN!xqhCaYiDc~@aa&cg0evD7j-TV!)(7p01aiszwRc2O!< zQJI~FEKT8|O>59$N<9C^UqvpP1prV=5mzOj&+Fa0cVqkZ?Ie@QprfNhu3fwKOlN23 zZ=0rhd3JV|6$%AaDwUAW=l}Tx-a2v&4kD5^6e~&N?{A>hDz4dZ?x9xo&0>vXY^tbc z%PuXu9;vtiDm4!^&xc#{;d>qe&Jn2yBiBAa|FSfmyssbs`RiXptyY6&Sq%cFX~HlJ zY}l{?_uY3NY}<}3%Tj%PedelFtG?6G(eX_}NZ@%MNhXu}qpGolz=Y{S+fQ^cI-ehnS>BR_Vn}^{r&xCdwY8yCxl!p zm&>$REJlSwVF?M+EFB6>_6+RRCypNdtIN7A-LvKHR6CKM9iJ`hnNp3Esx>sg*Xjg3 zKY;K12!a4%5FiXVq~M4+hn68k$g!cP3lHDjiEn@F&ydUI0caS8(I8?N26}pWuyNx? zSe6ATrOsxvT?Uy^v@@h`#; z{Dyp* >?+`4rOoO47`L}q7aap=&Y*1^HSW1i=227s297P`0s#+?crrv*#XsX+hE z)$}LMK9c5Ny*X7;bCnt^yFN;;HxE8Q&GS*K`3QJ`zz@JVhYUGX$e~0ChyWBC%u0Y* zHd=B8yngOF{`B+r;q6l=!8vaLkE_5K!`RpulF20U`8a3j>$jMW4SO8wvTHi|u8Jo9SWV2b&+qZ8+Yfbm<+baSi^;j6`{+d^5pDtEO z$@NiM1m5!l1YQ6h1PFNm$pfg6BMR%_2>@m%z$^#MOn{gUh+%`+Da;55sn#}RGZ~ns z3Cpq?;A4l1q6o!e5n&jDa}KRFsZ=WDjW^y{HZ(N!zqQuJ`1m->X0w=^n*&|8Y#DO7 zoB;qll+RtbF^ZXDRnJwuy2sZ%R9&y`Hogzv^T9bs$ODM5E}cjU5GgGgqcW#nGV1#D8itK3BoLBW<$e-&kRIngoNWD6atK~I_dddh-E|w0p}d1 zX+kLlAp`)B)2C0%6)RT!f!6vZLdYQJ97Zyk1OQw-ckUmi%T*y%WLEqDmD;?=`vH8v z34F*QLJq}4P_5A3-ij5=yOD2eho&YXYC=SS(hRQGm$U`xBLI_OLT=03^1Mw(?z|_(|#)Ddn%9IdcZ- zOa^Zs`vul_wW3lfBM9#3T?-DPBsQ$?MWMY7fzSw*u7i&VxB{4+!h~u$G3|lJ;FW?U zBpjh&iV)dC+CNiBI^q*|-K8wcY5-p>qvo)uwMH0*3uL5}A{Q@S#LUdhWAyat(_K?j zQ%EKf*+Z)OUS6i{IREd;a>=;|n7W%o*OsUac_2?h}n@CXPMjm%`;zg#h{ z=?FPN zi4!MmIz2soukZVylwz(_0-wBvf~660ACZ(mBw!gpZ*MOmWLg z=*8!I@4dH;-n@B}#^thY8#iwb(ZjLA6o_V+NM3SOrZ@NKgn32uUC!1}+Ii zL_iG(qh*v3kz^BiTM48>iYwpUI%@Xg%{_bduZI9Y2yvG!TZTj;u>`Q=IQ5ii7z-A% z#o)EpxOVLt=-Aj8aU7>%Uo9TI;)|!Enf3oHJ%>Crpv#UF_4xK%(gg@Wd2LPE&RwR>2YTI@r2brb` zLP%phXtvJyY$oA(9_ZqY1tA12`8;0x@oR9epU3a+-wviDAd0{hK^QTFQbTGoPlCdi zjB5p33Yb#r3?j{R2mPD>v2AG8L(a*s+`VGhjFKHRYX4ORtNTR&Fbz_39EUE}y=7UA zMy}Or2*a@1eU?ss>!_JUMs%4atGBg;7W+ckqqe$VgZ<({N`T|KX zDqzmfdK@F-G&(gkwM73hfw(t}wzf8mkB>J9EFK-lfl>++Q&V7+LPrsDsWe)c0V81| z(vezaIeD(bv!CeaE?(U4B8 zh>?*IluD%~vQbJkszC^Wv3c`mJvKH*nzwe%$*?)v`au8yC|4&Sr9vn|_`V;d5)OOx zGoLy7#U14RAH1WLII{cS8Z-R+vZVs883-(ZSb#R5VS(r=u&!Ujp2|!3zt=tq!%RTq zj*I}{gAYDf(zwmDABG_|Y}f$W-rjyTkw`Sk7YC`>6=ExkSH$_d22e_Z05A=M-MD@o zlarHQ{=sP|{?3!8x$orvG>X=%gnNLl0;oWv0?eP9c#xD}`I_C>yK)c$N!S(xWA#a# znVG@On>UxZPICpMl<4p8zeo#(!m&&y(*WOm%cI%Kq9|&Rh*!q>kxooZh~eSkC$!dC zd*?q20HDhHk~Lw^fK|BGRRC3J5|gNcpa?(FkM%3k*i<+VMbe-YP)gzK*|V6Nn_Dvb z&GNBr8a{Fe>$ z{&&tYpZ%UO8!?co2Il2N?nsI1F_2}CV^7!Hn4TQN;WytvwdyVb-duq&4E5&Co6*wJ z@(SIuWlMGK+O;#8RqPqFk2~@enbJ{PJJHTJj1mT^$3#!iHTu8iql(Z{LosTepr;0CVfs ztvl4!)z#2_GYPGAe1E1fHupm8(?SSLPEO**7hlYsKY#xAryqKtz<%YQ6aZk|SHEsf zwp2i?N+TxW0;G!i-$hi-KK!dsZNcOFD2mmEpyS_As{VDIot@acdGjw4iNq`=gvh?W zzJJ`dZ5s^3(2Ju5rL?}a6rw?**_Gl7#ge*p>z4Jx3ompYJb3V8xm6&o!62l@UD>M`*z_Z~ z=`09ZLC^}I1w`MuHnojQ$Nv(K{Kt0@iU>Tc_W%G$DUr|T!xvwCv9f>v{w_j@G~x#b zJv}{NdiddoPrdTWE7GVRjZj4hSx^B03&1yfbNm_S9B0m)(Wg$Gf@zw>U=$h};*mBC zJX%IbD*(*;Nla*Mg1|yZ9BjJ(*YJ(szKv)9>o^=UYRtTpQa-XP(|640otRV4%7T+CUj4kMa#kr&zd~<4Sc)66& zkwmd7@LPXgLrcX(7?tnz0lCu`7M+A^?!#aF{yyy7U_vT_RjYc)bI(0D(%0AbTbC|f zGCDds>I-IjdpoMtD!RJ56d^=!+_>>K9(?e@;cPYw!!R_Z6p2IvnM?*+>yMO8Y_A`c z+ohBcQi4F@#(0Q-{}(P=B>-}#nL%6tE;MRjWCl*pllaR&+KBGXZ1lDN^e5`E#~yoz z5Hj1>*C$J*(!xhfGcz;DWHQ9IZLPIlee&eVp`%BSW`iKmj4{F(gX_8&85vmuGOobK zZ9JMkhgR@>iSPZp7CibSg)lN8C^Q-xXaP_F(2k_K$%h69?ag0!@i!m+nDqm}h9J(^#!>m~QhS7-|%x_0x2AN`p1!;T;bh~qd~Yt5#nrk)=j9{%=~D_6J> z!VJTZ4h;?A(xpoadf}r$FSgrw1T=y`;;;X(TR;78@8b07 zNypj;bhT1MCfl+Eqw#SBIOiGw=H}+m+1dFWDdkVQy1HJvapT6?nVA`D*REYir_*|H za1g%llVYl%yzTnrf8Cm^t?@W+i z_BKfT&#vpTbULl(iG6B(eEjLz+1Uqbwc4tySFd7la1iIupU3Unx94XTOJv14Z>;W_ zOa@!GZpHTP+p%TKJ#X*bJMeNkm-{P&kYMK8>!!8#VIk+{&{`<`%imV{kj6$fn}zTD zc;ST?@a(hC#>;ztVq&5_ilQ$}Pfy=9K0dzj^5x6-o;Y!WzWeUG#P@w@t>YIx^wzCg zwc|JkySuyJ+rNK*v})C=H`lFOcfq#pIYNjJ0Pd~VknZ^`{<+8h2Sn-UMw$>u?f?J) M07*qoM6N<$f}o~SM*si- literal 0 HcmV?d00001 diff --git a/setup.py b/setup.py index fb4748e..72ee9ec 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -import ez_setup, sys, shutil, os +import ez_setup, sys, shutil, os, os.path ez_setup.use_setuptools() from setuptools import setup, find_packages @@ -14,20 +14,24 @@ class CustomInstall(install): # Now we do our own magic if sys.platform != 'win32' and sys.platform != 'darwin': try: + print "Creating shared directory..." os.mkdir("/usr/local/share/jsoninspector", mode = 0755) except: - print "Warning: Couldn't create /usr/local/share/jsoninspector" + if not os.path.exists("/usr/local/share/jsoninspector"): + print "Warning: Couldn't create /usr/local/share/jsoninspector" # Copy the translations try: + print "Installing translations..." copy_tree('locale/po/', '/usr/share/locale/') except: print "Warning: error copying translation files." # Copy the icons - for icon_size in ['16x16', '32x32', '64x64', '128x128']: + print "Installing application icons..." + for icon_size in ['16x16', '32x32', '48x48', '64x64', '128x128']: try: shutil.copyfile('res/jsoninspector' + icon_size + ".png", '/usr/share/icons/hicolor/' + icon_size + "/apps/jsoninspector.png") @@ -36,12 +40,14 @@ class CustomInstall(install): print "Warning: error copying icon {size}.".format(icon_size) try: + print "Installing glade file..." shutil.copyfile('res/jsoninspector.glade', '/usr/local/share/jsoninspector/jsoninspector.desktop') except: - print "Warning: error copyin .glade file." + print "Warning: error copying .glade file." try: + print "Installing desktop entry..." shutil.copyfile('res/jsoninspector.desktop', '/usr/share/applications/jsoninspector.desktop') except: From 3ded9098dd7c386d6f53df20a3ab9bd8fd3f962f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas=20Albadalejo?= Date: Tue, 15 Jul 2014 12:43:08 +0200 Subject: [PATCH 12/18] More changes to see if we can get our icon and our desktop entry to show up _somewhere_ --- res/jsoninspector.desktop | 10 ++++------ res/jsoninspector.glade | 4 +++- setup.py | 6 ++++++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/res/jsoninspector.desktop b/res/jsoninspector.desktop index 2b6e906..1ec3688 100644 --- a/res/jsoninspector.desktop +++ b/res/jsoninspector.desktop @@ -1,11 +1,9 @@ [Desktop Entry] -Encoding=UTF-8 -Version=2.0 -Name[en_US]=JSON Inspector +Name=JSON Inspector GenericName=JSON Inspector Exec=jsoninspector.py Terminal=false -Icon[en_US]=/usr/local/share/jsoninspector/ +Icon=/usr/local/share/jsoninspector/ Type=Application -Categories=Application;Programming -Comment[en_US]=JSON Inspector +Categories=Application;Programming; +Comment=JSON Inspector diff --git a/res/jsoninspector.glade b/res/jsoninspector.glade index 57b7344..5c56bde 100644 --- a/res/jsoninspector.glade +++ b/res/jsoninspector.glade @@ -9,7 +9,7 @@ True center-on-parent True - dialog + normal False center False @@ -53,6 +53,7 @@ center 200 180 + java-1.7.0 @@ -174,6 +175,7 @@ False JSON Inspector center + java-1.7.0 diff --git a/setup.py b/setup.py index 72ee9ec..ba49a27 100644 --- a/setup.py +++ b/setup.py @@ -39,6 +39,12 @@ class CustomInstall(install): except: print "Warning: error copying icon {size}.".format(icon_size) + try: + shutil.copyfile('res/jsoninspector48x48.png', '/usr/share/pixmaps/jsoninspector.png') + + except: + print "Warning: error copying icon to pixmaps directory." + try: print "Installing glade file..." shutil.copyfile('res/jsoninspector.glade', '/usr/local/share/jsoninspector/jsoninspector.desktop') From c100527f1ccfab5b34ce20702468e53f45f96edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas=20Albadalejo?= Date: Tue, 15 Jul 2014 13:53:28 +0200 Subject: [PATCH 13/18] Reordered the code and managed to get a clean install. We still lack proper icon installation. --- res/jsoninspector.desktop | 5 ++--- res/jsoninspector.glade | 1 + setup.py | 8 ++++---- src/__init__.py | 0 src/jsoninspector/__init__.py | 13 +++++++++++++ src/{ => jsoninspector}/jsoninspector.py | 8 +++++--- 6 files changed, 25 insertions(+), 10 deletions(-) delete mode 100644 src/__init__.py create mode 100644 src/jsoninspector/__init__.py rename src/{ => jsoninspector}/jsoninspector.py (98%) diff --git a/res/jsoninspector.desktop b/res/jsoninspector.desktop index 1ec3688..ccb9a03 100644 --- a/res/jsoninspector.desktop +++ b/res/jsoninspector.desktop @@ -1,9 +1,8 @@ [Desktop Entry] Name=JSON Inspector -GenericName=JSON Inspector Exec=jsoninspector.py Terminal=false -Icon=/usr/local/share/jsoninspector/ +Icon=jsoninspector Type=Application -Categories=Application;Programming; +Categories=GNOME;GTK;Development; Comment=JSON Inspector diff --git a/res/jsoninspector.glade b/res/jsoninspector.glade index 5c56bde..342ee57 100644 --- a/res/jsoninspector.glade +++ b/res/jsoninspector.glade @@ -9,6 +9,7 @@ True center-on-parent True + jsoninspector normal False center diff --git a/setup.py b/setup.py index ba49a27..2e205b7 100644 --- a/setup.py +++ b/setup.py @@ -59,13 +59,13 @@ class CustomInstall(install): except: print "Warning: error copying .desktop entry." - setup( - name = "jsoninspector", + name = "Jsoninspector", version = "2.0", - packages = find_packages('src', exclude=['ez_setup']), - scripts = ['src/jsoninspector.py'], + packages = find_packages('src', exclude = ['ez_setup']), + entry_points = { 'gui_scripts' : [ 'jsoninspector = jsoninspector:main_start' ] }, include_package_data = True, + package_dir = { '' : 'src' }, package_data = { # If any package contains *.glade files, include them: 'src': ['*.glade'], diff --git a/src/__init__.py b/src/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/jsoninspector/__init__.py b/src/jsoninspector/__init__.py new file mode 100644 index 0000000..6954003 --- /dev/null +++ b/src/jsoninspector/__init__.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from jsoninspector import LogicObject, MainWindowMethods + +def main_start(): + """ + So setuptools makes a nice startup script + """ + logicObject = LogicObject() + + mainWindow = MainWindowMethods(logicObject) + mainWindow.run(None) diff --git a/src/jsoninspector.py b/src/jsoninspector/jsoninspector.py similarity index 98% rename from src/jsoninspector.py rename to src/jsoninspector/jsoninspector.py index 42a5f23..2661a74 100644 --- a/src/jsoninspector.py +++ b/src/jsoninspector/jsoninspector.py @@ -11,10 +11,10 @@ import locale APP = "jsoninspector" -if os.path.exists('../locale/po') and os.path.exists('../res'): +if os.path.exists('../locale/po') and os.path.exists('../../res'): # We're in the development tree - DIR = "../locale/po/" - RESOURCES = "../res/" + DIR = "../../locale/po/" + RESOURCES = "../../res/" elif sys.platform != 'win32' and sys.platform != 'darwin': DIR = "/usr/share/locale/" @@ -281,6 +281,8 @@ class LogicObject(object): str(type(elems[key_val]))]) + + # Main procedure if __name__ == "__main__": From f34ebca209c624d33e13b376f1c23d67cdbdb461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas=20Albadalejo?= Date: Tue, 15 Jul 2014 14:36:52 +0200 Subject: [PATCH 14/18] Removed unnecesary parameters from the setup method --- setup.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/setup.py b/setup.py index 2e205b7..089886b 100644 --- a/setup.py +++ b/setup.py @@ -64,13 +64,7 @@ setup( version = "2.0", packages = find_packages('src', exclude = ['ez_setup']), entry_points = { 'gui_scripts' : [ 'jsoninspector = jsoninspector:main_start' ] }, - include_package_data = True, package_dir = { '' : 'src' }, - package_data = { - # If any package contains *.glade files, include them: - 'src': ['*.glade'], - }, - # metadata for upload to PyPI author = "Jose Carlos Cuevas", author_email = "reset.reboot@gmail.com", From 6007a1379bb0fd116fe0494c79faf67791239547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas=20Albadalejo?= Date: Wed, 16 Jul 2014 09:29:34 +0200 Subject: [PATCH 15/18] Changed the bitmap icons for svg and added a generator for the sizes. It's almost there, but we still don't have our icon to show our nor our desktop entry. --- .gitignore | 3 + res/get_sizes.sh | 15 + res/jsoninspector.desktop | 25 +- res/jsoninspector.glade | 4 +- res/jsoninspector.svg | 1004 ++++++++++++++++++++++++++++++++++ res/jsoninspector128x128.png | Bin 18648 -> 0 bytes res/jsoninspector16x16.png | Bin 1010 -> 0 bytes res/jsoninspector32x32.png | Bin 2601 -> 0 bytes res/jsoninspector48x48.png | Bin 5462 -> 0 bytes res/jsoninspector64x64.png | Bin 6990 -> 0 bytes setup.py | 33 +- 11 files changed, 1073 insertions(+), 11 deletions(-) create mode 100755 res/get_sizes.sh mode change 100644 => 100755 res/jsoninspector.desktop create mode 100644 res/jsoninspector.svg delete mode 100644 res/jsoninspector128x128.png delete mode 100644 res/jsoninspector16x16.png delete mode 100644 res/jsoninspector32x32.png delete mode 100644 res/jsoninspector48x48.png delete mode 100644 res/jsoninspector64x64.png diff --git a/.gitignore b/.gitignore index ce85a3d..7ddd909 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,9 @@ Thumbs.db # Vim swap files *.swp +# png files +*.png + # Virtualenv ignore bin/ lib/ diff --git a/res/get_sizes.sh b/res/get_sizes.sh new file mode 100755 index 0000000..2aa4c47 --- /dev/null +++ b/res/get_sizes.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +SIZES=( 16x16 22x22 24x24 32x32 36x36 48x48 64x64 72x72 96x96 128x128 192x192 256x256 ) + +# If we can't find the svg, cd into res, we're +# probably being called from the root of +# the source tree +if [ ! -e jsoninspector.svg ]; then + cd res +fi + +for s in "${SIZES[@]}"; do + echo "Creating $s image from svg" ; + convert -background none jsoninspector.svg -resize $s jsoninspector$s.png +done diff --git a/res/jsoninspector.desktop b/res/jsoninspector.desktop old mode 100644 new mode 100755 index ccb9a03..e2cd65d --- a/res/jsoninspector.desktop +++ b/res/jsoninspector.desktop @@ -1,8 +1,21 @@ [Desktop Entry] -Name=JSON Inspector -Exec=jsoninspector.py -Terminal=false +Categories=GTK;Development; +Comment[en_US]=A tool for examining JSON text easily +Comment=A tool for examining JSON text easily +Exec=jsoninspector +GenericName[en_US]=JSON Inspector +GenericName=JSON Inspector Icon=jsoninspector -Type=Application -Categories=GNOME;GTK;Development; -Comment=JSON Inspector +MimeType= +Name[en_US]=JSON Inspector +Name=JSON Inspector +Path= +StartupNotify=true +Terminal=false +TerminalOptions= +TryExec=/usr/bin/jsoninspector +Type=Application +X-DBUS-ServiceName= +X-DBUS-StartupType= +X-KDE-SubstituteUID=false +X-KDE-Username= diff --git a/res/jsoninspector.glade b/res/jsoninspector.glade index 342ee57..c4faca0 100644 --- a/res/jsoninspector.glade +++ b/res/jsoninspector.glade @@ -54,7 +54,7 @@ center 200 180 - java-1.7.0 + jsoninspector @@ -176,7 +176,7 @@ False JSON Inspector center - java-1.7.0 + jsoninspector diff --git a/res/jsoninspector.svg b/res/jsoninspector.svg new file mode 100644 index 0000000..3f66a09 --- /dev/null +++ b/res/jsoninspector.svg @@ -0,0 +1,1004 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/jsoninspector128x128.png b/res/jsoninspector128x128.png deleted file mode 100644 index b7b8e2985b03d15dfd2ece96f01f6d939189dd57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18648 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 Ef&r(9cK`qY diff --git a/res/jsoninspector16x16.png b/res/jsoninspector16x16.png deleted file mode 100644 index b1247fddd16d47ceaea2e35110772c01b8556d95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1010 zcmV@DOFZ$L&16h z2?tG#NsU~L2?t{g9@>ONOz_~%*u;y<&5KqK^g?0L;xjQ1+F^q0J}BiPTP7%4}|+|Fgo{(jTa*%HZIjJ2W(u zN+c2&c`7yk!9FX}dXJNn{z|l!k|AS7B}#69p7>cF{Win={JdlsMtgU6w=*y>(Am<` zvH~Cj2w(l3Lb=kP+&g6L?;Un__s|daDG8l?T^pCKbP)&y$Y!&oQYmR-Vq$rHef>=U zDVNL1pMQ7nq^`Y_CtDhtmchtpacqH7A43W@(q7pl|M($3pAS`4@%elxio*E#xW`i{ z6v~yzGjhhPl1^t32U+~G!^=1N@JCy*oDgR`Wn_JiKp=qE>!nyMa&&aW@$vC(kEUs# zHMMn+EuLT=9uTirxq71?M~U#4_saKK`MK>ES#5WWeS*Otp-_l?K93NBWHRZMB}t;B zrLgij{F1}vS6)Rgd(ms++xxl{@}5+V`?@Zy)z#Gz4u?@y70a?PO_N+Mha3n5*m$(a z^WiENJG&^9JRFw1Jj{k3E7cNTU%ngbIdlKpXf%qds`&kWOw+_L40K(mCL9h^TU*Q4 z(gN=$I>}bkgdHE}o4voj*Yd^9rf8_cDL;GRT+AeI1<*7NUDvTJ3){AlRaGS%4igLp z5ZOK0UBbUL!yB=q*JGYv=3FU>Q+wEa{gQ$jQkb2cMF@dqSyU<&bnxh0t!4_qlpBn~mp8ktN6+qSVR3&(NrjEs!jN~hDc!C(+smMIpC zSe8XDm*eM!%~7-ZQtP?q70K(9INQ=eW_yR<|Jfa_9!0szL8ghf-~W=-uFd-Tx<>{W9v;3HkH-mxLZ^B{2!s&m zy3UXHO@6w&jVmQ-h!y$t!`GOan);}rp}~>pz0=dvGmDFhtgfyigupb-)3vLW zV}AImk!m?c^Z5_%ywLN`#{jslds-occX@evVQg&7NhA_(TU(nOi^beXB;rOQ5%=a> gebxNxH_Fq@zX(0bB+<+co&W#<07*qoM6N<$g0+X*5&!@I diff --git a/res/jsoninspector32x32.png b/res/jsoninspector32x32.png deleted file mode 100644 index cc768a52900c9f8d4da6a29313e7bb26c3d5fcbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2601 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 LNkvXXu0mjfB8;D6 diff --git a/res/jsoninspector48x48.png b/res/jsoninspector48x48.png deleted file mode 100644 index f7f74f2652ea5b42518acfc88a812102475de371..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5462 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%0AbTbC|f zGCDds>I-IjdpoMtD!RJ56d^=!+_>>K9(?e@;cPYw!!R_Z6p2IvnM?*+>yMO8Y_A`c z+ohBcQi4F@#(0Q-{}(P=B>-}#nL%6tE;MRjWCl*pllaR&+KBGXZ1lDN^e5`E#~yoz z5Hj1>*C$J*(!xhfGcz;DWHQ9IZLPIlee&eVp`%BSW`iKmj4{F(gX_8&85vmuGOobK zZ9JMkhgR@>iSPZp7CibSg)lN8C^Q-xXaP_F(2k_K$%h69?ag0!@i!m+nDqm}h9J(^#!>m~QhS7-|%x_0x2AN`p1!;T;bh~qd~Yt5#nrk)=j9{%=~D_6J> z!VJTZ4h;?A(xpoadf}r$FSgrw1T=y`;;;X(TR;78@8b07 zNypj;bhT1MCfl+Eqw#SBIOiGw=H}+m+1dFWDdkVQy1HJvapT6?nVA`D*REYir_*|H za1g%llVYl%yzTnrf8Cm^t?@W+i z_BKfT&#vpTbULl(iG6B(eEjLz+1Uqbwc4tySFd7la1iIupU3Unx94XTOJv14Z>;W_ zOa@!GZpHTP+p%TKJ#X*bJMeNkm-{P&kYMK8>!!8#VIk+{&{`<`%imV{kj6$fn}zTD zc;ST?@a(hC#>;ztVq&5_ilQ$}Pfy=9K0dzj^5x6-o;Y!WzWeUG#P@w@t>YIx^wzCg zwc|JkySuyJ+rNK*v})C=H`lFOcfq#pIYNjJ0Pd~VknZ^`{<+8h2Sn-UMw$>u?f?J) M07*qoM6N<$f}o~SM*si- diff --git a/res/jsoninspector64x64.png b/res/jsoninspector64x64.png deleted file mode 100644 index d002999b3f6fb357f08d4ced10fd5d02061f4a9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6990 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 diff --git a/setup.py b/setup.py index 089886b..c792a54 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -import ez_setup, sys, shutil, os, os.path +import ez_setup, sys, shutil, os, os.path, subprocess ez_setup.use_setuptools() from setuptools import setup, find_packages @@ -28,16 +28,26 @@ class CustomInstall(install): except: print "Warning: error copying translation files." + + # Generate the icons + try: + result = subprocess.call(['./res/get_sizes.sh']) + + except: + result = 1 + + if result != 0: + print "Warning: Error generating icons" # Copy the icons print "Installing application icons..." - for icon_size in ['16x16', '32x32', '48x48', '64x64', '128x128']: + for icon_size in ['{sz}x{sz}'.format(sz = x) for x in ['16', '22','24', '32', '36', '48', '64', '72', '96', '128', '192']]: try: shutil.copyfile('res/jsoninspector' + icon_size + ".png", '/usr/share/icons/hicolor/' + icon_size + "/apps/jsoninspector.png") except: - print "Warning: error copying icon {size}.".format(icon_size) + print "Warning: error copying icon {size}.".format(size = icon_size) try: shutil.copyfile('res/jsoninspector48x48.png', '/usr/share/pixmaps/jsoninspector.png') @@ -45,6 +55,23 @@ class CustomInstall(install): except: print "Warning: error copying icon to pixmaps directory." + try: + shutil.copyfile('res/jsoninspector.svg' ,'/usr/share/icons/hicolor/scalable/apps/jsoninspector.svg') + + except: + print "Warning: error copying svg to scalable." + + print "Updating icon cache..." + + try: + result = subprocess.call(['/usr/bin/gtk-update-icon-cache /usr/share/icons/hicolor/']) + + except: + result = 1 + + if result != 0: + print "Warning: Error updating hicolor icon cache." + try: print "Installing glade file..." shutil.copyfile('res/jsoninspector.glade', '/usr/local/share/jsoninspector/jsoninspector.desktop') From f287a8c5e60d9956bf37bf177d782990b9e888de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas=20Albadalejo?= Date: Wed, 16 Jul 2014 10:26:42 +0200 Subject: [PATCH 16/18] Remade the .desktop file and now the icons and everything seems to work. About to make a new stable release. Now bug testing and verfying everything installs correctly. --- res/jsoninspector.desktop | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) mode change 100755 => 100644 res/jsoninspector.desktop diff --git a/res/jsoninspector.desktop b/res/jsoninspector.desktop old mode 100755 new mode 100644 index e2cd65d..60eff11 --- a/res/jsoninspector.desktop +++ b/res/jsoninspector.desktop @@ -1,21 +1,7 @@ [Desktop Entry] -Categories=GTK;Development; -Comment[en_US]=A tool for examining JSON text easily -Comment=A tool for examining JSON text easily -Exec=jsoninspector -GenericName[en_US]=JSON Inspector -GenericName=JSON Inspector -Icon=jsoninspector -MimeType= -Name[en_US]=JSON Inspector -Name=JSON Inspector -Path= -StartupNotify=true +Comment=Lightweight JSON utility to inspect JSON documents Terminal=false -TerminalOptions= -TryExec=/usr/bin/jsoninspector +Name=JSON Inspector +Exec=jsoninspector Type=Application -X-DBUS-ServiceName= -X-DBUS-StartupType= -X-KDE-SubstituteUID=false -X-KDE-Username= +Icon=jsoninspector From c017b293baa35ffdf4b42ccc78da394584f45b99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas?= Date: Wed, 16 Jul 2014 18:27:30 +0200 Subject: [PATCH 17/18] Fixed some problems with os.mkdir(). Installation on Linux should be OK now. --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index c792a54..12ca842 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ class CustomInstall(install): if sys.platform != 'win32' and sys.platform != 'darwin': try: print "Creating shared directory..." - os.mkdir("/usr/local/share/jsoninspector", mode = 0755) + os.mkdir("/usr/local/share/jsoninspector", 0755) except: if not os.path.exists("/usr/local/share/jsoninspector"): @@ -74,7 +74,7 @@ class CustomInstall(install): try: print "Installing glade file..." - shutil.copyfile('res/jsoninspector.glade', '/usr/local/share/jsoninspector/jsoninspector.desktop') + shutil.copyfile('res/jsoninspector.glade', '/usr/local/share/jsoninspector/jsoninspector.glade') except: print "Warning: error copying .glade file." From ab5f27786621089ef2cde663ed49e3166543e7ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Cuevas?= Date: Wed, 16 Jul 2014 18:41:57 +0200 Subject: [PATCH 18/18] Added initial code for a .exe builder for Windows. We mean to be multiplatform. Also, the code has not been run yet, be careful. --- setup_windows.py | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 setup_windows.py diff --git a/setup_windows.py b/setup_windows.py new file mode 100644 index 0000000..ef47cfd --- /dev/null +++ b/setup_windows.py @@ -0,0 +1,74 @@ +# This was borrowed from +# https://wiki.gnome.org/Projects/PyGObject#Building_on_Win32_with_cx_freeze +# Thanks to Gian Mario Tagliaretti + +import os, site, sys +from cx_Freeze import setup, Executable + +## Get the site-package folder, not everybody will install +## Python into C:\PythonXX +site_dir = site.getsitepackages()[1] +include_dll_path = os.path.join(site_dir, "gtk") + +## Collect the list of missing dll when cx_freeze builds the app +missing_dll = ['libgtk-3-0.dll', + 'libgdk-3-0.dll', + 'libatk-1.0-0.dll', + 'libcairo-gobject-2.dll', + 'libgdk_pixbuf-2.0-0.dll', + 'libjpeg-8.dll', + 'libpango-1.0-0.dll', + 'libpangocairo-1.0-0.dll', + 'libpangoft2-1.0-0.dll', + 'libpangowin32-1.0-0.dll', + 'libgnutls-26.dll', + 'libgcrypt-11.dll', + 'libp11-kit-0.dll' +] + +## We also need to add the glade folder, cx_freeze will walk +## into it and copy all the necessary files +glade_folder = 'res' + +## We need to add all the libraries too (for themes, etc..) +gtk_libs = ['etc', 'lib', 'share'] + +## Create the list of includes as cx_freeze likes +include_files = [] +for dll in missing_dll: + include_files.append((os.path.join(include_dll_path, dll), dll)) + +## Let's add glade folder and files +include_files.append((glade_folder, glade_folder)) + +## Let's add gtk libraries folders and files +for lib in gtk_libs: + include_files.append((os.path.join(include_dll_path, lib), lib)) + +base = None + +## Lets not open the console while running the app +if sys.platform == "win32": + base = "Win32GUI" + +executables = [ + Executable("jsoninspector.py", + base = base + ) +] + +buildOptions = dict( + compressed = False, + includes = ["gi"], + packages = ["gi"], + include_files = include_files + ) + +setup( + name = "JSONInspector", + author = "Jose Carlos Cuevas Albadalejo", + version = "2.0", + description = "JSON Inspection tool", + options = dict(build_exe = buildOptions), + executables = executables +)