diff --git a/CMakeLists.txt b/CMakeLists.txt index c939d51..d2ce076 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required(VERSION 3.3) -project(sysexxer-ng VERSION 0.1 LANGUAGES C CXX) +cmake_minimum_required(VERSION "3.3") +project(sysexxer-ng VERSION "1.0" LANGUAGES C CXX) list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") include(GNUInstallDirs) @@ -30,13 +30,15 @@ add_executable(sysexxer-ng "sources/config.cc" "sources/window.cxx" "sources/dnd_hold_browser.cc" + "sources/hyperlink_button.cc" "sources/system_exclusive.cc" "sources/sysex_send.cc" "sources/utility.cc" "sources/device/midi.cc" "sources/device/midi_apis.cc") target_compile_definitions(sysexxer-ng - PRIVATE "LOCALE_DIRECTORY=\"${CMAKE_INSTALL_FULL_LOCALEDIR}\"") + PRIVATE "LOCALE_DIRECTORY=\"${CMAKE_INSTALL_FULL_LOCALEDIR}\"" + PRIVATE "PROJECT_VERSION=\"${PROJECT_VERSION}\"") target_include_directories(sysexxer-ng PRIVATE "sources" "${FLTK_INCLUDE_DIR}") target_link_libraries(sysexxer-ng PRIVATE "${FLTK_LIBRARIES}") diff --git a/po/fr/sysexxer-ng.po b/po/fr/sysexxer-ng.po index a44e308..faf974e 100644 --- a/po/fr/sysexxer-ng.po +++ b/po/fr/sysexxer-ng.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-11-01 21:18+0100\n" +"POT-Creation-Date: 2019-03-14 18:58+0100\n" "PO-Revision-Date: 2018-10-28 13:44+0100\n" "Last-Translator: Jean Pierre Cimalando \n" "Language-Team: French\n" @@ -19,47 +19,52 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #. Fl_Button* btn_load -#: sources/window.cxx:96 +#: sources/window.cxx:104 msgid "@-> Send" msgstr "@-> Envoyer" -#: sources/window.cxx:129 +#: sources/window.cxx:137 msgid "@<- Receive" msgstr "@<- Recevoir" #. Fl_Box* lbl_midi_out #. Fl_Button* btn_midi_in -#: sources/window.cxx:206 sources/window.cxx:209 +#: sources/window.cxx:214 sources/window.cxx:217 msgid "@DnArrow" msgstr "" -#: sources/window.cxx:91 +#: sources/window.cxx:99 msgid "@fileopen Load" msgstr "@fileopen Charger" #. Fl_Button* btn_receive -#: sources/window.cxx:135 +#: sources/window.cxx:143 msgid "@filesave Save" msgstr "@filesave Sauvegarder" -#: sources/window_impl.cc:279 +#: sources/window_impl.cc:300 msgid "@undo Cancel" msgstr "@undo Annuler" -#: sources/window_impl.cc:179 +#. Fl_Group* tab_options +#: sources/window.cxx:230 +msgid "About" +msgstr "À propos" + +#: sources/window_impl.cc:200 msgid "Confirm overwrite" msgstr "Confirmer l'écrasement" -#: sources/window_impl.cc:223 +#: sources/window_impl.cc:244 msgid "Could not load the system-exclusive file." msgstr "Impossible de charger le fichier system-exclusive" -#: sources/window_impl.cc:240 sources/window_impl.cc:251 +#: sources/window_impl.cc:261 sources/window_impl.cc:272 msgid "Could not save the system-exclusive file." msgstr "Impossible de sauvegarder le fichier system-exclusive" -#: sources/window_impl.cc:222 sources/window_impl.cc:239 -#: sources/window_impl.cc:250 +#: sources/window_impl.cc:243 sources/window_impl.cc:260 +#: sources/window_impl.cc:271 msgid "Error" msgstr "Erreur" @@ -67,44 +72,44 @@ msgstr "Erreur" msgid "Invalid arguments" msgstr "Arguments invalides" -#: sources/window_impl.cc:132 +#: sources/window_impl.cc:153 msgid "Load" msgstr "Charger" #. Fl_Button* btn_midi_out -#: sources/window.cxx:212 +#: sources/window.cxx:220 msgid "MIDI input port" msgstr "Port d'entrée MIDI" -#: sources/window.cxx:168 +#: sources/window.cxx:176 msgid "MIDI interface" msgstr "Interface MIDI" #. Fl_Box* o -#: sources/window.cxx:216 +#: sources/window.cxx:224 msgid "MIDI output port" msgstr "Port de sortie MIDI" #. Fl_Box* o -#: sources/window.cxx:172 +#: sources/window.cxx:180 msgid "Max Transmission Rate" msgstr "Taux de transmission maximum" -#: sources/window_impl.cc:180 +#: sources/window_impl.cc:201 msgid "No" msgstr "Non" #. Fl_Group* tab_recv -#: sources/window.cxx:165 +#: sources/window.cxx:173 msgid "Options" msgstr "Options" #. Fl_Group* tab_send -#: sources/window.cxx:126 +#: sources/window.cxx:134 msgid "Receive" msgstr "Recevoir" -#: sources/window_impl.cc:109 +#: sources/window_impl.cc:111 msgid "" "Receiving instructions\n" "1. Connect the MIDI output to software input.\n" @@ -118,15 +123,15 @@ msgstr "" "3. Transmettre, et désactiver Recevoir quand c'est fini.\n" "4. Sauvegarder le fichier system-exclusive." -#: sources/window_impl.cc:165 +#: sources/window_impl.cc:186 msgid "Save" msgstr "Sauvegarder" -#: sources/window.cxx:88 +#: sources/window.cxx:96 msgid "Send" msgstr "Envoyer" -#: sources/window_impl.cc:104 +#: sources/window_impl.cc:106 msgid "" "Sending instructions\n" "1. Load a system-exclusive file.\n" @@ -155,7 +160,7 @@ msgstr "Entrée MIDI Sysexxer" msgid "Sysexxer MIDI out" msgstr "Sortie MIDI Sysexxer" -#: sources/main.cc:60 sources/window.cxx:80 +#: sources/main.cc:60 sources/window.cxx:88 msgid "Sysexxer NG" msgstr "Sysexxer NG" @@ -163,11 +168,32 @@ msgstr "Sysexxer NG" msgid "Sysexxer Out" msgstr "Sortie Sysexxer" -#: sources/window_impl.cc:167 +#: sources/window_impl.cc:132 +#, c-format +msgid "" +"Sysexxer-NG is a universal tool to exchange MIDI system-exclusive data.\n" +"\n" +"This free program is published under the terms of the Boost Software License " +"1.0.\n" +"\n" +"Version %s © 2018-2019\n" +"Author: Jean Pierre Cimalando\n" +"Contributor: Olivier Humbert" +msgstr "" +"Sysexxer-NG est un outil universel d'échange de données MIDI exclusives-système.\n" +"\n" +"Ce logiciel libre est publié sous les termes de la licence Boost Software License " +"1.0.\n" +"\n" +"Version %s © 2018-2019\n" +"Auteur : Jean Pierre Cimalando\n" +"Contributeur : Olivier Humbert" + +#: sources/window_impl.cc:188 msgid "System-exclusive dump\t*.syx" msgstr "Dump system-exclusive\t*.syx" -#: sources/window_impl.cc:134 +#: sources/window_impl.cc:155 msgid "" "System-exclusive dump\t*.syx\n" "Standard MIDI file\t*.mid" @@ -175,7 +201,7 @@ msgstr "" "Dump system-exclusive\t*.syx\n" "Fichier MIDI standard\t*.mid" -#: sources/window_impl.cc:180 +#: sources/window_impl.cc:201 msgid "The file already exists. Replace it?" msgstr "Le fichier existe déjà. L'écraser ?" @@ -183,16 +209,26 @@ msgstr "Le fichier existe déjà. L'écraser ?" msgid "Unknown" msgstr "Inconnu" -#: sources/window_impl.cc:343 sources/window_impl.cc:344 -#: sources/window_impl.cc:361 sources/window_impl.cc:389 +#: sources/window_impl.cc:364 sources/window_impl.cc:365 +#: sources/window_impl.cc:382 sources/window_impl.cc:410 msgid "Virtual port" msgstr "Port virtuel" -#: sources/window_impl.cc:180 +#. Hyperlink_Button* o +#: sources/window.cxx:250 +msgid "Visit the home page" +msgstr "Visiter la page d'accueil" + +#: sources/window_impl.cc:201 msgid "Yes" msgstr "Oui" +#. Fl_Text_Display* txt_about +#: sources/window.cxx:238 +msgid "https://github.com/linuxmao-org/sysexxer-ng" +msgstr "" + #. Fl_Box* lbl_sendrate -#: sources/window.cxx:192 +#: sources/window.cxx:200 msgid "kb/s" msgstr "kb/s" diff --git a/sources/hyperlink_button.cc b/sources/hyperlink_button.cc new file mode 100644 index 0000000..b10e1bb --- /dev/null +++ b/sources/hyperlink_button.cc @@ -0,0 +1,26 @@ +// Copyright Jean Pierre Cimalando 2018. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "hyperlink_button.h" +#include + +Hyperlink_Button::Hyperlink_Button(int x, int y, int w, int h, const char *l) + : Fl_Button(x, y, w, h, l) +{ +} + +int Hyperlink_Button::handle(int event) +{ + if (event == FL_ENTER) { + Fl_Window *win = window(); + win->cursor(FL_CURSOR_HAND); + } + else if (event == FL_LEAVE) { + Fl_Window *win = window(); + win->cursor(FL_CURSOR_DEFAULT); + } + + return Fl_Button::handle(event); +} diff --git a/sources/hyperlink_button.h b/sources/hyperlink_button.h new file mode 100644 index 0000000..ba644fe --- /dev/null +++ b/sources/hyperlink_button.h @@ -0,0 +1,13 @@ +// Copyright Jean Pierre Cimalando 2018. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#pragma once +#include + +class Hyperlink_Button : public Fl_Button { +public: + Hyperlink_Button(int x, int y, int w, int h, const char *l = nullptr); + int handle(int event) override; +}; diff --git a/sources/window.cxx b/sources/window.cxx index 9c5295f..0517436 100644 --- a/sources/window.cxx +++ b/sources/window.cxx @@ -1,8 +1,9 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0304 +// generated by Fast Light User Interface Designer (fluid) version 1.0305 #include "app_i18n.h" #include "window.h" #include "dnd_hold_browser.h" +#include "hyperlink_button.h" #include "window_impl.cc" void Main_Window::cb_btn_load_i(Fl_Button*, void*) { @@ -74,6 +75,13 @@ void Main_Window::cb_btn_midi_out_i(Fl_Button*, void*) { void Main_Window::cb_btn_midi_out(Fl_Button* o, void* v) { ((Main_Window*)(o->parent()->parent()->parent()))->cb_btn_midi_out_i(o,v); } + +void Main_Window::cb_https_i(Hyperlink_Button* o, void*) { + fl_open_uri(o->label()); +} +void Main_Window::cb_https(Hyperlink_Button* o, void* v) { + ((Main_Window*)(o->parent()->parent()->parent()))->cb_https_i(o,v); +} Main_Window::Main_Window(int X, int Y, int W, int H, const char *L) : Fl_Group(X, Y, W, H, L) { P.reset(new Impl); @@ -219,6 +227,32 @@ P.reset(new Impl); } // Fl_Box* o tab_options->end(); } // Fl_Group* tab_options + { Fl_Group* o = new Fl_Group(0, 25, 465, 225, _("About")); + o->labelsize(12); + o->hide(); + { txt_about = new Fl_Text_Display(10, 35, 445, 140); + txt_about->box(FL_THIN_DOWN_BOX); + txt_about->labelsize(12); + txt_about->textsize(12); + } // Fl_Text_Display* txt_about + { Hyperlink_Button* o = new Hyperlink_Button(10, 215, 325, 20, _("https://github.com/linuxmao-org/sysexxer-ng")); + o->box(FL_NO_BOX); + o->color(FL_BACKGROUND_COLOR); + o->selection_color(FL_BACKGROUND_COLOR); + o->labeltype(FL_NORMAL_LABEL); + o->labelfont(1); + o->labelsize(12); + o->labelcolor((Fl_Color)4); + o->callback((Fl_Callback*)cb_https); + o->align(Fl_Align(FL_ALIGN_CENTER)); + o->when(FL_WHEN_RELEASE); + } // Hyperlink_Button* o + { Fl_Box* o = new Fl_Box(10, 195, 325, 20, _("Visit the home page")); + o->labelsize(12); + o->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE)); + } // Fl_Box* o + o->end(); + } // Fl_Group* o tabs->end(); } // Fl_Tabs* tabs P->init(this); diff --git a/sources/window.fl b/sources/window.fl index a2daa02..4d9c88e 100644 --- a/sources/window.fl +++ b/sources/window.fl @@ -1,5 +1,5 @@ # data file for the Fltk User Interface Designer (fluid) -version 1.0304 +version 1.0305 i18n_type 1 i18n_include app_i18n.h i18n_function _ @@ -8,6 +8,9 @@ code_name {.cxx} decl {\#include "dnd_hold_browser.h"} {private global } +decl {\#include "hyperlink_button.h"} {private global +} + decl {\#include } {public global } @@ -17,11 +20,14 @@ decl {\#include "window_impl.cc"} {private global decl {class Dnd_Hold_Browser;} {public global } -decl {class Fl_Hold_Browser;} {selected public global +decl {class Hyperlink_Button;} {public global +} + +decl {class Fl_Hold_Browser;} {public global } widget_class Main_Window {open - xywh {120 180 465 250} type Double visible + xywh {117 206 465 250} type Double visible } { decl {static int const width = 465, height = 250;} {public local } @@ -41,7 +47,7 @@ widget_class Main_Window {open xywh {0 0 465 250} } { Fl_Group tab_send { - label Send open + label Send open selected xywh {0 25 465 225} box THIN_UP_FRAME labelsize 12 } { Fl_Button btn_load { @@ -144,6 +150,24 @@ widget_class Main_Window {open xywh {10 95 180 25} labelsize 12 align 20 } } + Fl_Group {} { + label About open + xywh {0 25 465 225} labelsize 12 hide + } { + Fl_Text_Display txt_about { + xywh {10 35 445 140} box THIN_DOWN_BOX labelsize 12 textsize 12 + } + Fl_Button {} { + label {https://github.com/linuxmao-org/sysexxer-ng} + callback {fl_open_uri(o->label());} + xywh {10 215 325 20} box NO_BOX labelfont 1 labelsize 12 labelcolor 4 + class Hyperlink_Button + } + Fl_Box {} { + label {Visit the home page} + xywh {10 195 325 20} labelsize 12 align 20 + } + } } decl {struct Impl;} {private local } diff --git a/sources/window.h b/sources/window.h index e5e67d1..03933b0 100644 --- a/sources/window.h +++ b/sources/window.h @@ -1,10 +1,11 @@ -// generated by Fast Light User Interface Designer (fluid) version 1.0304 +// generated by Fast Light User Interface Designer (fluid) version 1.0305 #ifndef window_h #define window_h #include #include class Dnd_Hold_Browser; +class Hyperlink_Button; class Fl_Hold_Browser; #include #include @@ -79,6 +80,11 @@ class Main_Window : public Fl_Group { private: inline void cb_btn_midi_out_i(Fl_Button*, void*); static void cb_btn_midi_out(Fl_Button*, void*); +public: + Fl_Text_Display *txt_about; +private: + inline void cb_https_i(Hyperlink_Button*, void*); + static void cb_https(Hyperlink_Button*, void*); struct Impl; std::unique_ptr P; public: diff --git a/sources/window_impl.cc b/sources/window_impl.cc index acab7c2..178c2a4 100644 --- a/sources/window_impl.cc +++ b/sources/window_impl.cc @@ -24,6 +24,8 @@ struct Main_Window::Impl { std::vector event_recvlist_; Fl_Text_Buffer txb_recvdata_; Fl_Text_Buffer tsb_recvdata_; + Fl_Text_Buffer txb_about_; + Fl_Text_Buffer tsb_about_; bool receive_first_ = false; std::unique_ptr receive_buffer_; std::vector receive_tmpbuf_; @@ -123,6 +125,25 @@ void Main_Window::Impl::init(Main_Window *Q) tsb_senddata_.text(std::string(strchr(send_text, '\n') - send_text, 'A').c_str()); tsb_recvdata_.text(std::string(strchr(recv_text, '\n') - recv_text, 'A').c_str()); + /// + Q->txt_about->buffer(txb_about_); + Q->txt_about->wrap_mode(Fl_Text_Display::WRAP_AT_BOUNDS, 0); + + const char *about_text = _(u8"" + "Sysexxer-NG is a universal tool to exchange MIDI system-exclusive data.\n" + "\n" + "This free program is published under the terms of the Boost Software License 1.0.\n" + "\n" + "Version %s © 2018-2019\n" + "Author: Jean Pierre Cimalando\n" + "Contributor: Olivier Humbert"); + + txb_about_.text(astrprintf(about_text, PROJECT_VERSION).c_str()); + Q->txt_about->highlight_data(&tsb_about_, style_table, style_count, 'A', 0, 0); + + tsb_about_.text(std::string(strchr(about_text, ' ') - about_text, 'A').c_str()); + + /// Q->br_sendlist->dnd_callback(&on_dnd_load, this); }