Qt Jambi : JEditor, un simple éditeur de fichier texte

| Natim | dourouc05 |

On va ici créer un lecteur avec des menus.

Commentez

- Titre : Qt Jambi : JEditor, un simple éditeur de fichier texte

- Auteurs : Natim, dourouc05

- Parution : 28 avril 2011

- Mise à jour : 20 mai 2011

- Licence :

Sommaire

- I. Cahier des charges

- II. La solution

- III. Remerciements

I - Cahier des charges

Ce lecteur possédera trois menus :

- Fichier :

- Nouveau,

- Ouvrir,

- Enregistrer,

- Enregistrer sous,

- Quitter ;

- Édition :

- Couper,

- Copier,

- Coller ;

- Aide :

- À propos de JEditor,

- À propos de Qt Jambi.

On pourra donc créer, ouvrir, enregistrer et enregistrer sous un fichier texte. En plus d'avoir ces menus dans la barre de menu, on ajoutera une barre d'outils contenant les plus utiles.

II - La solution

Pour avoir une barre de menu, il nous faudra hériter de la classe QMainWindow de Qt. En effet, avec Qt, lorsque l'on veut créer un widget, on hérite de la classe Qt et ensuite on ajoute des méthodes d'actions spécifiques. Par exemple, les méthodes new(), open(), save(), saveas(), quit(). N'oubliez pas la documentation de Qt Jambi. C'est votre source de renseignements par excellence. Dedans, il y a absolument tout. Vous pouvez aussi la trouver dans votre installation de Qt Jambi en local. Vous le savez peut-être, Qt Jambi propose un outil très intéressant que l'on appelle QtDesigner. Malgré les apparences, cet outil est difficile à prendre en main. En le lançant, on s'aperçoit très vite que l'on peut faire des choses très jolies, mais c'est un faux semblant : vous n'arriverez pas à l'exploiter correctement dans vos programmes. Pour bien comprendre la manière dont les choses se présentent, on ne va pas utiliser QtDesigner dans un premier temps. Vous pouvez télécharger le pack d'image, ainsi que les sources.

/*
* JEditor.java
* Version : 2
*
* Créé le 2 novembre 2007
* Modifié le 13 novembre 2007
*/

/* Import des classes espace de nommage nécessaires */
import com.trolltech.qt.QVariant;

/* Importation des éléments du GUI */
import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QMainWindow;
import com.trolltech.qt.gui.QTextEdit;
import com.trolltech.qt.gui.QMenu;
import com.trolltech.qt.gui.QToolBar;
import com.trolltech.qt.gui.QAction;
import com.trolltech.qt.gui.QMenuBar;
import com.trolltech.qt.gui.QFileDialog;
import com.trolltech.qt.gui.QCloseEvent;
import com.trolltech.qt.gui.QMessageBox;
import com.trolltech.qt.gui.QIcon;
import com.trolltech.qt.gui.QKeySequence;
import com.trolltech.qt.gui.QCursor;

/* Importation des éléments de gestion */
import com.trolltech.qt.core.QFile;
import com.trolltech.qt.core.QTextStream;
import com.trolltech.qt.core.Qt;

