Documentation Développeurs - TitusVM/stonksmanager GitHub Wiki
Electron
Le frameworkElectron est un framework permettant de créer des applications de bureau à l'aide de JavaScript, HTML et CSS. En intégrant Chromium et Node.js dans son binaire, Electron permet de maintenir une base de code JavaScript et de créer des applications multiplateformes qui fonctionnent sous Windows, macOS et Linux. (source Electronjs.org)
Pour plus d'informations sur l'utilisation des fonctionnalités d'Electron, il est conseillé de visiter la documentation Electron. Dans cette documentation seront expliqué en détails tous les différents procédés du framework.
Les dépendances nécessaires
Pour StonksManager plusieurs döpendances et librairies externes sont utilisées. Ces dernières peuvent être installée grâce au gestionnaire de librairies npm
et pip
pour les librairies python. Ceci nécessite d'avoir npm
et pip
installés sur la machine, lien d'installation npm
et lien d'installation pip
.
Il suffit d'exécuter les commandes suivantes :
npm install --save-dev electron
npm install --save-dev python-shell
npm install --save-dev chart.js
pip install simplejson
Electron
La librairie Electron permet d'installer le framework et d'exécuter le code source en mode debug.
Python-shell
Cette librairie s'occupe de la communication entre le code python et le code javascript.
Chart.js
Cette librairie est nécessaire pour le dessin du graphe. Elle utilise les données standardisées json
pour produire les statistiques nécessaires à l'affichage automatisé et dynamique d'un graphe.
SimpleJson
Est nécessaire pour la lecture des fichiers de relevés de comptes (écrites en json
) depuis le code python. Ce dernier se charge aussi de faire passer les données json
à python-shell pour afficher les données dans l'application.
Execution de l'application en mode debug
Pour pouvoir executer l'application, il est nécessaire de lancer la commande suivante dans le dossier source de l'application.
npm start
Les commandes sont réunies dans le fichier package.json
qui définit ce que chaque commande exécute. Dans le cas de la commande start
, Electron se chargera de l'exécution du script suivant :
"start": "electron ."
Il est fort utile de se munir du logiciel Visual Studio Code pour faciliter le développement. Ceci est fortement conseillé car l'application est composé d'une variété de fichier de formats différents et ne nécessite pas l'utilisation d'une solution comme dans Visual Studio. Mais tout sorte d'IDE peut évidemment être utilisé, à condition que ce dernier puisse consulter les fichier .html
, .css
, .py
entre autres, .js
et .json
.
Déroulement de l'exécution
La commande electron .
est en mesure de lancer le fichier spécifié comme main
dans le fichier package.json
(pour plus d'informations consulter la documentation Electron) et se lance dans la construction des dépendances et de l'application. Une fois celle-ci démarrée, une première fenêtre s'ouvre. Ceci se fait grâce au code suivant du fichier main.js
:
function createWindows() {
mainWindow = new BrowserWindow({
minWidth: 1200,
minHeight: 720,
show: false,
autoHideMenuBar: true,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true,
webviewTag: true
}
});
loginWindow = new BrowserWindow({
parent: mainWindow,
width: 400,
height: 320,
transparent: true,
frame: false,
resizable: false,
maximizable: false,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true,
}
});
loginWindow.loadURL(url.format({
pathname: path.join(__dirname, 'login.html'),
protocol: 'file',
slashes: true
}));
loginWindow.setBackgroundColor('#00000000');
}
Lorsque la fenêtre principale est créée (mainWindow
), elle se cache pour laisser la place à la fenêtre de connexion (loginWindow
).
Les options de création de fenêtre peuvent aussi être consultées sur la documentation Electron).
.js
La communication entre fichier Electron propose un module pour pouvoir faire de la communication intra-application. Ce dernier porte le nom de ipcRenderer
et est responsable de la majorité de la communication pour le logiciel. Plus d'informations peuvent être trouvés dans la documentation Electron.
Le ipcMain
(processus principal) gère les différents appels et évènements comme le montre l'exemple qui suit :
/* Open the file dialog to select a json file */
ipcMain.on('open-JSON', (evt, arg) => {
dialog.showOpenDialog(mainWindow, {
properties: ['openFile'],
filters: [{
name: 'JSON', extensions: ['json']
}]
}).then(result => {
if (result.canceled) {
evt.returnValue = null;
} else {
evt.returnValue = result.filePaths[0];
}
}).catch(err => {
console.log(err) // avoid crashes
});
});
python
et javascript
La communication entre Le fichier /data/ipc.py
s'occupe de la communication entre le ipcRenderer
du framework de l'application et le code python
qui est nécessaire à la lecture des fichiers json
ainsi qu'aux calculs pour les affichages.
En voici les fonctions de communication :
def send(obj: list):
print(json.dumps(obj, use_decimal=True, namedtuple_as_object=True))
def read():
return json.loads(input(), use_decimal=True)
En effet, le code python
dans le dossier /data/
se charge de toute la gestion des données :
graphs.py
pour la génération des informations nécessaires pour l'affichage du graphe en page principaleipc.py
pour l'extraction des donnéesjson
etipcRenderer
loading.py
qui permet de charger les données nécessaires lors de l'exécution du programmesave.py
pour permettre de stocker les informations à la fermeture du programme pour garder les informations même après fermeture et ré-exécutiontransaction.py
qui se charge des transactions faites (factures)
L'interaction
L'interaction avec le logiciel est primairement gérée par les appels de l'ipcRenderer
dans le code des fichiers .js
.
La chose la plus importante à noter est l'utilisation persistante de l'ipcRenderer
car ce dernier permet d'exécuter des fonctions dans d'autres fichiers. Cela se présente comme suit :
function loginKeyPress() {
if (fs.existsSync(filename)) {
let data = fs.readFileSync(filename, 'utf8').split('\n');
data.forEach((authorities, index) => {
let [user, password] = authorities.split(',');
let usr = user.split(':')[1].trim();
let pass = password.split(':')[1].trim();
let txtUser = $('#txtUsr').val();
let txtPwd = $('#txtPwd').val();
if (txtUser == usr && txtPwd == pass) {
ipc.sendSync('entry-accepted', usr);
}
else {
$('#lbl').text('username or password is incorrect');
}
})
}
}
Cet exemple simple en montre sa fonctionnalité.
Lors de l'exécution de la ligne ipc.sendSync('entry-accepted', usr);
, un évènement ipc
est généré et envoyé au renderer (voir documentation ipcRenderer). Ce dernier a été instancié grâce aux lignes de codes suivantes (dans le programme main.js
) :
/* User logged in */
ipcMain.on('entry-accepted', (e, name) => {
username = name;
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'budget.html'),
protocol: 'file',
slashes: true
}));
mainWindow.show();
loginWindow.close();
});
Lors de la réception de l'évènement entry-accepted
(entrée acceptée), le renderer exécute le code fourni ci-dessus, en l'occurence, il charge le fichier budget.html
.
L'interface
L'interface est composée en majorité par le code .html
. Il semble non-pertinant d'expliquer chaque affichage car c'est assez évident de comprendre sa fonctionnalité.