Comic Book Reader
Projet C++ avec Qt
Bruno PETIT - Antonin RAFFIN
ENSTA ParisTech 2016
Plan
I. Cahier des charges
2. Architecture
3. Résultat
4. Annexe
Note: voir README.md/.pdf pour la compilation
Cahier des charges
Réaliser un lecteur permettant de prendre en charge les différents formats utilisés
pour les bandes dessinés
Intuitif
Interface agréable
Rapide
Orienté vers l'utilisateur:
Démarche (1)
1. ANalyse du problème
- Définition des objectifs
- Réflexion sur les points importants
- Réflexion sur les différentes étapes pour avoir une structure évolutive
2. Choix de l'architecture
- Combien de classes ? Quel héritage ?
- Quelles fonctions doivent-être implémentées ?
Démarche (2)
3. Répartition des tâches
- Travail en parallèle
- Partie GUI quasi-indépendante de l'extraction
4. Choix des Technologies et conventions
- Quel langage ? Quelle bibliothèque ?
- Quel framework pour le GUI ?
- Conventions de programmation ?
- Versioning avec GIT
Démarche (3)
5. Réalisation
- Tests unitaires
- Création d'une première version stable
6. Améliorations
- Ajout de fonctionnalités
- Amélioration de l'interface et de la robustesse du système
Fonctionnalités
Archives Supportées
- cbz (zip)
- cbr (rar)
- tar
- gz
Formats Supportés
- jpeg
- png
- gif
- bmp
- tiff
Fonctionnalités
Système
Utilisateur
- Lazy loading (on n'extrait que ce dont on a besoin)
- Robuste: supporte presque tous les types d'organisation et de nommage
- N'extrait que les images de l'archive
- Affichage multiple (une ou deux images)
- Redimensionnement automatique avec filtre
- Zoom et grab avec la souris
- Réinitialisation du zoom (avec adaptation à la fenêtre)
Les différentes classes
Extraction
GUI
Note: Les différentes classes sont détaillées par la suite
- Archive
- Book
- Async
- MainWindow
- ImageGraphicView
Book
Archive
MainWindow
Extraction
Gestion du livre
Affichage et interaction avec l'utilisateur
Async
Lazy Loading
Les différentes classes
Affichage de l'image
ImageGraphicView
Classe Archive
class Archive
{
private:
std::string name;
std::string currentEntryName;
unsigned int nbEntries;
unsigned int counter;
void* currentArchive;
void* currentEntry;
public:
Archive(){}
virtual ~Archive(){}
virtual void open(){}
virtual void close(){}
virtual bool hasNext(){}
virtual void next(){}
virtual std::string getEntryName(){}
virtual int getCurrentEntryNb(){}
virtual int getNbOfEntries(){}
virtual void writeTempEntry(std::string tempFolder){}
}
Classe abstraite pour représenter et extraire une archive
Classe Archive
Contient les informations essentielles:
- Récupérer les différentes informations
- Parcourir l'archive
- Extraire une entité
Fonctions pour l'Extraction
- Nom de l'archive
- Nombre de pages
- Informations sur l'entité en cours d'extraction
Classe Archive
Résultat: Une extraction facile
archive = new LibArchive(archiveName); //Classe héritant de la classe Archive
while (archive->hasNext())
{
archive->next();
archive->writeTempEntry(tempFolder);//Extraction de l'entité courante
}
archive->close();
Exemple: extraire toute une archive
Archive
LibArchive
LibZippp
Chaque classe qui utilise une certaine bibliothèque pour extraire les archives hérite de la classe Archive
Bibliothèque:
Classe Book
class Book
{
public:
Book(){}
Book(std::string archiveName);
Book(std::string archiveName, std::string tempFolderName);
~Book();
void extractOneImage();
void extractAll();
void createImagesList();
unsigned int getNbPages();
int getCurrentPageNumber();
QImage getCurrentImage();
QImage getNextImage();
void setPage(unsigned int pageNumber);
bool hasPrev();
bool hasNext();
void prev();
void next();
private:
void init(std::string archiveName);
void createTempFolder();
std::string tempFolder;
LibArchive* bookArchive;
QStringList images;
unsigned int currentPage;//Warning: page numbers go from 0 to nbPages-1
unsigned int nbPages;
};
Classe pour représenter et manipuler un livre
Classe Book
Surcouche pour faire le lien entre l'extracteur (de type Archive) et l'interface graphique (MainWindow)
Permet de parcourir le dossier temporaire dans lequel ont été extraites les images
Book
Archive
MainWindow
Extraction
Gestion du livre
Affichage et interaction avec l'utilisateur
Classe ASYNC
class Async : public QObject
{
Q_OBJECT
public:
Async();
Async(Book* comicBook);
~Async();
void beginExtraction();
void continueExtraction();
void setCurrentBook(Book* comicBook);
int getNbPagesLoaded();
signals:
void imageReady(int pageNumber);
private:
int nbPagesLoaded;// number of pages extracted
int nbPages;// Total number of pages (of the book)
int nextStop;// Used in the async extraction for stopping the loop
int nbPagesToExtractBeforeDipslay;// Nb of pages to be load before showing
Book* currentBook;// The current comic book we are extracting
};
Classe pour extraire l'archive de manière asynchrone
Classe Async
Se place entre la classe Book et l'interface graphique (MainWindow)
Book
Archive
MainWindow
Extraction
Gestion du livre
Affichage et interaction avec l'utilisateur
Lazy loading: extrait une image que lorsqu'elle doit être affichée
=> Le dossier temporaire a une taille minimale
Async
Permet un affichage rapide (émet un signal dès que les deux premières images sont prêtes)
Lazy Loading
Classe ImageGraphicView
class ImageGraphicView : public QGraphicsView
{
Q_OBJECT
public:
ImageGraphicView(QWidget * parent=0);
~ ImageGraphicView();
void setImage(const QImage & image);
public slots:
void fitImage();
protected:
virtual void resizeEvent(QResizeEvent *event);
virtual void wheelEvent(QWheelEvent *event);
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
void setZoomFactor(const double factor) { zoomFactor=factor; }
void setZoomCtrlFactor(const double factor) {zoomCtrlFactor=factor; }
double zoomFactor;
double zoomCtrlFactor;
private:
// Scene where the image is drawn
QGraphicsScene* scene;
// Pixmap item containing the image
QGraphicsPixmapItem* pixmapItem;
// Size of the current image
QSize imageSize;
// Current pixmap
QPixmap currentPixmap;
};
Classe pour afficher et manipuler une image
Classe ImageGraphicView
Gère les différents événements:
MainWindow
Affichage et interaction avec l'utilisateur
ImageGraphicView
Affichage de l'image
- Zoom (avec la souris)
- Drag (avec la souris)
- Redimensionnement de la fenêtre
S'occupe du bon affichage de l'image:
- Ajustement de la taille de l'image aux dimensions de la fenêtre
- Application d'un filtre pour atténuer les effets du redimensionnement
Classe MainWindow
Classe principale pour l'affichage et l'interaction avec l'utilisateur
Interaction
- Création des menus
- Création de la barre d'outil
- Création des événements associés
- Gestion des raccourcis clavier
Affichage
- Nombre de pages et page courante
- Gestion des différents modes de vue
- Gestion de l'ouverture d'une archive
Résultat
Résultat
Ouvrir un fichier
Navigation
Mode d'affichage
(une ou deux pages)
Réinitialiser le zoom
Icônes => plus universel et intuitif
Crédits: flaticon.com
Un raccourci clavier est associé à chaque icône
Annexe
Les instructions pour la compilation et les informations sur le logiciel sont dans le README.md
Comic Book Reader
By Antonin Raffin
Comic Book Reader
- 1,128