/* Définition de l'application et de ses attributs */
public class JEditor extends QMainWindow {
private String curFile;         // Fichier actuellement ouvert
private QTextEdit textEdit;     // Widget permettant l'affichage et la modification du texte
private QMenu fileMenu;         // Menu Fichier
private QMenu editMenu;         // Menu Edition
private QMenu helpMenu;         // Menu Aide
private QToolBar fileToolBar;   // Barre d'outil Fichier
private QToolBar editToolBar;   // Barre d'outil Edition
private QAction newAct;         // Action Nouveau
private QAction openAct;        // Action Ouvrir
private QAction saveAct;        // Action Enregistrer
private QAction saveAsAct;      // Action Enregistrer Sous
private QAction exitAct;        // Action Quitter
private QAction cutAct;         // Action Couper
private QAction copyAct;        // Action Copier
private QAction pasteAct;       // Action Coller
private QAction aboutAct;       // Action A Propos de JEditor
private QAction aboutQtAct;     // Action A propos de Qt Jambi
private String rsrcPath = "classpath:images"; // Répertoire des images

/* Définition du constructeur */
public JEditor()
{
QMenuBar menuBar = new QMenuBar();                // On crée la barre de menu
textEdit = new QTextEdit(this);
setMenuBar(menuBar);                              // On ajoute la barre de menu à notre Application
setCentralWidget(textEdit);                       // On ajoute la zone de Texte
/* On lance les méthodes de création des différents attributs de notre fenêtre */
try {
createActions();
} catch (Exception e) {
e.printStackTrace();
}
createMenus();
createToolBars();
createStatusBar();
/* On lance la méthode documentWasModified lorsque le contenu du texte est modifié */
textEdit.document().contentsChanged.connect(this, "documentWasModified()");
/* Le fichier de départ est un fichier vide */
setCurrentFile("");
}

/* On redéfinit la méthode lorsque l'on clique sur le bouton fermer de la fenêtre pour demander à l'utilisateur
s'il veut enregistrer avant de quitter */
public void closeEvent(QCloseEvent event)
{
if (maybeSave()) {
event.accept();
} else {
event.ignore();
}
}

/* Lors de l'ouverture d'un nouveau fichier, on doit fermer le précédent, on avertit donc l'utilisateur.
On efface le contenu du widget textEdit et on met à 0 la valeur du nom de fichier */
public void newFile()
{
if (maybeSave()) {
textEdit.clear();
setCurrentFile("");
}
}

/* Méthode d'ouverture du fichier */
public void open()
{
if (maybeSave()) {
String fileName = QFileDialog.getOpenFileName(this);
if (fileName.length() != 0)
loadFile(fileName);
}
}

/* On enregistre les modifications effectuées dans le fichier */
public boolean save()
{
if (curFile.length() == 0) {
return saveAs();
} else {
return saveFile(curFile);
}
}

/* On enregistre les modifications dans un nouveau fichier */
public boolean saveAs()
{
String fileName = QFileDialog.getSaveFileName(this);
if (fileName.length() == 0)
return false;

return saveFile(fileName);
}

/* Fonction A propos de JEditor */
public void about()
{
QMessageBox.about(this,
tr("A Propos de JEditor"),
tr("<b>JEditor<b> est une application d'exemple"+
"pour faire une démonstration de l'utilisation de Qt Jambi"));
}

/* Méthode qui définit que le document a été modifié pour savoir si on a besoin de le sauvegarder ou pas */
public void documentWasModified()
{
setWindowModified(textEdit.document().isModified());
}

/* Création des actions des menus et des toolbars */
private void createActions()
{
/* Actions du menu Fichier */
newAct = new QAction(new QIcon(rsrcPath + "/new.png"), tr("&Nouveau"), this);
newAct.setShortcut(new QKeySequence(tr("Ctrl+N")));
newAct.setStatusTip(tr("Nouveau fichier"));
newAct.triggered.connect(this, "newFile()");

openAct = new QAction(new QIcon(rsrcPath + "/open.png"), tr("&Ouvrir..."), this);
openAct.setShortcut(tr("Ctrl+O"));
openAct.setStatusTip(tr("Ouvrir un fichier"));
openAct.triggered.connect(this, "open()");

saveAct = new QAction(new QIcon(rsrcPath + "/save.png"), tr("&Enregistrer..."), this);
saveAct.setShortcut(tr("Ctrl+S"));
saveAct.setStatusTip(tr("Enregistrer le fichier"));
saveAct.triggered.connect(this, "save()");

saveAsAct = new QAction(new QIcon(rsrcPath + "/save_as.png"), tr("Enregistrer Sous..."), this);
saveAsAct.setStatusTip(tr("Enregistrer le fichier sous..."));
saveAsAct.triggered.connect(this, "saveAs()");

exitAct = new QAction(tr("Quitter"), this);
exitAct.setStatusTip(tr("Quitter l'application"));
exitAct.triggered.connect(QApplication.instance(), "quit()");

/* Actions du Menu Edition */
cutAct = new QAction(new QIcon(rsrcPath + "/cut.png"), tr("Cou&per"), this);
cutAct.setShortcut(new QKeySequence(tr("Ctrl+X")));
cutAct.setStatusTip(tr("Couper la séléction"));
cutAct.triggered.connect(textEdit, "cut()");

copyAct = new QAction(new QIcon(rsrcPath + "/copy.png"), tr("&Copier..."), this);
copyAct.setShortcut(tr("Ctrl+C"));
copyAct.setStatusTip(tr("Copier la séléction"));
copyAct.triggered.connect(textEdit, "copy()");

pasteAct = new QAction(new QIcon(rsrcPath + "/paste.png"), tr("Co&ller..."), this);
pasteAct.setShortcut(tr("Ctrl+V"));
pasteAct.setStatusTip(tr("Coller le texte précédement coupé ou copié"));
pasteAct.triggered.connect(textEdit, "paste()");

/* Action du menu Aide */
aboutAct = new QAction(new QIcon(rsrcPath + "/about.png"), tr("A Propos de &JEditor"), this);
aboutAct.setStatusTip(tr("A Propos de JEditor"));
aboutAct.triggered.connect(this, "about()");

aboutQtAct = new QAction(new QIcon(rsrcPath + "/qt.png"), tr("A Propos de &Qt"), this);
aboutQtAct.setStatusTip(tr("Show the Qt library's About box"));
aboutQtAct.triggered.connect(QApplication.instance(), "aboutQt()");

cutAct.setEnabled(false);
copyAct.setEnabled(false);
textEdit.copyAvailable.connect(cutAct, "setEnabled(boolean)");
textEdit.copyAvailable.connect(copyAct, "setEnabled(boolean)");
}

/* Création des Menus */
private void createMenus()
{
/* Menu fichier */
fileMenu = menuBar().addMenu(tr("&Fichier"));
fileMenu.addAction(newAct);
fileMenu.addAction(openAct);
fileMenu.addAction(saveAct);
fileMenu.addAction(saveAsAct);
fileMenu.addSeparator();
fileMenu.addAction(exitAct);

/* Menu Edition */
editMenu = menuBar().addMenu(tr("&Edition"));
editMenu.addAction(cutAct);
editMenu.addAction(copyAct);
editMenu.addAction(pasteAct);

menuBar().addSeparator();

/* Menu Aide */
helpMenu = menuBar().addMenu(tr("&Aide"));
helpMenu.addAction(aboutAct);
helpMenu.addAction(aboutQtAct);
}

/* Création de la barre de menu */
private void createToolBars()
{
fileToolBar = addToolBar(tr("Fichier"));
fileToolBar.addAction(newAct);
fileToolBar.addAction(openAct);
fileToolBar.addAction(saveAct);

editToolBar = addToolBar(tr("Edition"));
editToolBar.addAction(cutAct);
editToolBar.addAction(copyAct);
editToolBar.addAction(pasteAct);
}

/* Création de la Barre de Status */
private void createStatusBar()
{
statusBar().showMessage(tr("Prêt"));
}

/* Teste si le fichier doit être sauvegardé ou non */
private boolean maybeSave()
{
if (textEdit.document().isModified()) {
QMessageBox.StandardButton ret = QMessageBox.warning(this, tr("JEditor"),
tr("Le document a été modifié.\n" +
"Voulez-vous sauvegarder les modifications ?"),
new QMessageBox.StandardButtons(QMessageBox.StandardButton.Ok,
QMessageBox.StandardButton.Discard,
QMessageBox.StandardButton.Cancel));
if (ret == QMessageBox.StandardButton.Ok) {
return save();
} else if (ret == QMessageBox.StandardButton.Cancel) {
return false;
}
}
return true;
}

/* Charger un fichier */
public void loadFile(String fileName)
{
QFile file = new QFile(fileName);
if (!file.open(new QFile.OpenMode(QFile.OpenModeFlag.ReadOnly, QFile.OpenModeFlag.Text))) {
QMessageBox.warning(this, tr("JEditor"), String.format(tr("Impossible de lire le fichier %1$s:\n%2$s."), fileName, file.errorString()));
return;
}

QTextStream in = new QTextStream(file);
QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.WaitCursor));
textEdit.setPlainText(in.readAll());
QApplication.restoreOverrideCursor();

setCurrentFile(fileName);
statusBar().showMessage(tr("Fichier Chargé"), 2000);
}

/* Sauvegarde du fichier */
public boolean saveFile(String fileName)
{
QFile file = new QFile(fileName);
if (!file.open(new QFile.OpenMode(QFile.OpenModeFlag.WriteOnly, QFile.OpenModeFlag.Text))) {
QMessageBox.warning(this, tr("JEditor"), String.format(tr("Impossible d'écrire dans le fichier %1$s:\n%2$s."), fileName, file.errorString()));
return false;
}

QTextStream out = new QTextStream(file);
QApplication.setOverrideCursor(new QCursor(Qt.CursorShape.WaitCursor));
out.writeString(textEdit.toPlainText());
QApplication.restoreOverrideCursor();

setCurrentFile(fileName);
statusBar().showMessage(tr("Fichier sauvegardé"), 2000);
file.close();
return true;
}

/* On enregistre le nom du fichier ouvert comme nom du fichier courant */
public void setCurrentFile(String fileName)
{
curFile = fileName;
textEdit.document().setModified(false);
setWindowModified(false);

String shownName;
if (curFile.length() == 0)
shownName = tr("sans_titre.txt");
else
shownName = curFile;

setWindowTitle(String.format(tr("%1$s[*] - %2$s"), shownName, tr("JEditor")));
}

/* Lancement de l'application */
public static void main(String[] args) {
QApplication.initialize(args);

JEditor application = new JEditor();
application.show();

QApplication.exec();
}
}

III - Remerciements

Merci à Thibaut Cuvelier pour la mise en page et à Jacques Thery pour la relecture !