modificado el script de mac os x para generar un .dmg

This commit is contained in:
Luis Ángel San Martín
2012-08-26 20:16:15 +02:00
commit fcbe4725ff
271 changed files with 24248 additions and 0 deletions

BIN
YACReader/YACReader.icns Normal file

Binary file not shown.

62
YACReader/YACReader.pro Normal file
View File

@ -0,0 +1,62 @@
# #####################################################################
# Automatically generated by qmake (2.01a) mi<EFBFBD> 8. oct 20:54:05 2008
# #####################################################################
TEMPLATE = app
TARGET =
DEPENDPATH += . \
release
INCLUDEPATH += .
INCLUDEPATH += ../common
QT += network webkit phonon
CONFIG += release
CONFIG -= flat
# Input
HEADERS += comic.h \
configuration.h \
goto_dialog.h \
magnifying_glass.h \
main_window_viewer.h \
viewer.h \
../common/pictureflow.h \
../common/custom_widgets.h \
../common/check_new_version.h \
../common/qnaturalsorting.h \
goto_flow.h \
options_dialog.h \
bookmarks.h \
bookmarks_dialog.h \
render.h \
shortcuts_dialog.h \
translator.h
SOURCES += comic.cpp \
configuration.cpp \
goto_dialog.cpp \
magnifying_glass.cpp \
main.cpp \
main_window_viewer.cpp \
viewer.cpp \
../common/pictureflow.cpp \
../common/custom_widgets.cpp \
../common/check_new_version.cpp \
../common/qnaturalsorting.cpp \
goto_flow.cpp \
options_dialog.cpp \
bookmarks.cpp \
bookmarks_dialog.cpp \
render.cpp \
shortcuts_dialog.cpp \
translator.cpp
RESOURCES += images.qrc \
files.qrc
RC_FILE = icon.rc
macx {
ICON = YACReader.icns
}
TRANSLATIONS = yacreader_es.ts \ yacreader_fr.ts
FORMS +=
Release:DESTDIR = ../release
Debug:DESTDIR = ../debug

159
YACReader/bookmarks.cpp Normal file
View File

@ -0,0 +1,159 @@
#include "bookmarks.h"
#include <QFile>
#include <QDataStream>
#include <QCoreApplication>
#include <QFileInfo>
#include <QMessageBox>
#define NUM_BOOKMARKS 250
Bookmarks::Bookmarks()
:lastPageIndex(0)
{
list.load();
}
void Bookmarks::setLastPage(int index,const QPixmap & page)
{
lastPageIndex = index;
lastPage = page;
}
void Bookmarks::setBookmark(int index,const QPixmap & page)
{
if(!bookmarks.contains(index))
{
bookmarks.insert(index,page);
latestBookmarks.push_front(index);
if(latestBookmarks.count()>3)
{
bookmarks.remove(latestBookmarks.back());
latestBookmarks.pop_back();
}
}
else //udate de pixmap;
{
bookmarks[index]=page;
}
}
void Bookmarks::removeBookmark(int index)
{
bookmarks.remove(index);
}
QList<int> Bookmarks::getBookmarkPages() const
{
return bookmarks.keys();
}
QPixmap Bookmarks::getBookmarkPixmap(int page) const
{
return bookmarks.value(page);
}
QPixmap Bookmarks::getLastPagePixmap() const
{
return lastPage;
}
int Bookmarks::getLastPage() const
{
return lastPageIndex;
}
bool Bookmarks::isBookmark(int page)
{
return bookmarks.contains(page);
}
bool Bookmarks::imageLoaded(int page)
{
return !bookmarks.value(page).isNull();
}
void Bookmarks::newComic(const QString & path)
{
QFileInfo f(path);
QString comicID = f.fileName().toLower()+QString::number(f.size());
clear();
BookmarksList::Bookmark b = list.get(comicID);
comicPath=comicID;
lastPageIndex = b.lastPage;
latestBookmarks = b.bookmarks;
for(int i=0;i<latestBookmarks.count();i++)
bookmarks.insert(latestBookmarks.at(i),QPixmap());
added = b.added;
}
void Bookmarks::clear()
{
bookmarks.clear();
latestBookmarks.clear();
lastPageIndex=0;
lastPage = QPixmap();
}
void Bookmarks::save()
{
BookmarksList::Bookmark b;
b.lastPage = lastPageIndex;
b.bookmarks = getBookmarkPages();
BookmarksList::Bookmark previousBookmarks;
bool updated = ((previousBookmarks.lastPage != b.lastPage) || (previousBookmarks.bookmarks != b.bookmarks));
if(b.added.isNull() || updated)
b.added = QDateTime::currentDateTime();
list.add(comicPath,b);
list.save();
}
//-----------------------------------------------------------------------------
void BookmarksList::load()
{
QFile f(QCoreApplication::applicationDirPath()+"/bookmarks.yacr");
if(f.open(QIODevice::ReadOnly))
{
QDataStream dataS(&f);
dataS >> list;
f.close();
}
}
void BookmarksList::save()
{
QFile f(QCoreApplication::applicationDirPath()+"/bookmarks.yacr");
f.open(QIODevice::WriteOnly);
QDataStream dataS(&f);
if(list.count()>NUM_BOOKMARKS)
deleteOldest(list.count()-NUM_BOOKMARKS);
dataS << list;
f.close();
}
void BookmarksList::deleteOldest(int num)
{
QString comic;
QDateTime date(QDate(10000,1,1));//TODO MAX_DATE??
for(QMap<QString,Bookmark>::const_iterator itr=list.begin();itr!=list.end();itr++)
{
if(itr->added<date)
{
comic=itr.key();
date = itr->added;
}
}
list.remove(comic);
}
void BookmarksList::add(const QString & comicID, const Bookmark & b)
{
list.insert(comicID,b);
}
BookmarksList::Bookmark BookmarksList::get(const QString & comicID)
{
//if(list.contains(comicID)
return list.value(comicID);
}

77
YACReader/bookmarks.h Normal file
View File

@ -0,0 +1,77 @@
#ifndef BOOKMARKS_H
#define BOOKMARKS_H
#include <QObject>
#include <QMap>
#include <QPixmap>
#include <QString>
#include <QMap>
#include <QDateTime>
class BookmarksList
{
public:
struct Bookmark {
int lastPage;
QList<int> bookmarks;
QDateTime added;
Bookmark():lastPage(0){};
friend QDataStream & operator<< ( QDataStream & out, const Bookmark & bm )
{
out << bm.lastPage;
out << bm.bookmarks;
out << bm.added;
return out;
}
friend QDataStream & operator>> ( QDataStream & in, Bookmark & bm )
{
in >> bm.lastPage;
in >> bm.bookmarks;
in >> bm.added;
return in;
}
};
BookmarksList(){}
void load();
void save();
void add(const QString & comicID, const Bookmark & b);
Bookmark get(const QString & comicID);
protected:
QMap<QString,Bookmark> list;
void deleteOldest(int num);
};
class Bookmarks : public QObject
{
Q_OBJECT
protected:
QString comicPath;
//bookmarks setted by the user
QMap<int,QPixmap> bookmarks;
QList<int> latestBookmarks;
//last page readed
int lastPageIndex;
QPixmap lastPage;
BookmarksList list;
QDateTime added;
public:
Bookmarks();
void setLastPage(int index,const QPixmap & page);
void setBookmark(int index,const QPixmap & page);
void removeBookmark(int index);
QList<int> getBookmarkPages() const;
QPixmap getBookmarkPixmap(int page) const;
QPixmap getLastPagePixmap() const;
int getLastPage() const;
bool isBookmark(int page);
bool imageLoaded(int page);
void newComic(const QString & path);
void clear();
void save();
};
#endif // BOOKMARKS_H

View File

@ -0,0 +1,182 @@
#include "bookmarks_dialog.h"
#include <QGridLayout>
#include <QLabel>
#include <QApplication>
#include <QDesktopWidget>
#include <QFrame>
#include <QImage>
#include "bookmarks.h"
BookmarksDialog::BookmarksDialog(QWidget * parent)
:QDialog(parent,Qt::FramelessWindowHint)
{
setModal(true);
animation = new QPropertyAnimation(this,"windowOpacity");
animation->setDuration(150);
QHBoxLayout * layout = new QHBoxLayout();
//bookmarks
QGridLayout * bookmarksL = new QGridLayout();
pages.push_back(new QLabel(tr("Lastest Page")));
for(int i=0;i<3;i++)
pages.push_back(new QLabel("-"));
int heightDesktopResolution = QApplication::desktop()->screenGeometry().height();
int height,width;
height = heightDesktopResolution*0.50;
width = height*0.65;
coverSize = QSize(width,height);
for(int i=0;i<4;i++)
{
QLabel * l = new QLabel();
l->setFixedSize(coverSize);
l->setScaledContents(false);
//l->setPixmap(QPixmap(":/images/notCover.png"));
l->installEventFilter(this);
images.push_back(l);
}
for(int i=0;i<3;i++)
bookmarksL->addWidget(pages.at(i+1),0,i,Qt::AlignCenter);
for(int i=0;i<3;i++)
bookmarksL->addWidget(images.at(i+1),1,i,Qt::AlignCenter);
//last page
QGridLayout * lp = new QGridLayout();
lp->addWidget(pages.at(0),0,0,Qt::AlignCenter);
lp->addWidget(images.at(0),1,0,Qt::AlignCenter);
layout->addLayout(bookmarksL);
QFrame *f = new QFrame( this );
f->setFrameStyle( QFrame::VLine | QFrame::Sunken );
layout->addWidget(f);
layout->addLayout(lp);
QHBoxLayout * buttons = new QHBoxLayout();
cancel = new QPushButton(tr("Close"));
cancel->setFlat(true);
connect(cancel,SIGNAL(clicked()),this,SLOT(hide()));
buttons->addStretch();
buttons->addWidget(cancel);
QVBoxLayout * l = new QVBoxLayout();
l->addWidget(new QLabel(tr("Click on any image to go to the bookmark")),0,Qt::AlignCenter);
l->addLayout(layout);
l->addLayout(buttons);
this->setPalette(QPalette(QColor(25,25,25)));
//this->setAutoFillBackground(true);
setLayout(l);
}
void BookmarksDialog::setBookmarks(const Bookmarks & bm)
{
lastPage = bm.getLastPage();
if (lastPage > 0)
{
QPixmap p = bm.getLastPagePixmap();
if(p.isNull())
{
images.at(0)->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
images.at(0)->setText(tr("Loading..."));
}
else
{
images.at(0)->setAlignment(Qt::AlignHCenter|Qt::AlignBottom);
images.at(0)->setPixmap(p.scaled(coverSize,Qt::KeepAspectRatio,Qt::SmoothTransformation));
}
}
else
{
images.at(0)->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
images.at(0)->setPixmap(QPixmap(":/images/notCover.png").scaled(coverSize,Qt::KeepAspectRatio,Qt::SmoothTransformation));
}
QList<int> l = bm.getBookmarkPages();
int s = l.count();
for(int i=0;i<s;i++)
{
pages.at(i+1)->setText(QString::number(l.at(i)+1));
QPixmap p = bm.getBookmarkPixmap(l.at(i));
if(p.isNull())
{
images.at(i+1)->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
images.at(i+1)->setText(tr("Loading..."));
}
else
{
images.at(i+1)->setAlignment(Qt::AlignHCenter|Qt::AlignBottom);
images.at(i+1)->setPixmap(p.scaled(coverSize,Qt::KeepAspectRatio,Qt::SmoothTransformation));
}
}
for(int i=s;i<3;i++)
{
pages.at(i+1)->setText("-");
images.at(i+1)->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
images.at(i+1)->setPixmap(QPixmap(":/images/notCover.png").scaled(coverSize,Qt::KeepAspectRatio,Qt::SmoothTransformation));
}
}
bool BookmarksDialog::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::MouseButtonPress)
{
if (obj == images.at(0))
{
emit(goToPage(lastPage+1));
close();
event->accept();
}
for(int i=1;i<=3;i++)
{
if(obj == images.at(i))
{
bool b;
int page = pages.at(i)->text().toInt(&b);
if(b)
{
emit(goToPage(page));
close();
}
event->accept();
}
}
}
// pass the event on to the parent class
return QDialog::eventFilter(obj, event);
}
void BookmarksDialog::keyPressEvent(QKeyEvent * event)
{
if(event->key() == Qt::Key_M)
hide();
}
void BookmarksDialog::show()
{
QDialog::show();
disconnect(animation,SIGNAL(finished()),this,SLOT(close()));
animation->setStartValue(0);
animation->setEndValue(1);
animation->start();
}
void BookmarksDialog::hide()
{
connect(animation,SIGNAL(finished()),this,SLOT(close()));
animation->setStartValue(1);
animation->setEndValue(0);
animation->start();
}

View File

@ -0,0 +1,45 @@
#ifndef __BOOKMARKS_DIALOG_H
#define __BOOKMARKS_DIALOG_H
#include <QWidget>
#include <QDialog>
#include <QLabel>
#include <QPushButton>
#include <QEvent>
#include <QKeyEvent>
#include <QPropertyAnimation>
#include "bookmarks.h"
class BookmarksDialog : public QDialog
{
Q_OBJECT
protected:
QList<QLabel *> pages;
QList<QLabel *> images;
int lastPage;
QPushButton * accept;
QPushButton * cancel;
QSize coverSize;
bool eventFilter(QObject *obj, QEvent *event);
void keyPressEvent(QKeyEvent * event);
QPropertyAnimation * animation;
public:
BookmarksDialog(QWidget * parent = 0);
public slots:
void setBookmarks(const Bookmarks & bookmarks);
void show();
void hide();
signals:
void goToPage(unsigned int page);
};
#endif // BOOKMARKS_DIALOG_H

300
YACReader/comic.cpp Normal file
View File

@ -0,0 +1,300 @@
#include "comic.h"
#include <QPixmap>
#include <QRegExp>
#include <QString>
#include <algorithm>
#include <QDir>
#include <QFileInfoList>
#include "bookmarks.h"
#include "qnaturalsorting.h"
#define EXTENSIONS << "*.jpg" << "*.jpeg" << "*.png" << "*.gif" << "*.tiff" << "*.tif" << "*.bmp"
//-----------------------------------------------------------------------------
Comic::Comic()
:_pages(),_index(0),_path(),_loaded(false),bm(new Bookmarks())
{
setup();
}
//-----------------------------------------------------------------------------
Comic::Comic(const QString pathFile)
:_pages(),_index(0),_path(pathFile),_loaded(false),bm(new Bookmarks())
{
setup();
loadFromFile(pathFile);
}
//-----------------------------------------------------------------------------
void Comic::setup()
{
connect(this,SIGNAL(pageChanged(int)),this,SLOT(checkIsBookmark(int)));
connect(this,SIGNAL(imageLoaded(int)),this,SLOT(updateBookmarkImage(int)));
}
//-----------------------------------------------------------------------------
bool Comic::load(const QString & path)
{
QFileInfo fi(path);
if(fi.exists())
{
bm->newComic(path);
emit bookmarksLoaded(*bm);
if(fi.isFile())
{
loadFromFile(path);
}
else
{
if(fi.isDir())
{
loadFromDir(path);
}
}
return true;
}
else
{
QMessageBox::critical(NULL,tr("Not found"),tr("Comic not found"));
emit errorOpening();
return false;
}
}
//-----------------------------------------------------------------------------
void Comic::loadFromFile(const QString & pathFile)
{
_path = QDir::cleanPath(pathFile);
//load files size
_7z = new QProcess();
QStringList attributes;
attributes << "l" << "-ssc-" << "-r" << _path EXTENSIONS;
connect(_7z,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(loadSizes(void)));
connect(_7z,SIGNAL(error(QProcess::ProcessError)),this,SLOT(openingError(QProcess::ProcessError)));
_7z->start(QCoreApplication::applicationDirPath()+"/utils/7z",attributes);
}
//-----------------------------------------------------------------------------
void Comic::loadFromDir(const QString & pathDir)
{
_pathDir = pathDir;
start();
}
//-----------------------------------------------------------------------------
void Comic::run()
{
QDir d(_pathDir);
QStringList l;
l EXTENSIONS;
d.setNameFilters(l);
d.setFilter(QDir::Files|QDir::NoDotAndDotDot);
//d.setSorting(QDir::Name|QDir::IgnoreCase|QDir::LocaleAware);
QFileInfoList list = d.entryInfoList();
qSort(list.begin(),list.end(),naturalSortLessThanCIFileInfo);
int nPages = list.size();
_pages.clear();
_pages.resize(nPages);
if(nPages==0)
{
QMessageBox::critical(NULL,tr("No images found"),tr("There are not images on the selected folder"));
emit errorOpening();
}
else
{
emit pageChanged(0); // this indicates new comic, index=0
emit numPages(_pages.size());
_loaded = true;
for(int i=0;i<nPages;i++)
{
QFile f(list.at(i).absoluteFilePath());
f.open(QIODevice::ReadOnly);
_pages[i]=f.readAll();
emit imageLoaded(i);
emit imageLoaded(i,_pages[i]);
}
}
emit imagesLoaded();
}
//-----------------------------------------------------------------------------
void Comic::loadSizes()
{
QRegExp rx("[0-9]{4}-[0-9]{2}-[0-9]{2}[ ]+[0-9]{2}:[0-9]{2}:[0-9]{2}[ ]+.{5}[ ]+([0-9]+)[ ]+([0-9]+)[ ]+(.+)");
QByteArray ba = _7z->readAllStandardOutput();
QList<QByteArray> lines = ba.split('\n');
QByteArray line;
QString name;
foreach(line,lines)
{
if(rx.indexIn(QString(line))!=-1)
{
_sizes.push_back(rx.cap(1).toInt());
name = rx.cap(3).trimmed();
_order.push_back(name);
_fileNames.push_back(name);
}
}
if(_sizes.size()==0)
{
QMessageBox::critical(NULL,tr("File error"),tr("File not found or not images in file"));
emit errorOpening();
return;
}
_pages.resize(_sizes.size());
emit pageChanged(0); // this indicates new comic, index=0
emit numPages(_pages.size());
_loaded = true;
_cfi=0;
qSort(_fileNames.begin(),_fileNames.end(), naturalSortLessThanCI);
int i=0;
foreach(name,_fileNames)
{
_newOrder.insert(name,i);
i++;
}
_7ze = new QProcess();
QStringList attributes;
attributes << "e" << "-ssc-" << "-so" << "-r" << _path EXTENSIONS;
connect(_7ze,SIGNAL(error(QProcess::ProcessError)),this,SLOT(openingError(QProcess::ProcessError)));
connect(_7ze,SIGNAL(readyReadStandardOutput()),this,SLOT(loadImages(void)));
connect(_7ze,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(loadFinished(void)));
_7ze->start(QCoreApplication::applicationDirPath()+"/utils/7z",attributes);
}
//-----------------------------------------------------------------------------
void Comic::loadImages()
{
QByteArray ba = _7ze->readAllStandardOutput();
int s;
int rigthIndex;
while(ba.size()>0)
{
rigthIndex = _newOrder.value(_order[_cfi]);
s = _pages[rigthIndex].size();
_pages[rigthIndex].append(ba.left(_sizes[_cfi]-s));
ba.remove(0,_sizes[_cfi]-s);
if(_pages[rigthIndex].size()==static_cast<int>(_sizes[_cfi]))
{
emit imageLoaded(rigthIndex);
emit imageLoaded(rigthIndex,_pages[rigthIndex]);
_cfi++;
}
}
}
//-----------------------------------------------------------------------------
void Comic::openingError(QProcess::ProcessError error)
{
switch(error)
{
case QProcess::FailedToStart:
QMessageBox::critical(NULL,tr("7z not found"),tr("7z wasn't found in your PATH."));
break;
case QProcess::Crashed:
QMessageBox::critical(NULL,tr("7z crashed"),tr("7z crashed."));
break;
case QProcess::ReadError:
QMessageBox::critical(NULL,tr("7z reading"),tr("problem reading from 7z"));
break;
case QProcess::UnknownError:
QMessageBox::critical(NULL,tr("7z problem"),tr("Unknown error 7z"));
break;
default:
//TODO
break;
}
_loaded = false;
emit errorOpening();
}
int Comic::nextPage()
{
if(_index<_pages.size()-1)
_index++;
emit pageChanged(_index);
return _index;
}
//-----------------------------------------------------------------------------
int Comic::previousPage()
{
if(_index>0)
_index--;
emit pageChanged(_index);
return _index;
}
//-----------------------------------------------------------------------------
void Comic::setIndex(unsigned int index)
{
if(static_cast<int>(index)<_pages.size()-1)
_index = index;
else
_index = _pages.size()-1;
emit pageChanged(_index);
}
//-----------------------------------------------------------------------------
QPixmap * Comic::currentPage()
{
QPixmap * p = new QPixmap();
p->loadFromData(_pages[_index]);
return p;
}
//-----------------------------------------------------------------------------
QPixmap * Comic::operator[](unsigned int index)
{
QPixmap * p = new QPixmap();
p->loadFromData(_pages[index]);
return p;
}
//-----------------------------------------------------------------------------
bool Comic::loaded()
{
return _loaded;
}
//-----------------------------------------------------------------------------
void Comic::loadFinished()
{
emit imagesLoaded();
}
//-----------------------------------------------------------------------------
void Comic::setBookmark()
{
bm->setBookmark(_index,*operator[](_index));
emit bookmarksLoaded(*bm);
}
//-----------------------------------------------------------------------------
void Comic::removeBookmark()
{
bm->removeBookmark(_index);
emit bookmarksLoaded(*bm);
}
//-----------------------------------------------------------------------------
void Comic::saveBookmarks()
{
bm->setLastPage(_index,*operator[](_index));
bm->save();
}
//-----------------------------------------------------------------------------
void Comic::checkIsBookmark(int index)
{
emit isBookmark(bm->isBookmark(index));
}
//-----------------------------------------------------------------------------
void Comic::updateBookmarkImage(int index)
{
if(bm->isBookmark(index))
{
bm->setBookmark(index,*operator[](index));
emit bookmarksLoaded(*bm);
}
if(bm->getLastPage() == index)
{
bm->setLastPage(index,*operator[](index));
emit bookmarksLoaded(*bm);
}
}

70
YACReader/comic.h Normal file
View File

@ -0,0 +1,70 @@
#ifndef __COMIC_H
#define __COMIC_H
#include <QtCore>
#include <QImage>
#include <QtGui>
#include <QByteArray>
#include <QMap>
#include "bookmarks.h"
class Comic : public QThread
{
Q_OBJECT
private:
//Comic pages, one QPixmap for each file.
QVector<QByteArray> _pages;
QVector<uint> _sizes;
QStringList _fileNames;
QMap<QString,int> _newOrder;
QVector<QString> _order;
int _index;
QString _path;
bool _loaded;
QProcess * _7z;
QProcess * _7ze;
int _cfi;
QString _pathDir;
Bookmarks * bm;
void run();
public:
//Constructors
Comic();
Comic(const QString pathFile);
void setup();
//Load pages from file
bool load(const QString & path);
void loadFromFile(const QString & pathFile);
void loadFromDir(const QString & pathDir);
int nextPage();
int previousPage();
void setIndex(unsigned int index);
unsigned int getIndex(){return _index;};
unsigned int numPages(){return _pages.size();}
QPixmap * currentPage();
bool loaded();
QPixmap * operator[](unsigned int index);
QVector<QByteArray> * getRawData(){return &_pages;};
public slots:
void loadImages();
void loadSizes();
void openingError(QProcess::ProcessError error);
void loadFinished();
void setBookmark();
void removeBookmark();
void saveBookmarks();
void checkIsBookmark(int index);
void updateBookmarkImage(int);
signals:
void imagesLoaded();
void imageLoaded(int index);
void imageLoaded(int index,const QByteArray & image);
void pageChanged(int index);
void numPages(unsigned int numPages);
void errorOpening();
void isBookmark(bool);
void bookmarksLoaded(const Bookmarks &);
};
#endif

199
YACReader/configuration.cpp Normal file
View File

@ -0,0 +1,199 @@
#include "configuration.h"
#include <QFile>
#include <QFile>
#include <QTextStream>
#include <QCoreApplication>
#include <QStringList>
#include <QMessageBox>
#define PATH "PATH"
#define MAG_GLASS_SIZE "MAG_GLASS_SIZE"
#define ZOOM_LEVEL "ZOOM_LEVEL"
#define SLIDE_SIZE "SLIDE_SIZE"
#define FIT "FIT"
#define FLOW_TYPE "FLOW_TYPE"
#define FULLSCREEN "FULLSCREEN"
#define FIT_TO_WIDTH_RATIO "FIT_TO_WIDTH_RATIO"
#define POS "POS"
#define SIZE "SIZE"
#define MAXIMIZED "MAXIMIZED"
#define DOUBLE_PAGE "DOUBLE_PAGE"
#define ADJUST_TO_FULL_SIZE "ADJUST_TO_FULL_SIZE"
#define BACKGROUND_COLOR "BACKGROUND_COLOR"
#define ALWAYS_ON_TOP "ALWAYS_ON_TOP"
Configuration::Configuration()
{
//read configuration
load("/YACReader.conf");
}
Configuration::Configuration(const Configuration & conf)
{
//nothing
}
void Configuration::load(const QString & path)
{
//load default configuration
defaultPath = ".";
magnifyingGlassSize = QSize(350,175);
gotoSlideSize = QSize(126,200); //normal
//gotoSlideSize = QSize(79,125); //small
//gotoSlideSize = QSize(173,275); //big
//gotoSlideSize = QSize(220,350); //huge
zoomLevel = 0.5;
adjustToWidth = true;
flowType = PictureFlow::Strip;
fullScreen = false;
fitToWidthRatio = 1;
windowSize = QSize(0,0);
maximized = false;
doublePage = false;
adjustToFullSize = false;
backgroundColor = QColor(0,0,0);
alwaysOnTop = false;
//load from file
QFile f(QCoreApplication::applicationDirPath()+path);
f.open(QIODevice::ReadOnly);
QTextStream txtS(&f);
QString content = txtS.readAll();
QStringList lines = content.split('\n');
QString line,name;
int i=0;
foreach(line,lines)
{
if((i%2)==0)
{
name = line.trimmed();
}
else
{
if(name==PATH)
defaultPath = line.trimmed();
else
if(name==MAG_GLASS_SIZE)
{
QStringList values = line.split(',');
magnifyingGlassSize = QSize(values[0].toInt(),values[1].toInt());
}
else
if(name==ZOOM_LEVEL)
zoomLevel = line.toFloat();
else
if(name==SLIDE_SIZE)
{
int height = line.toInt();
gotoSlideSize = QSize(static_cast<int>(height/SLIDE_ASPECT_RATIO),height);
}
else
if(name==FIT)
adjustToWidth = line.toInt();
else
if(name==FLOW_TYPE)
flowType = (PictureFlow::FlowType)line.toInt();
else
if(name==FULLSCREEN)
fullScreen = line.toInt();
else
if(name==FIT_TO_WIDTH_RATIO)
fitToWidthRatio = line.toFloat();
else
if(name==POS)
{
QStringList l = line.split(',');
windowPos = QPoint(l[0].toInt(),l[1].toInt());
}
else
if(name==SIZE)
{
QStringList l = line.split(',');
windowSize = QSize(l[0].toInt(),l[1].toInt());
}
else
if(name==MAXIMIZED)
maximized = line.toInt();
else
if(name==DOUBLE_PAGE)
doublePage = line.toInt();
else
if(name==ADJUST_TO_FULL_SIZE)
adjustToFullSize = line.toInt();
else
if(name==BACKGROUND_COLOR)
{
QStringList l = line.split(',');
backgroundColor = QColor(l[0].toInt(),l[1].toInt(),l[2].toInt());
}
else
if(name==ALWAYS_ON_TOP)
alwaysOnTop = line.toInt();
}
i++;
}
}
void Configuration::save()
{
QFile f(QCoreApplication::applicationDirPath()+"/YACReader.conf");
if(!f.open(QIODevice::WriteOnly))
{
QMessageBox::critical(NULL,tr("Saving config file...."),tr("There was a problem saving YACReader configuration. Please, check if you have enough permissions in the YACReader root folder."));
}
else
{
QTextStream txtS(&f);
txtS << PATH << "\n";
txtS << defaultPath << "\n";
txtS << MAG_GLASS_SIZE << "\n";
txtS << magnifyingGlassSize.width() <<","<< magnifyingGlassSize.height() << "\n";
txtS << ZOOM_LEVEL << "\n";
txtS << zoomLevel << "\n";
txtS << SLIDE_SIZE << "\n";
txtS << gotoSlideSize.height() << "\n";
txtS << FIT << "\n";
txtS << (int)adjustToWidth << "\n";
txtS << FLOW_TYPE << "\n";
txtS << (int)flowType << "\n";
txtS << FULLSCREEN << "\n";
txtS << (int)fullScreen << "\n";
txtS << FIT_TO_WIDTH_RATIO << "\n";
txtS << fitToWidthRatio << "\n";
txtS << POS << "\n";
txtS << windowPos.x() << "," << windowPos.y() << "\n";
txtS << SIZE << "\n";
txtS << windowSize.width() << "," << windowSize.height() << "\n";
txtS << MAXIMIZED << "\n";
txtS << (int)maximized << "\n";
txtS << DOUBLE_PAGE << "\n";
txtS << (int)doublePage << "\n";
txtS << ADJUST_TO_FULL_SIZE << "\n";
txtS << (int) adjustToFullSize << "\n";
txtS << BACKGROUND_COLOR << "\n";
txtS << backgroundColor.red() << "," << backgroundColor.green() << "," << backgroundColor.blue() << "\n";
txtS << ALWAYS_ON_TOP << "\n";
txtS << (int)alwaysOnTop << "\n";
}
}

77
YACReader/configuration.h Normal file
View File

@ -0,0 +1,77 @@
#ifndef __CONFIGURATION_H
#define __CONFIGURATION_H
#include <QString>
#include <QSize>
#include <QObject>
#include "pictureflow.h"
#define CONF_FILE_PATH "."
#define SLIDE_ASPECT_RATIO 1.585
class Configuration : public QObject
{
Q_OBJECT
private:
QString defaultPath;
//configuration properties
QSize magnifyingGlassSize;
QSize gotoSlideSize;
float zoomLevel;
bool adjustToWidth;
bool fullScreen;
PictureFlow::FlowType flowType;
float fitToWidthRatio;
QPoint windowPos;
QSize windowSize;
bool maximized;
bool doublePage;
bool alwaysOnTop;
bool adjustToFullSize;
QColor backgroundColor;
Configuration();
Configuration(const Configuration & conf);
void load(const QString & path = CONF_FILE_PATH);
public:
static Configuration & getConfiguration()
{
static Configuration configuration;
return configuration;
};
QString getDefaultPath() { return defaultPath; };
void setDefaultPath(QString defaultPath){this->defaultPath = defaultPath;};
QSize getMagnifyingGlassSize() { return magnifyingGlassSize;};
void setMagnifyingGlassSize(const QSize & mgs) { magnifyingGlassSize = mgs;};
QSize getGotoSlideSize() { return gotoSlideSize;};
void setGotoSlideSize(const QSize & gss) { gotoSlideSize = gss;};
float getZoomLevel() { return zoomLevel;};
void setZoomLevel(float zl) { zoomLevel = zl;};
bool getAdjustToWidth() {return adjustToWidth;};
void setAdjustToWidth(bool atw=true) {adjustToWidth = atw;};
PictureFlow::FlowType getFlowType(){return flowType;};
void setFlowType(PictureFlow::FlowType type){flowType = type;};
bool getFullScreen(){return fullScreen;};
void setFullScreen(bool f){fullScreen = f;};
float getFitToWidthRatio(){return fitToWidthRatio;};
void setFitToWidthRatio(float r){fitToWidthRatio = r;};
QPoint getPos(){return windowPos;};
void setPos(QPoint p){windowPos = p;};
QSize getSize(){return windowSize;};
void setSize(QSize s){windowSize = s;};
bool getMaximized(){return maximized;};
void setMaximized(bool b){maximized = b;};
bool getDoublePage(){return doublePage;};
void setDoublePage(bool b){doublePage = b;};
void setAdjustToFullSize(bool b){adjustToFullSize = b;};
bool getAdjustToFullSize(){return adjustToFullSize;};
void setBackgroundColor(const QColor& color){backgroundColor = color;};
QColor getBackgroundColor(){return backgroundColor;};
void setAlwaysOnTop(bool b){alwaysOnTop = b;};
bool getAlwaysOnTop(){return alwaysOnTop;};
void save();
};
#endif

15
YACReader/files.qrc Normal file
View File

@ -0,0 +1,15 @@
<RCC>
<qresource>
<file>../files/about.html</file>
<file>../files/helpYACReader.html</file>
<file>../files/shortcuts.html</file>
<file>../files/shortcuts2.html</file>
<file>../files/translator.html</file>
<file>./yacreader_es.qm</file>
</qresource>
<qresource lang="es_ES">
<file alias="/files/about.html">../files/about_es_ES.html</file>
<file alias="/files/helpYACReader.html">../files/helpYACReader_es_ES.html</file>
</qresource>
</RCC>

75
YACReader/goto_dialog.cpp Normal file
View File

@ -0,0 +1,75 @@
#include "goto_dialog.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QIntValidator>
GoToDialog::GoToDialog(QWidget * parent)
:QDialog(parent)
{
setupUI();
}
void GoToDialog::setupUI()
{
textLabel = new QLabel(tr("Page : "));
pageNumber = new QLineEdit;
v = new QIntValidator(this);
v->setBottom(1);
pageNumber->setValidator(v);
textLabel->setBuddy(pageNumber);
textLabel->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
accept = new QPushButton(tr("Go To"));
connect(accept,SIGNAL(clicked()),this,SLOT(goTo()));
cancel = new QPushButton(tr("Cancel"));
connect(cancel,SIGNAL(clicked()),this,SLOT(close()));
QHBoxLayout *topLayout = new QHBoxLayout;
topLayout->addWidget(textLabel);
topLayout->addWidget(pageNumber);
QHBoxLayout *bottomLayout = new QHBoxLayout;
bottomLayout->addStretch();
bottomLayout->addWidget(accept);
bottomLayout->addWidget(cancel);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(numPagesLabel = new QLabel(tr("Total pages : ")));
mainLayout->addLayout(topLayout);
mainLayout->addStretch();
mainLayout->addLayout(bottomLayout);
QHBoxLayout *imgMainLayout = new QHBoxLayout;
QLabel * imgLabel = new QLabel();
QPixmap p(":/images/goto.png");
imgLabel->setPixmap(p);
imgMainLayout->addWidget(imgLabel);
imgMainLayout->addLayout(mainLayout);
setLayout(imgMainLayout);
setWindowTitle(tr("Go to..."));
setModal (true);
}
void GoToDialog::goTo()
{
unsigned int page = pageNumber->text().toInt();
pageNumber->clear();
if(page >= 1)
emit(goToPage(page));
close();
}
void GoToDialog::setNumPages(unsigned int numPages)
{
numPagesLabel->setText(tr("Total pages : ")+QString::number(numPages));
v->setTop(numPages);
}

31
YACReader/goto_dialog.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef __GOTODIALOG_H
#define __GOTODIALOG_H
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QIntValidator>
class GoToDialog : public QDialog
{
Q_OBJECT
public:
GoToDialog(QWidget * parent = 0);
private:
QLabel * numPagesLabel;
QLabel * textLabel;
QLineEdit * pageNumber;
QIntValidator * v;
QPushButton * accept;
QPushButton * cancel;
void setupUI();
public slots:
void goTo();
void setNumPages(unsigned int numPages);
signals:
void goToPage(unsigned int page);
};
#endif

373
YACReader/goto_flow.cpp Normal file
View File

@ -0,0 +1,373 @@
#include "goto_flow.h"
#include "configuration.h"
#include "comic.h"
#include "custom_widgets.h"
#include <QVBoxLayout>
#include <QSize>
#include <QImage>
#include <QLabel>
#include <QPushButton>
#include <QMutex>
#include <QCoreApplication>
/*#define WIDTH 126
#define HEIGHT 200*/
QMutex mutexGoToFlow;
GoToFlow::GoToFlow(QWidget *parent,PictureFlow::FlowType flowType)
:QWidget(parent),ready(false)
{
updateTimer = new QTimer;
connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateImageData()));
worker = new PageLoader;
QVBoxLayout * layout = new QVBoxLayout(this);
flow = new YACReaderFlow(this,flowType);
flow->setReflectionEffect(PictureFlow::PlainReflection);
imageSize = Configuration::getConfiguration().getGotoSlideSize();
flow->setSlideSize(imageSize);
connect(flow,SIGNAL(centerIndexChanged(int)),this,SLOT(setPageNumber(int)));
connect(flow,SIGNAL(selected(unsigned int)),this,SLOT(goTo()));
QHBoxLayout * bottom = new QHBoxLayout(this);
bottom->addStretch();
bottom->addWidget(new QLabel(tr("Page : "),this));
bottom->addWidget(edit = new QLineEdit(this));
v = new QIntValidator(this);
v->setBottom(1);
edit->setValidator(v);
edit->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
edit->setFixedWidth(40);
edit->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Minimum));
centerButton = new QPushButton(this);
centerButton->setIcon(QIcon(":/images/center.png"));
connect(centerButton,SIGNAL(clicked()),this,SLOT(centerSlide()));
bottom->addWidget(centerButton);
goToButton = new QPushButton(this);
goToButton->setIcon(QIcon(":/images/goto.png"));
connect(goToButton,SIGNAL(clicked()),this,SLOT(goTo()));
bottom->addWidget(goToButton);
bottom->addStretch();
layout->addWidget(flow);
layout->addLayout(bottom);
layout->setStretchFactor(flow,1);
layout->setStretchFactor(bottom,0);
layout->setMargin(0);
layout->setSpacing(0);
setLayout(layout);
this->setAutoFillBackground(true);
resize(static_cast<int>(5*imageSize.width()),static_cast<int>(imageSize.height()*1.7));
//install eventFilter
//flow->installEventFilter(this);
edit->installEventFilter(this);
centerButton->installEventFilter(this);
goToButton->installEventFilter(this);
connect(edit,SIGNAL(returnPressed()),goToButton,SIGNAL(clicked()));
this->setCursor(QCursor(Qt::ArrowCursor));
}
void GoToFlow::goTo()
{
//emit(goToPage(flow->centerIndex()+1));
emit(goToPage(edit->text().toInt()));
}
void GoToFlow::setPageNumber(int page)
{
edit->setText(QString::number(page+1));
}
void GoToFlow::centerSlide()
{
int page = edit->text().toInt()-1;
int distance = flow->centerIndex()-page;
if(abs(distance)>10)
{
if(distance<0)
flow->setCenterIndex(flow->centerIndex()+(-distance)-10);
else
flow->setCenterIndex(flow->centerIndex()-distance+10);
}
flow->showSlide(page);
}
void GoToFlow::centerSlide(int slide)
{
if(flow->centerIndex()!=slide)
{
flow->setCenterIndex(slide);
if(ready)// load images if pages are loaded.
{
//worker->reset(); //BUG FIXED : image didn't load if worker was working
preload();
}
}
}
void GoToFlow::setNumSlides(unsigned int slides)
{
// numPagesLabel->setText(tr("Total pages : ")+QString::number(slides));
// numPagesLabel->adjustSize();
imagesReady.clear();
imagesReady.fill(false,slides);
rawImages.clear();
rawImages.resize(slides);
v->setTop(slides);
SlideInitializer * si = new SlideInitializer(flow,slides);
imagesLoaded.clear();
imagesLoaded.fill(false,slides);
imagesSetted.clear();
imagesSetted.fill(false,slides);
numImagesLoaded = 0;
connect(flow, SIGNAL(centerIndexChanged(int)), this, SLOT(preload()));
ready = true;
worker->reset();
si->start();
}
void GoToFlow::reset()
{
updateTimer->stop();
/*imagesLoaded.clear();
numImagesLoaded = 0;
imagesReady.clear();
rawImages.clear();*/
ready = false;
}
void GoToFlow::setImageReady(int index,const QByteArray & image)
{
rawImages[index]=image;
imagesReady[index]=true;
preload();
}
void GoToFlow::preload()
{
if(numImagesLoaded < imagesLoaded.size())
updateTimer->start(30); //TODO comprobar rendimiento, antes era 70
}
void GoToFlow::updateImageData()
{
// can't do anything, wait for the next possibility
if(worker->busy())
return;
// set image of last one
int idx = worker->index();
if( idx >= 0 && !worker->result().isNull())
{
if(!imagesSetted[idx])
{
flow->setSlide(idx, worker->result());
imagesSetted[idx] = true;
numImagesLoaded++;
rawImages[idx].clear();; //release memory
}
}
// try to load only few images on the left and right side
// i.e. all visible ones plus some extra
#define COUNT 8
int indexes[2*COUNT+1];
int center = flow->centerIndex();
indexes[0] = center;
for(int j = 0; j < COUNT; j++)
{
indexes[j*2+1] = center+j+1;
indexes[j*2+2] = center-j-1;
}
for(int c = 0; c < 2*COUNT+1; c++)
{
int i = indexes[c];
if((i >= 0) && (i < flow->slideCount()))
if(!imagesLoaded[i]&&imagesReady[i])//slide(i).isNull())
{
// schedule thumbnail generation
imagesLoaded[i]=true;
worker->generate(i, flow->slideSize(),rawImages[i]);
return;
}
}
// no need to generate anything? stop polling...
updateTimer->stop();
}
bool GoToFlow::eventFilter(QObject *target, QEvent *event)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
int key = keyEvent->key();
if((key==Qt::Key_Return)||
(key==Qt::Key_Enter)||
(key==Qt::Key_Space)||
(key==Qt::Key_Left)||
(key==Qt::Key_Right)||
(key==Qt::Key_S))
this->keyPressEvent(keyEvent);
}
return QWidget::eventFilter(target, event);
}
void GoToFlow::keyPressEvent(QKeyEvent* event)
{
switch (event->key())
{
case Qt::Key_Return: case Qt::Key_Enter:
goTo();
centerSlide();
break;
case Qt::Key_Space:
centerSlide();
break;
case Qt::Key_S:
QCoreApplication::sendEvent(this->parent(),event);
break;
case Qt::Key_Left: case Qt::Key_Right:
QCoreApplication::sendEvent(flow,event);
}
event->accept();
}
void GoToFlow::wheelEvent(QWheelEvent * event)
{
if(event->delta()<0)
flow->showNext();
else
flow->showPrevious();
event->accept();
}
void GoToFlow::setFlowType(PictureFlow::FlowType flowType)
{
flow->setFlowType(flowType);
}
void GoToFlow::updateSize() //TODO : fix. it doesn't work.
{
imageSize = Configuration::getConfiguration().getGotoSlideSize();
flow->setSlideSize(imageSize);
resize(static_cast<int>(5*imageSize.width()),static_cast<int>(imageSize.height()*1.7));
}
//-----------------------------------------------------------------------------
//SlideInitializer
//-----------------------------------------------------------------------------
SlideInitializer::SlideInitializer(PictureFlow * flow,int slides)
:QThread(),_flow(flow),_slides(slides)
{
}
void SlideInitializer::run()
{
mutexGoToFlow.lock();
_flow->clear();
for(int i=0;i<_slides;i++)
_flow->addSlide(QImage());
_flow->setCenterIndex(0);
mutexGoToFlow.unlock();
}
//-----------------------------------------------------------------------------
//PageLoader
//-----------------------------------------------------------------------------
PageLoader::PageLoader():
QThread(), restart(false), working(false), idx(-1)
{
}
PageLoader::~PageLoader()
{
mutexGoToFlow.lock();
condition.wakeOne();
mutexGoToFlow.unlock();
wait();
}
bool PageLoader::busy() const
{
return isRunning() ? working : false;
}
void PageLoader::generate(int index, QSize size,const QByteArray & rImage)
{
mutexGoToFlow.lock();
this->idx = index;
//this->img = QImage();
this->size = size;
this->rawImage = rImage;
mutexGoToFlow.unlock();
if (!isRunning())
start();
else
{
// already running, wake up whenever ready
restart = true;
condition.wakeOne();
}
}
void PageLoader::run()
{
for(;;)
{
// copy necessary data
mutexGoToFlow.lock();
this->working = true;
//int idx = this->idx;
QImage image;
image.loadFromData(this->rawImage);
// let everyone knows it is ready
image = image.scaled(this->size,Qt::KeepAspectRatio,Qt::SmoothTransformation);
mutexGoToFlow.unlock();
mutexGoToFlow.lock();
this->working = false;
this->img = image;
mutexGoToFlow.unlock();
// put to sleep
mutexGoToFlow.lock();
if (!this->restart)
condition.wait(&mutexGoToFlow);
restart = false;
mutexGoToFlow.unlock();
}
}

105
YACReader/goto_flow.h Normal file
View File

@ -0,0 +1,105 @@
#ifndef __GOTO_FLOW_H
#define __GOTO_FLOW_H
#include <QLineEdit>
#include <QPushButton>
#include <QPixmap>
#include <QThread>
#include <QSize>
#include <QIntValidator>
#include <QWaitCondition>
#include <QObject>
#include <QEvent>
#include <QLabel>
#include "custom_widgets.h"
class Comic;
class SlideInitializer;
class PageLoader;
class GoToFlow : public QWidget
{
Q_OBJECT
public:
GoToFlow(QWidget* parent = 0,PictureFlow::FlowType flowType = PictureFlow::CoverFlowLike);
bool ready; //comic is ready for read.
void keyPressEvent(QKeyEvent* event);
bool eventFilter(QObject *target, QEvent *event);
private:
YACReaderFlow * flow;
QLineEdit * edit;
QIntValidator * v;
QPushButton * centerButton;
QPushButton * goToButton;
Comic * comic;
QSize imageSize;
QVector<bool> imagesLoaded;
QVector<bool> imagesSetted;
uint numImagesLoaded;
QVector<bool> imagesReady;
QVector<QByteArray> rawImages;
QTimer* updateTimer;
PageLoader* worker;
virtual void wheelEvent(QWheelEvent * event);
private slots:
void preload();
void updateImageData();
public slots:
void goTo();
void setPageNumber(int page);
void centerSlide();
void centerSlide(int slide);
void reset();
void setNumSlides(unsigned int slides);
void setImageReady(int index,const QByteArray & image);
void setFlowType(PictureFlow::FlowType flowType);
void updateSize();
signals:
void goToPage(unsigned int page);
};
//-----------------------------------------------------------------------------
//SlideInitializer
//-----------------------------------------------------------------------------
class SlideInitializer : public QThread
{
public:
SlideInitializer(PictureFlow * flow,int slides);
private:
PictureFlow * _flow;
int _slides;
void run();
};
//-----------------------------------------------------------------------------
//PageLoader
//-----------------------------------------------------------------------------
class PageLoader : public QThread
{
public:
PageLoader();
~PageLoader();
// returns FALSE if worker is still busy and can't take the task
bool busy() const;
void generate(int index, QSize size,const QByteArray & rImage);
void reset(){idx = -1;};
int index() const { return idx; }
QImage result() const { return img; }
protected:
void run();
private:
QWaitCondition condition;
bool restart;
bool working;
int idx;
QSize size;
QImage img;
QByteArray rawImage;
};
#endif

BIN
YACReader/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

1
YACReader/icon.rc Normal file
View File

@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "icon.ico"

67
YACReader/images.qrc Normal file
View File

@ -0,0 +1,67 @@
<RCC>
<qresource>
<file>../images/open.png</file>
<file>../images/openFolder.png</file>
<file>../images/next.png</file>
<file>../images/prev.png</file>
<file>../images/icon.png</file>
<file>../images/zoom.png</file>
<file>../images/fit.png</file>
<file>../images/goto.png</file>
<file>../images/help.png</file>
<file>../images/center.png</file>
<file>../images/options.png</file>
<file>../images/comicFolder.png</file>
<file>../images/save.png</file>
<file>../images/rotateL.png</file>
<file>../images/rotateR.png</file>
<file>../images/flow1.png</file>
<file>../images/flow2.png</file>
<file>../images/flow3.png</file>
<file>../images/bookmark.png</file>
<file>../images/setBookmark.png</file>
<file>../images/notCover.png</file>
<file>../images/previousComic.png</file>
<file>../images/nextComic.png</file>
<file>../images/deleteLibrary.png</file>
<file>../images/properties.png</file>
<file>../images/doublePage.png</file>
<file>../images/shortcuts.png</file>
<file>../images/close.png</file>
<file>../images/up.png</file>
<file>../images/down.png</file>
<file>../images/dictionary.png</file>
<file>../images/alwaysOnTop.png</file>
<file>../images/adjustToFullSize.png</file>
<file>../images/helpImages/open.png</file>
<file>../images/helpImages/openFolder.png</file>
<file>../images/helpImages/next.png</file>
<file>../images/helpImages/prev.png</file>
<file>../images/helpImages/icon.png</file>
<file>../images/helpImages/zoom.png</file>
<file>../images/helpImages/fit.png</file>
<file>../images/helpImages/goto.png</file>
<file>../images/helpImages/help.png</file>
<file>../images/helpImages/center.png</file>
<file>../images/helpImages/options.png</file>
<file>../images/helpImages/comicFolder.png</file>
<file>../images/helpImages/save.png</file>
<file>../images/helpImages/rotateL.png</file>
<file>../images/helpImages/rotateR.png</file>
<file>../images/helpImages/flow1.png</file>
<file>../images/helpImages/flow2.png</file>
<file>../images/helpImages/flow3.png</file>
<file>../images/helpImages/bookmark.png</file>
<file>../images/helpImages/setBookmark.png</file>
<file>../images/helpImages/notCover.png</file>
<file>../images/helpImages/previousComic.png</file>
<file>../images/helpImages/nextComic.png</file>
<file>../images/helpImages/deleteLibrary.png</file>
<file>../images/helpImages/properties.png</file>
<file>../images/helpImages/doublePage.png</file>
<file>../images/helpImages/shortcuts.png</file>
<file>../images/helpImages/keyboard.png</file>
<file>../images/helpImages/mouse.png</file>
<file>../images/helpImages/speaker.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,267 @@
#include "magnifying_glass.h"
#include "viewer.h"
MagnifyingGlass::MagnifyingGlass(int w, int h, QWidget * parent)
:QLabel(parent),zoomLevel(0.5)
{
setup(QSize(w,h));
}
MagnifyingGlass::MagnifyingGlass(const QSize & size, QWidget * parent)
:QLabel(parent),zoomLevel(0.5)
{
setup(size);
}
void MagnifyingGlass::setup(const QSize & size)
{
resize(size);
setScaledContents(true);
setMouseTracking(true);
setCursor(QCursor(QBitmap(1,1),QBitmap(1,1)));
}
void MagnifyingGlass::mouseMoveEvent(QMouseEvent * event)
{
updateImage();
}
void MagnifyingGlass::updateImage(int x, int y)
{
//image section augmented
int zoomWidth = static_cast<int>(width() * zoomLevel);
int zoomHeight = static_cast<int>(height() * zoomLevel);
Viewer * p = (Viewer *)parent();
int currentPos = p->verticalScrollBar()->sliderPosition();
const QPixmap * image = p->pixmap();
int iWidth = image->width();
int iHeight = image->height();
float wFactor = static_cast<float>(iWidth) / p->widget()->width();
float hFactor = static_cast<float>(iHeight) / p->widget()->height();
zoomWidth *= wFactor;
zoomHeight *= hFactor;
if(p->verticalScrollBar()->minimum()==p->verticalScrollBar()->maximum())
{
int xp = static_cast<int>(((x-p->widget()->pos().x())*wFactor)-zoomWidth/2);
int yp = static_cast<int>((y-p->widget()->pos().y()+currentPos)*hFactor-zoomHeight/2);
int xOffset=0;
int yOffset=0;
int zw=zoomWidth;
int zh=zoomHeight;
//int wOffset,hOffset=0;
bool outImage = false;
if(xp<0)
{
xOffset = -xp;
xp=0;
zw = zw - xOffset;
outImage = true;
}
if(yp<0)
{
yOffset = -yp;
yp=0;
zh = zh - yOffset;
outImage = true;
}
if(xp+zoomWidth >= image->width())
{
zw -= xp+zw - image->width();
outImage = true;
}
if(yp+zoomHeight >= image->height())
{
zh -= yp+zh - image->height();
outImage = true;
}
if(outImage)
{
QImage img(zoomWidth,zoomHeight,QImage::Format_RGB32);
img.fill(0);
if(zw>0&&zh>0)
{
QPainter painter(&img);
painter.drawPixmap(xOffset,yOffset,p->pixmap()->copy(xp,yp,zw,zh));
}
setPixmap(QPixmap().fromImage(img));
}
else
setPixmap(p->pixmap()->copy(xp,yp,zoomWidth,zoomHeight));
}
else
{
int xp = static_cast<int>(((x-p->widget()->pos().x())*wFactor)-zoomWidth/2);
int yp = static_cast<int>((y+currentPos)*hFactor-zoomHeight/2);
int xOffset=0;
int yOffset=0;
int zw=zoomWidth;
int zh=zoomHeight;
//int wOffset,hOffset=0;
bool outImage = false;
if(xp<0)
{
xOffset = -xp;
xp=0;
zw = zw - xOffset;
outImage = true;
}
if(yp<0)
{
yOffset = -yp;
yp=0;
zh = zh - yOffset;
outImage = true;
}
if(xp+zoomWidth >= image->width())
{
zw -= xp+zw - image->width();
outImage = true;
}
if(yp+zoomHeight >= image->height())
{
zh -= yp+zh - image->height();
outImage = true;
}
if(outImage)
{
QImage img(zoomWidth,zoomHeight,QImage::Format_RGB32);
img.fill(0);
if(zw>0&&zh>0)
{
QPainter painter(&img);
painter.drawPixmap(xOffset,yOffset,p->pixmap()->copy(xp,yp,zw,zh));
}
setPixmap(QPixmap().fromImage(img));
}
else
setPixmap(p->pixmap()->copy(xp,yp,zoomWidth,zoomHeight));
}
move(static_cast<int>(x-float(width())/2),static_cast<int>(y-float(height())/2));
}
void MagnifyingGlass::updateImage()
{
if(isVisible())
{
QPoint p = QPoint(cursor().pos().x(),cursor().pos().y());
p = this->parentWidget()->mapFromGlobal(p);
updateImage(p.x(),p.y());
}
}
void MagnifyingGlass::wheelEvent(QWheelEvent * event)
{
switch(event->modifiers())
{
//size
case Qt::NoModifier:
if(event->delta()<0)
sizeUp();
else
sizeDown();
break;
//size height
case Qt::ControlModifier:
if(event->delta()<0)
heightUp();
else
heightDown();
break;
//size width
case Qt::AltModifier:
if(event->delta()<0)
widthUp();
else
widthDown();
break;
//zoom level
case Qt::ShiftModifier:
if(event->delta()<0)
zoomIn();
else
zoomOut();
break;
}
updateImage();
event->setAccepted(true);
}
void MagnifyingGlass::zoomIn()
{
if(zoomLevel>0.2)
zoomLevel -= 0.025;
}
void MagnifyingGlass::zoomOut()
{
if(zoomLevel<0.9)
zoomLevel += 0.025;
}
void MagnifyingGlass::sizeUp()
{
Viewer * p = (Viewer *)parent();
if(width()<(p->width()*0.90))
resize(width()+30,height()+15);
}
void MagnifyingGlass::sizeDown()
{
if(width()>175)
resize(width()-30,height()-15);
}
void MagnifyingGlass::heightUp()
{
Viewer * p = (Viewer *)parent();
if(height()<(p->height()*0.90))
resize(width(),height()+15);
}
void MagnifyingGlass::heightDown()
{
if(height()>80)
resize(width(),height()-15);
}
void MagnifyingGlass::widthUp()
{
Viewer * p = (Viewer *)parent();
if(width()<(p->width()*0.90))
resize(width()+30,height());
}
void MagnifyingGlass::widthDown()
{
if(width()>175)
resize(width()-30,height());
}
void MagnifyingGlass::keyPressEvent(QKeyEvent *event)
{
bool validKey = false;
switch (event->key())
{
case Qt::Key_Plus:
sizeUp();
validKey = true;
break;
case Qt::Key_Minus:
sizeDown();
validKey = true;
break;
case Qt::Key_Underscore:
zoomOut();
validKey = true;
break;
case Qt::Key_Asterisk:
zoomIn();
validKey = true;
break;
}
updateImage();
if(validKey)
event->setAccepted(true);
}

View File

@ -0,0 +1,34 @@
#ifndef __MAGNIFYING_GLASS
#define __MAGNIFYING_GLASS
#include <QLabel>
#include <QtGui>
#include <QMouseEvent>
#include <QWidget>
class MagnifyingGlass : public QLabel
{
Q_OBJECT
private:
float zoomLevel;
void setup(const QSize & size);
void keyPressEvent(QKeyEvent * event);
public:
MagnifyingGlass(int width,int height,QWidget * parent);
MagnifyingGlass(const QSize & size, QWidget * parent);
void mouseMoveEvent(QMouseEvent * event);
public slots:
void updateImage(int x, int y);
void updateImage();
void wheelEvent(QWheelEvent * event);
void zoomIn();
void zoomOut();
void sizeUp();
void sizeDown();
void heightUp();
void heightDown();
void widthUp();
void widthDown();
};
#endif

34
YACReader/main.cpp Normal file
View File

@ -0,0 +1,34 @@
#include <QApplication>
#include <QPixmap>
#include <QLabel>
//#include <QMetaObject>
#include <QPushButton>
#include <QMainWindow>
#include <QtCore>
#include <QThread>
#include <QFile>
#include <QDataStream>
#include <QTranslator>
#include "main_window_viewer.h"
#include "configuration.h"
int main(int argc, char * argv[])
{
QApplication app(argc, argv);
QTranslator translator;
QString sufix = QLocale::system().name();
translator.load(":/yacreader_"+sufix);
app.installTranslator(&translator);
app.setApplicationName("YACReader");
MainWindowViewer mwv;
mwv.show();
int ret = app.exec();
Configuration::getConfiguration().save();
return ret;
}

View File

@ -0,0 +1,680 @@
#include "main_window_viewer.h"
#include "configuration.h"
#include "viewer.h"
#include "goto_dialog.h"
#include "custom_widgets.h"
#include "options_dialog.h"
#include "check_new_version.h"
#include "comic.h"
#include "bookmarks_dialog.h"
#include "shortcuts_dialog.h"
MainWindowViewer::MainWindowViewer()
:QMainWindow(),fullscreen(false),toolbars(true),alwaysOnTop(false),currentDirectory("."),currentDirectoryImgDest(".")
{
loadConfiguration();
setupUI();
}
void MainWindowViewer::loadConfiguration()
{
Configuration & config = Configuration::getConfiguration();
currentDirectory = config.getDefaultPath();
fullscreen = config.getFullScreen();
}
void MainWindowViewer::setupUI()
{
setWindowIcon(QIcon(":/images/icon.png"));
viewer = new Viewer(this);
connect(viewer,SIGNAL(reset()),this,SLOT(disableActions()));
setCentralWidget(viewer);
int heightDesktopResolution = QApplication::desktop()->screenGeometry().height();
int widthDesktopResolution = QApplication::desktop()->screenGeometry().width();
int height,width;
height = static_cast<int>(heightDesktopResolution*0.84);
width = static_cast<int>(height*0.70);
Configuration & conf = Configuration::getConfiguration();
QPoint p = conf.getPos();
QSize s = conf.getSize();
if(s.width()!=0)
{
move(p);
resize(s);
}
else
{
move(QPoint((widthDesktopResolution-width)/2,((heightDesktopResolution-height)-40)/2));
resize(QSize(width,height));
}
had = new HelpAboutDialog(this); //TODO load data
had->loadAboutInformation(":/files/about.html");
had->loadHelp(":/files/helpYACReader.html");
optionsDialog = new OptionsDialog(this);
connect(optionsDialog,SIGNAL(accepted()),viewer,SLOT(updateOptions()));
shortcutsDialog = new ShortcutsDialog(this);
createActions();
createToolBars();
if(QCoreApplication::argc()>1)
{
//TODO: new method open(QString)
QString pathFile = QCoreApplication::arguments().at(1);
currentDirectory = pathFile;
QFileInfo fi(pathFile);
getSiblingComics(fi.absolutePath(),fi.fileName());
viewer->open(pathFile);
enableActions();
}
versionChecker = new HttpVersionChecker();
connect(versionChecker,SIGNAL(newVersionDetected()),
this,SLOT(newVersion()));
versionChecker->get();
viewer->setFocusPolicy(Qt::StrongFocus);
setWindowTitle("YACReader");
if(Configuration::getConfiguration().getAlwaysOnTop())
{
setWindowFlags(this->windowFlags() | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint);
}
if(fullscreen)
toFullScreen();
if(conf.getMaximized())
showMaximized();
setAcceptDrops(true);
}
void MainWindowViewer::createActions()
{
openAction = new QAction(tr("&Open"),this);
openAction->setShortcut(tr("O"));
openAction->setIcon(QIcon(":/images/open.png"));
openAction->setToolTip(tr("Open a comic"));
connect(openAction, SIGNAL(triggered()), this, SLOT(open()));
openFolderAction = new QAction(tr("Open Folder"),this);
openFolderAction->setShortcut(tr("Ctrl+O"));
openFolderAction->setIcon(QIcon(":/images/openFolder.png"));
openFolderAction->setToolTip(tr("Open image folder"));
connect(openFolderAction, SIGNAL(triggered()), this, SLOT(openFolder()));
saveImageAction = new QAction(tr("Save"),this);
saveImageAction->setIcon(QIcon(":/images/save.png"));
saveImageAction->setToolTip(tr("Save current page"));
saveImageAction->setDisabled(true);
connect(saveImageAction,SIGNAL(triggered()),this,SLOT(saveImage()));
openPreviousComicAction = new QAction(tr("Previous Comic"),this);
openPreviousComicAction->setIcon(QIcon(":/images/previousComic.png"));
openPreviousComicAction->setShortcut(Qt::CTRL + Qt::Key_Left);
openPreviousComicAction->setToolTip(tr("Open previous comic"));
openPreviousComicAction->setDisabled(true);
connect(openPreviousComicAction,SIGNAL(triggered()),this,SLOT(openPreviousComic()));
openNextComicAction = new QAction(tr("Next Comic"),this);
openNextComicAction->setIcon(QIcon(":/images/nextComic.png"));
openNextComicAction->setShortcut(Qt::CTRL + Qt::Key_Right);
openNextComicAction->setToolTip(tr("Open next comic"));
openNextComicAction->setDisabled(true);
connect(openNextComicAction,SIGNAL(triggered()),this,SLOT(openNextComic()));
prevAction = new QAction(tr("&Previous"),this);
prevAction->setIcon(QIcon(":/images/prev.png"));
prevAction->setShortcut(Qt::Key_Left);
prevAction->setToolTip(tr("Go to previous page"));
prevAction->setDisabled(true);
connect(prevAction, SIGNAL(triggered()),viewer,SLOT(prev()));
nextAction = new QAction(tr("&Next"),this);
nextAction->setIcon(QIcon(":/images/next.png"));
nextAction->setShortcut(Qt::Key_Right);
nextAction->setToolTip(tr("Go to next page"));
nextAction->setDisabled(true);
connect(nextAction, SIGNAL(triggered()),viewer,SLOT(next()));
adjustWidth = new QAction(tr("Fit Width"),this);
adjustWidth->setShortcut(tr("A"));
adjustWidth->setIcon(QIcon(":/images/fit.png"));
adjustWidth->setCheckable(true);
adjustWidth->setDisabled(true);
adjustWidth->setChecked(Configuration::getConfiguration().getAdjustToWidth());
adjustWidth->setToolTip(tr("Fit image to ..."));
//adjustWidth->setIcon(QIcon(":/images/fitWidth.png"));
connect(adjustWidth, SIGNAL(triggered()),this,SLOT(changeFit()));
leftRotationAction = new QAction(tr("Rotate image to the left"),this);
leftRotationAction->setShortcut(tr("L"));
leftRotationAction->setIcon(QIcon(":/images/rotateL.png"));
leftRotationAction->setDisabled(true);
connect(leftRotationAction, SIGNAL(triggered()),viewer,SLOT(rotateLeft()));
rightRotationAction = new QAction(tr("Rotate image to the right"),this);
rightRotationAction->setShortcut(tr("R"));
rightRotationAction->setIcon(QIcon(":/images/rotateR.png"));
rightRotationAction->setDisabled(true);
connect(rightRotationAction, SIGNAL(triggered()),viewer,SLOT(rotateRight()));
doublePageAction = new QAction(tr("Double page mode"),this);
doublePageAction->setToolTip(tr("Switch to double page mode"));
doublePageAction->setShortcut(tr("D"));
doublePageAction->setIcon(QIcon(":/images/doublePage.png"));
doublePageAction->setDisabled(true);
doublePageAction->setCheckable(true);
doublePageAction->setChecked(Configuration::getConfiguration().getDoublePage());
connect(doublePageAction, SIGNAL(triggered()),viewer,SLOT(doublePageSwitch()));
goToPage = new QAction(tr("Go To"),this);
goToPage->setShortcut(tr("G"));
goToPage->setIcon(QIcon(":/images/goto.png"));
goToPage->setDisabled(true);
goToPage->setToolTip(tr("Go to page ..."));
connect(goToPage, SIGNAL(triggered()),viewer,SLOT(showGoToDialog()));
optionsAction = new QAction(tr("Options"),this);
optionsAction->setShortcut(tr("C"));
optionsAction->setToolTip(tr("YACReader options"));
optionsAction->setIcon(QIcon(":/images/options.png"));
connect(optionsAction, SIGNAL(triggered()),optionsDialog,SLOT(show()));
helpAboutAction = new QAction(tr("Help"),this);
helpAboutAction->setToolTip(tr("Help, About YACReader"));
helpAboutAction->setShortcut(Qt::Key_F1);
helpAboutAction->setIcon(QIcon(":/images/help.png"));
connect(helpAboutAction, SIGNAL(triggered()),had,SLOT(show()));
showMagnifyingGlass = new QAction(tr("Magnifying glass"),this);
showMagnifyingGlass->setToolTip(tr("Switch Magnifying glass"));
showMagnifyingGlass->setShortcut(tr("Z"));
showMagnifyingGlass->setIcon(QIcon(":/images/zoom.png"));
showMagnifyingGlass->setDisabled(true);
showMagnifyingGlass->setCheckable(true);
connect(showMagnifyingGlass, SIGNAL(triggered()),viewer,SLOT(magnifyingGlassSwitch()));
setBookmark = new QAction(tr("Set bookmark"),this);
setBookmark->setToolTip(tr("Set a bookmark on the current page"));
setBookmark->setShortcut(Qt::CTRL+Qt::Key_M);
setBookmark->setIcon(QIcon(":/images/setBookmark.png"));
setBookmark->setDisabled(true);
setBookmark->setCheckable(true);
connect(setBookmark,SIGNAL(triggered (bool)),viewer,SLOT(setBookmark(bool)));
connect(viewer,SIGNAL(pageAvailable(bool)),setBookmark,SLOT(setEnabled(bool)));
connect(viewer,SIGNAL(pageIsBookmark(bool)),setBookmark,SLOT(setChecked(bool)));
showBookmarks = new QAction(tr("Show bookmarks"),this);
showBookmarks->setToolTip(tr("Show the bookmarks of the current comic"));
showBookmarks->setShortcut(tr("M"));
showBookmarks->setIcon(QIcon(":/images/bookmark.png"));
showBookmarks->setDisabled(true);
connect(showBookmarks, SIGNAL(triggered()),viewer->getBookmarksDialog(),SLOT(show()));
showShorcutsAction = new QAction(tr("Show keyboard shortcuts"), this );
showShorcutsAction->setIcon(QIcon(":/images/shortcuts.png"));
connect(showShorcutsAction, SIGNAL(triggered()),shortcutsDialog,SLOT(show()));
showInfo = new QAction(tr("Show Info"),this);
showInfo->setShortcut(tr("I"));
showInfo->setIcon(QIcon(":/images/properties.png"));
showInfo->setDisabled(true);
connect(showInfo, SIGNAL(triggered()),viewer,SLOT(informationSwitch()));
closeAction = new QAction(tr("Close"),this);
closeAction->setShortcut(Qt::Key_Escape);
closeAction->setIcon(QIcon(":/images/deleteLibrary.png"));
connect(closeAction,SIGNAL(triggered()),this,SLOT(close()));
showDictionaryAction = new QAction(tr("Show Dictionary"),this);
showDictionaryAction->setShortcut(Qt::Key_T);
showDictionaryAction->setIcon(QIcon(":/images/dictionary.png"));
showDictionaryAction->setCheckable(true);
showDictionaryAction->setDisabled(true);
connect(showDictionaryAction,SIGNAL(triggered()),viewer,SLOT(translatorSwitch()));
alwaysOnTopAction = new QAction(tr("Always on top"),this);
alwaysOnTopAction->setShortcut(Qt::Key_Q);
alwaysOnTopAction->setIcon(QIcon(":/images/alwaysOnTop.png"));
alwaysOnTopAction->setCheckable(true);
alwaysOnTopAction->setDisabled(true);
alwaysOnTopAction->setChecked(Configuration::getConfiguration().getAlwaysOnTop());
connect(alwaysOnTopAction,SIGNAL(triggered()),this,SLOT(alwaysOnTopSwitch()));
adjustToFullSizeAction = new QAction(tr("Show full size"),this);
adjustToFullSizeAction->setShortcut(Qt::Key_W);
adjustToFullSizeAction->setIcon(QIcon(":/images/adjustToFullSize.png"));
adjustToFullSizeAction->setCheckable(true);
adjustToFullSizeAction->setDisabled(true);
adjustToFullSizeAction->setChecked(Configuration::getConfiguration().getAdjustToFullSize());
connect(adjustToFullSizeAction,SIGNAL(triggered()),this,SLOT(adjustToFullSizeSwitch()));
}
void MainWindowViewer::createToolBars()
{
comicToolBar = addToolBar(tr("&File"));
QToolButton * tb = new QToolButton();
tb->addAction(openAction);
tb->addAction(openFolderAction);
tb->setPopupMode(QToolButton::MenuButtonPopup);
tb->setDefaultAction(openAction);
comicToolBar->addWidget(tb);
comicToolBar->addAction(saveImageAction);
comicToolBar->addAction(openPreviousComicAction);
comicToolBar->addAction(openNextComicAction);
comicToolBar->addSeparator();
comicToolBar->addAction(prevAction);
comicToolBar->addAction(nextAction);
comicToolBar->addAction(goToPage);
comicToolBar->addSeparator();
comicToolBar->addAction(alwaysOnTopAction);
comicToolBar->addSeparator();
comicToolBar->addAction(adjustWidth);
comicToolBar->addAction(adjustToFullSizeAction);
comicToolBar->addAction(leftRotationAction);
comicToolBar->addAction(rightRotationAction);
comicToolBar->addAction(doublePageAction);
comicToolBar->addSeparator();
comicToolBar->addAction(showMagnifyingGlass);
comicToolBar->addSeparator();
comicToolBar->addAction(setBookmark);
comicToolBar->addAction(showBookmarks);
comicToolBar->addSeparator();
comicToolBar->addAction(showDictionaryAction);
comicToolBar->addWidget(new QToolBarStretch());
comicToolBar->addAction(showShorcutsAction);
comicToolBar->addAction(optionsAction);
comicToolBar->addAction(helpAboutAction);
comicToolBar->addAction(closeAction);
comicToolBar->setMovable(false);
viewer->addAction(openAction);
viewer->addAction(openFolderAction);
viewer->addAction(saveImageAction);
viewer->addAction(openPreviousComicAction);
viewer->addAction(openNextComicAction);
QAction * separator = new QAction("",this);
separator->setSeparator(true);
viewer->addAction(separator);
viewer->addAction(prevAction);
viewer->addAction(nextAction);
viewer->addAction(goToPage);
viewer->addAction(adjustWidth);
viewer->addAction(adjustToFullSizeAction);
viewer->addAction(leftRotationAction);
viewer->addAction(rightRotationAction);
viewer->addAction(doublePageAction);
separator = new QAction("",this);
separator->setSeparator(true);
viewer->addAction(separator);
viewer->addAction(setBookmark);
viewer->addAction(showBookmarks);
separator = new QAction("",this);
separator->setSeparator(true);
viewer->addAction(separator);
viewer->addAction(showDictionaryAction);
separator = new QAction("",this);
separator->setSeparator(true);
viewer->addAction(separator);
viewer->addAction(showMagnifyingGlass);
viewer->addAction(optionsAction);
viewer->addAction(helpAboutAction);
viewer->addAction(showInfo);
viewer->addAction(showShorcutsAction);
separator = new QAction("",this);
separator->setSeparator(true);
viewer->addAction(separator);
viewer->addAction(closeAction);
viewer->setContextMenuPolicy(Qt::ActionsContextMenu);
}
void MainWindowViewer::open()
{
QFileDialog openDialog;
QString pathFile = openDialog.getOpenFileName(this,tr("Open Comic"),currentDirectory,tr("Comic files (*.cbr *.cbz *.rar *.zip *.tar *.arj)"));
if (!pathFile.isEmpty())
{
openComicFromPath(pathFile);
}
}
void MainWindowViewer::openComicFromPath(QString pathFile)
{
currentDirectory = pathFile;
QFileInfo fi(pathFile);
getSiblingComics(fi.absolutePath(),fi.fileName());
viewer->open(pathFile);
enableActions();
}
void MainWindowViewer::openFolder()
{
QFileDialog openDialog;
QString pathDir = openDialog.getExistingDirectory(this,tr("Open folder"),currentDirectory);
if (!pathDir.isEmpty())
{
openFolderFromPath(pathDir);
}
}
void MainWindowViewer::openFolderFromPath(QString pathDir)
{
currentDirectory = pathDir; //TODO ??
QFileInfo fi(pathDir);
getSiblingComics(fi.absolutePath(),fi.fileName());
viewer->open(pathDir);
enableActions();
}
void MainWindowViewer::saveImage()
{
QFileDialog saveDialog;
QString pathFile = saveDialog.getSaveFileName(this,tr("Save current page"),currentDirectoryImgDest,tr("Image files (*.jpg)"));
if (!pathFile.isEmpty())
{
currentDirectoryImgDest = pathFile;
const QPixmap * p = viewer->pixmap();
if(p!=NULL)
p->save(pathFile);
}
}
void MainWindowViewer::enableActions()
{
saveImageAction->setDisabled(false);
prevAction->setDisabled(false);
nextAction->setDisabled(false);
adjustWidth->setDisabled(false);
goToPage->setDisabled(false);
alwaysOnTopAction->setDisabled(false);
leftRotationAction->setDisabled(false);
rightRotationAction->setDisabled(false);
showMagnifyingGlass->setDisabled(false);
doublePageAction->setDisabled(false);
adjustToFullSizeAction->setDisabled(false);
//setBookmark->setDisabled(false);
showBookmarks->setDisabled(false);
showInfo->setDisabled(false); //TODO enable goTo and showInfo (or update) when numPages emited
showDictionaryAction->setDisabled(false);
}
void MainWindowViewer::disableActions()
{
saveImageAction->setDisabled(true);
prevAction->setDisabled(true);
nextAction->setDisabled(true);
adjustWidth->setDisabled(true);
goToPage->setDisabled(true);
alwaysOnTopAction->setDisabled(true);
leftRotationAction->setDisabled(true);
rightRotationAction->setDisabled(true);
showMagnifyingGlass->setDisabled(true);
doublePageAction->setDisabled(true);
adjustToFullSizeAction->setDisabled(true);
setBookmark->setDisabled(true);
showBookmarks->setDisabled(true);
showInfo->setDisabled(true); //TODO enable goTo and showInfo (or update) when numPages emited
openPreviousComicAction->setDisabled(true);
openNextComicAction->setDisabled(true);
showDictionaryAction->setDisabled(true);
}
void MainWindowViewer::keyPressEvent(QKeyEvent *event)
{
switch (event->key())
{
case Qt::Key_Escape:
this->close();
break;
case Qt::Key_F:
toggleFullScreen();
break;
case Qt::Key_H:
toggleToolBars();
break;
case Qt::Key_O:
open();
break;
default:
QWidget::keyPressEvent(event);
break;
}
}
void MainWindowViewer::mouseDoubleClickEvent ( QMouseEvent * event )
{
toggleFullScreen();
event->accept();
}
void MainWindowViewer::toggleFullScreen()
{
fullscreen?toNormal():toFullScreen();
Configuration::getConfiguration().setFullScreen(fullscreen = !fullscreen);
}
void MainWindowViewer::toFullScreen()
{
hideToolBars();
viewer->hide();
viewer->fullscreen = true;//TODO, change by the right use of windowState();
showFullScreen();
viewer->show();
if(viewer->magnifyingGlassIsVisible())
viewer->showMagnifyingGlass();
}
void MainWindowViewer::toNormal()
{
//show all
viewer->hide();
viewer->fullscreen = false;//TODO, change by the right use of windowState();
//viewer->hideMagnifyingGlass();
showNormal();
showToolBars();
viewer->show();
if(viewer->magnifyingGlassIsVisible())
viewer->showMagnifyingGlass();
}
void MainWindowViewer::toggleToolBars()
{
toolbars?hideToolBars():showToolBars();
}
void MainWindowViewer::hideToolBars()
{
//hide all
this->comicToolBar->hide();
toolbars = false;
}
void MainWindowViewer::showToolBars()
{
this->comicToolBar->show();
toolbars = true;
}
void MainWindowViewer::changeFit()
{
Configuration & conf = Configuration::getConfiguration();
conf.setAdjustToWidth(!conf.getAdjustToWidth());
viewer->updatePage();
}
void MainWindowViewer::newVersion()
{
QMessageBox msgBox;
msgBox.setText(tr("There is a new version avaliable"));
msgBox.setInformativeText(tr("Do you want to download the new version?"));
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::Yes);
int ret = msgBox.exec();
if(ret==QMessageBox::Yes){
QDesktopServices::openUrl(QUrl("http://www.yacreader.com"));
}
}
void MainWindowViewer::closeEvent ( QCloseEvent * event )
{
viewer->save();
Configuration & conf = Configuration::getConfiguration();
if(!fullscreen && !isMaximized())
{
conf.setPos(pos());
conf.setSize(size());
}
conf.setMaximized(isMaximized());
}
void MainWindowViewer::openPreviousComic()
{
if(!previousComicPath.isEmpty())
{
viewer->open(previousComicPath);
QFileInfo fi(previousComicPath);
getSiblingComics(fi.absolutePath(),fi.fileName());
}
}
void MainWindowViewer::openNextComic()
{
if(!nextComicPath.isEmpty())
{
viewer->open(nextComicPath);
QFileInfo fi(nextComicPath);
getSiblingComics(fi.absolutePath(),fi.fileName());
}
}
void MainWindowViewer::getSiblingComics(QString path,QString currentComic)
{
QDir d(path);
d.setFilter(QDir::Files|QDir::NoDotAndDotDot);
d.setNameFilters(QStringList() << "*.cbr" << "*.cbz" << "*.rar" << "*.zip" << "*.tar");
d.setSorting(QDir::Name|QDir::IgnoreCase|QDir::LocaleAware);
QStringList list = d.entryList();
int index = list.indexOf(currentComic);
if(index == -1) //comic not found
{
QFile f(QCoreApplication::applicationDirPath()+"/errorLog.txt");
if(!f.open(QIODevice::WriteOnly))
{
QMessageBox::critical(NULL,tr("Saving error log file...."),tr("There was a problem saving YACReader error log file. Please, check if you have enough permissions in the YACReader root folder."));
}
else
{
QTextStream txtS(&f);
txtS << "METHOD : MainWindowViewer::getSiblingComics" << '\n';
txtS << "ERROR : current comic not found in its own path" << '\n';
txtS << path << '\n';
txtS << currentComic << '\n';
txtS << "Comic list count : " + list.count() << '\n';
foreach(QString s, list){
txtS << s << '\n';
}
f.close();
}
}
previousComicPath = nextComicPath = "";
if(index>0)
{
previousComicPath = path+"/"+list.at(index-1);
openPreviousComicAction->setDisabled(false);
}
else
openPreviousComicAction->setDisabled(true);
if(index+1<list.count())
{
nextComicPath = path+"/"+list.at(index+1);
openNextComicAction->setDisabled(false);
}
else
openNextComicAction->setDisabled(true);
}
void MainWindowViewer::dropEvent(QDropEvent *event)
{
QList<QUrl> urlList;
QString fName;
QFileInfo info;
if (event->mimeData()->hasUrls())
{
urlList = event->mimeData()->urls();
if ( urlList.size() > 0)
{
fName = urlList[0].toLocalFile(); // convert first QUrl to local path
info.setFile( fName ); // information about file
if (info.isFile())
openComicFromPath(fName); // if is file, setText
else
if(info.isDir())
openFolderFromPath(fName);
}
}
event->acceptProposedAction();
}
void MainWindowViewer::dragEnterEvent(QDragEnterEvent *event)
{
// accept just text/uri-list mime format
if (event->mimeData()->hasFormat("text/uri-list"))
{
event->acceptProposedAction();
}
}
void MainWindowViewer::alwaysOnTopSwitch()
{
if(!Configuration::getConfiguration().getAlwaysOnTop())
{
setWindowFlags(this->windowFlags() | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint); //always on top
show();
}
else
{
setWindowFlags(this->windowFlags() ^ (Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint));
show();
}
Configuration::getConfiguration().setAlwaysOnTop(!Configuration::getConfiguration().getAlwaysOnTop());
}
void MainWindowViewer::adjustToFullSizeSwitch()
{
Configuration::getConfiguration().setAdjustToFullSize(!Configuration::getConfiguration().getAdjustToFullSize());
viewer->updatePage();
}

View File

@ -0,0 +1,115 @@
#ifndef __MAIN_WINDOW_VIEWER_H
#define __MAIN_WINDOW_VIEWER_H
#include <QMainWindow>
#include <QScrollArea>
#include <QToolBar>
#include <QAction>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QCloseEvent>
class Comic;
class Viewer;
class OptionsDialog;
class HelpAboutDialog;
class HttpVersionChecker;
class ShortcutsDialog;
class MainWindowViewer : public QMainWindow
{
Q_OBJECT
public slots:
void open();
void openFolder();
void saveImage();
void toggleToolBars();
void hideToolBars();
void showToolBars();
void changeFit();
void enableActions();
void disableActions();
void toggleFullScreen();
void toFullScreen();
void toNormal();
void loadConfiguration();
void newVersion();
void openPreviousComic();
void openNextComic();
void openComicFromPath(QString pathFile);
void openFolderFromPath(QString pathDir);
void alwaysOnTopSwitch();
void adjustToFullSizeSwitch();
/*void viewComic();
void prev();
void next();
void updatePage();*/
private:
//!State
bool fullscreen;
bool toolbars;
bool alwaysOnTop;
QString currentDirectory;
QString currentDirectoryImgDest;
//!Widgets
Viewer * viewer;
//GoToDialog * goToDialog;
OptionsDialog * optionsDialog;
HelpAboutDialog * had;
ShortcutsDialog * shortcutsDialog;
//! ToolBars
QToolBar *comicToolBar;
//! Actions
QAction *openAction;
QAction *openFolderAction;
QAction *saveImageAction;
QAction *openPreviousComicAction;
QAction *openNextComicAction;
QAction *nextAction;
QAction *prevAction;
QAction *adjustWidth;
QAction *adjustHeight;
QAction *goToPage;
QAction *optionsAction;
QAction *helpAboutAction;
QAction *showMagnifyingGlass;
QAction *setBookmark;
QAction *showBookmarks;
QAction *leftRotationAction;
QAction *rightRotationAction;
QAction *showInfo;
QAction *closeAction;
QAction *doublePageAction;
QAction *showShorcutsAction;
QAction *showDictionaryAction;
QAction *alwaysOnTopAction;
QAction *adjustToFullSizeAction;
HttpVersionChecker * versionChecker;
QString previousComicPath;
QString nextComicPath;
//! M<>todo que inicializa el interfaz.
void setupUI();
void createActions();
void createToolBars();
void getSiblingComics(QString path,QString currentComic);
//! Manejadores de evento:
void keyPressEvent(QKeyEvent *event);
//void resizeEvent(QResizeEvent * event);
void mouseDoubleClickEvent ( QMouseEvent * event );
void dropEvent(QDropEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
protected:
virtual void closeEvent ( QCloseEvent * event );
public:
MainWindowViewer();
};
#endif

View File

@ -0,0 +1,188 @@
#include "options_dialog.h"
#include "configuration.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QFileDialog>
#include <QGroupBox>
#include <QRadioButton>
OptionsDialog::OptionsDialog(QWidget * parent)
:QDialog(parent)
{
QVBoxLayout * layout = new QVBoxLayout(this);
QGroupBox *slideSizeBox = new QGroupBox(tr("\"Go to flow\" size"));
//slideSizeLabel = new QLabel(,this);
slideSize = new QSlider(this);
slideSize->setMinimum(125);
slideSize->setMaximum(350);
slideSize->setPageStep(5);
slideSize->setOrientation(Qt::Horizontal);
QHBoxLayout * slideLayout = new QHBoxLayout();
slideLayout->addWidget(slideSize);
slideSizeBox->setLayout(slideLayout);
QGroupBox *pathBox = new QGroupBox(tr("My comics path"));
QHBoxLayout * path = new QHBoxLayout();
path->addWidget(pathEdit = new QLineEdit());
path->addWidget(pathFindButton = new QPushButton(QIcon(":/images/comicFolder.png"),""));
pathBox->setLayout(path);
connect(pathFindButton,SIGNAL(clicked()),this,SLOT(findFolder()));
accept = new QPushButton(tr("Save"));
cancel = new QPushButton(tr("Cancel"));
connect(accept,SIGNAL(clicked()),this,SLOT(saveOptions()));
connect(cancel,SIGNAL(clicked()),this,SLOT(restoreOptions()));
connect(cancel,SIGNAL(clicked()),this,SLOT(close()));
QGroupBox *groupBox = new QGroupBox(tr("How to show pages in GoToFlow:"));
radio1 = new QRadioButton(tr("CoverFlow look"));
radio2 = new QRadioButton(tr("Stripe look"));
radio3 = new QRadioButton(tr("Overlapped Stripe look"));
QVBoxLayout *vbox = new QVBoxLayout;
QHBoxLayout * opt1 = new QHBoxLayout;
opt1->addWidget(radio1);
QLabel * lOpt1 = new QLabel();
lOpt1->setPixmap(QPixmap(":/images/flow1.png"));
opt1->addStretch();
opt1->addWidget(lOpt1);
vbox->addLayout(opt1);
QHBoxLayout * opt2 = new QHBoxLayout;
opt2->addWidget(radio2);
QLabel * lOpt2 = new QLabel();
lOpt2->setPixmap(QPixmap(":/images/flow2.png"));
opt2->addStretch();
opt2->addWidget(lOpt2);
vbox->addLayout(opt2);
QHBoxLayout * opt3 = new QHBoxLayout;
opt3->addWidget(radio3);
QLabel * lOpt3 = new QLabel();
lOpt3->setPixmap(QPixmap(":/images/flow3.png"));
opt3->addStretch();
opt3->addWidget(lOpt3);
vbox->addLayout(opt3);
//vbox->addStretch(1);
groupBox->setLayout(vbox);
//fitToWidthRatioLabel = new QLabel(tr("Page width stretch"),this);
QGroupBox *fitBox = new QGroupBox(tr("Page width stretch"));
fitToWidthRatioS = new QSlider(this);
fitToWidthRatioS->setMinimum(50);
fitToWidthRatioS->setMaximum(100);
fitToWidthRatioS->setPageStep(5);
fitToWidthRatioS->setOrientation(Qt::Horizontal);
QHBoxLayout * fitLayout = new QHBoxLayout;
fitLayout->addWidget(fitToWidthRatioS);
fitBox->setLayout(fitLayout);
QHBoxLayout * colorSelection = new QHBoxLayout;
backgroundColor = new QLabel();
QPalette pal = backgroundColor->palette();
pal.setColor(backgroundColor->backgroundRole(), Qt::black);
backgroundColor->setPalette(pal);
backgroundColor->setAutoFillBackground(true);
colorDialog = new QColorDialog(Qt::red,this);
connect(colorDialog,SIGNAL(colorSelected(QColor)),this,SLOT(updateColor(QColor)));
QGroupBox *colorBox = new QGroupBox(tr("Background color"));
//backgroundColor->setMinimumWidth(100);
colorSelection->addWidget(backgroundColor);
colorSelection->addWidget(selectBackgroundColorButton = new QPushButton(tr("Choose")));
//colorSelection->addStretch();
connect(selectBackgroundColorButton, SIGNAL(clicked()), colorDialog, SLOT(show()));
colorBox->setLayout(colorSelection);
QHBoxLayout * buttons = new QHBoxLayout();
buttons->addStretch();
buttons->addWidget(new QLabel(tr("Restart is needed")));
buttons->addWidget(accept);
buttons->addWidget(cancel);
layout->addWidget(pathBox);
//layout->addLayout(path);
layout->addWidget(slideSizeBox);
//layout->addWidget(slideSize);
layout->addWidget(groupBox);
//layout->addWidget(fitToWidthRatioLabel);
layout->addWidget(fitBox);
layout->addWidget(colorBox);
//layout->addLayout(colorSelection);
layout->addLayout(buttons);
setLayout(layout);
restoreOptions(); //load options
resize(400,0);
setModal (true);
setWindowTitle("Options");
}
void OptionsDialog::findFolder()
{
QString s = QFileDialog::getExistingDirectory(0,tr("Comics directory"),".");
if(!s.isEmpty())
{
pathEdit->setText(s);
}
}
void OptionsDialog::saveOptions()
{
Configuration & conf = Configuration::getConfiguration();
conf.setDefaultPath(pathEdit->text());
conf.setGotoSlideSize(QSize(static_cast<int>(slideSize->sliderPosition()*SLIDE_ASPECT_RATIO),slideSize->sliderPosition()));
if(radio1->isChecked())
conf.setFlowType(PictureFlow::CoverFlowLike);
if(radio2->isChecked())
conf.setFlowType(PictureFlow::Strip);
if(radio3->isChecked())
conf.setFlowType(PictureFlow::StripOverlapped);
conf.setFitToWidthRatio(fitToWidthRatioS->sliderPosition()/100.0);
conf.setBackgroundColor(colorDialog->currentColor());
conf.save();
close();
emit(accepted());
}
void OptionsDialog::restoreOptions()
{
Configuration & conf = Configuration::getConfiguration();
slideSize->setSliderPosition(conf.getGotoSlideSize().height());
fitToWidthRatioS->setSliderPosition(conf.getFitToWidthRatio()*100);
pathEdit->setText(conf.getDefaultPath());
updateColor(Configuration::getConfiguration().getBackgroundColor());
switch(conf.getFlowType()){
case PictureFlow::CoverFlowLike:
radio1->setChecked(true);
break;
case PictureFlow::Strip:
radio2->setChecked(true);
break;
case PictureFlow::StripOverlapped:
radio3->setChecked(true);
break;
}
}
void OptionsDialog::updateColor(const QColor & color)
{
QPalette pal = backgroundColor->palette();
pal.setColor(backgroundColor->backgroundRole(), color);
backgroundColor->setPalette(pal);
backgroundColor->setAutoFillBackground(true);
colorDialog->setCurrentColor(color);
}

View File

@ -0,0 +1,57 @@
#ifndef __OPTIONS_DIALOG_H
#define __OPTIONS_DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QSlider>
#include <QPushButton>
#include <QRadioButton>
#include <QColorDialog>
class OptionsDialog : public QDialog
{
Q_OBJECT
public:
OptionsDialog(QWidget * parent = 0);
private:
//QLabel * pathLabel;
QLineEdit * pathEdit;
QPushButton * pathFindButton;
QLabel * magGlassSizeLabel;
QLabel * zoomLevel;
//QLabel * slideSizeLabel;
QSlider * slideSize;
QPushButton * accept;
QPushButton * cancel;
QRadioButton *radio1;
QRadioButton *radio2;
QRadioButton *radio3;
//QLabel * fitToWidthRatioLabel;
QSlider * fitToWidthRatioS;
QLabel * backgroundColor;
QPushButton * selectBackgroundColorButton;
QColorDialog * colorDialog;
public slots:
void saveOptions();
void restoreOptions();
void findFolder();
void updateColor(const QColor & color);
signals:
void changedOptions();
};
#endif

757
YACReader/render.cpp Normal file
View File

@ -0,0 +1,757 @@
#include "render.h"
#include <cmath>
#include <QList>
#include <algorithm>
#include <QByteArray>
#include <QPixmap>
#define NL 2
#define NR 2
QMutex mutex;
//-----------------------------------------------------------------------------
// MeanNoiseReductionFilter
//-----------------------------------------------------------------------------
MeanNoiseReductionFilter::MeanNoiseReductionFilter(enum NeighborghoodSize ns)
:neighborghoodSize(ns)
{
}
QImage MeanNoiseReductionFilter::setFilter(const QImage & image)
{
int width = image.width();
int height = image.height();
QImage result(width,height,image.format());
int filterSize = sqrt((float)neighborghoodSize);
int bound = filterSize/2;
QRgb pix;
int r,g,b;
for(int j=bound;j<height-bound;j++){
for(int i=bound;i<width-bound;i++){
r=g=b=0;
for(int y=j-bound;y<=j+bound;y++)
{
for(int x=i-bound;x<=i+bound;x++)
{
pix = image.pixel(x,y);
r += qRed(pix);
g += qGreen(pix);
b += qBlue(pix);
}
}
result.setPixel(i,j,QColor(r/neighborghoodSize,g/neighborghoodSize,b/neighborghoodSize).rgb());
//qDebug((QString::number(redChannel.at(4))+" "+QString::number(greenChannel.at(4))+" "+QString::number(blueChannel.at(4))).toAscii());
//qDebug((QString::number(redChannel.size())+" "+QString::number(greenChannel.size())+" "+QString::number(blueChannel.size())).toAscii());
}
}
return result;
}
//-----------------------------------------------------------------------------
// MedianNoiseReductionFilter
//-----------------------------------------------------------------------------
MedianNoiseReductionFilter::MedianNoiseReductionFilter(enum NeighborghoodSize ns)
:neighborghoodSize(ns)
{
}
QImage MedianNoiseReductionFilter::setFilter(const QImage & image)
{
int width = image.width();
int height = image.height();
QImage result(width,height,image.format());
int filterSize = sqrt((float)neighborghoodSize);
int bound = filterSize/2;
QRgb pix;
QList<int> redChannel;
QList<int> greenChannel;
QList<int> blueChannel;
for(int j=bound;j<height-bound;j++){
for(int i=bound;i<width-bound;i++){
redChannel.clear();
greenChannel.clear();
blueChannel.clear();
for(int y=j-bound;y<=j+bound;y++)
{
for(int x=i-bound;x<=i+bound;x++)
{
pix = image.pixel(x,y);
redChannel.push_back(qRed(pix));
greenChannel.push_back(qGreen(pix));
blueChannel.push_back(qBlue(pix));
}
}
std::sort(redChannel.begin(),redChannel.end());
std::sort(greenChannel.begin(),greenChannel.end());
std::sort(blueChannel.begin(),blueChannel.end());
result.setPixel(i,j,QColor(redChannel.at(4),greenChannel.at(4),blueChannel.at(4)).rgb());
}
}
return result;
}
//-----------------------------------------------------------------------------
// BrightnessFilter
//-----------------------------------------------------------------------------
BrightnessFilter::BrightnessFilter(int l)
:level(l)
{
}
QImage BrightnessFilter::setFilter(const QImage & image)
{
int width = image.width();
int height = image.height();
QImage result(width,height,image.format());
for(int j=0;j<height;j++){
for(int i=0;i<width;i++){
result.setPixel(i,j,QColor(image.pixel(i,j)).light(level).rgb());
}
}
return result;
}
//-----------------------------------------------------------------------------
// ContrastFilter
//-----------------------------------------------------------------------------
ContrastFilter::ContrastFilter()
{
}
QImage ContrastFilter::setFilter(const QImage & image)
{
int width = image.width();
int height = image.height();
QImage result(width,height,image.format());
int min,max,v;
min = 0;
max = 255;
int sum = 0;
QVector<int> hist(256,0);
for(int j=0;j<height;j++){
for(int i=0;i<width;i++){
hist[QColor(image.pixel(i,j)).lightness()]++;
sum++;
}
}
long double count = sum;
long double new_count = 0.0;
long double percentage,next_percentage;
for (int i = 0; i < 254; i++)
{
new_count += hist[i];
percentage = new_count/count;
next_percentage = (new_count+hist[i+1])/count;
if(fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
{
min = i+1;
break;
}
}
new_count=0.0;
for (int i = 255; i > 1; i--)
{
new_count += hist[i];
percentage = new_count/count;
next_percentage = (new_count+hist[i-1])/count;
if(fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
{
max = i-1;
break;
}
}
QColor c;
int range = max - min;
for(int j=0;j<height;j++){
for(int i=0;i<width;i++){
c = QColor(image.pixel(i,j));
result.setPixel(i,j,c.light(((c.lightness()-min)/range*1.0)*255).rgb());
}
}
return result;
}
//-----------------------------------------------------------------------------
// PageRender
//-----------------------------------------------------------------------------
PageRender::PageRender()
:QThread()
{
}
PageRender::PageRender(int np, const QByteArray & rd, QImage * p,unsigned int d, QVector<ImageFilter *> f)
:QThread(),
numPage(np),
data(rd),
page(p),
degrees(d),
filters(f)
{
}
void PageRender::run()
{
//QMutexLocker locker(&mutex);
QImage img;
img.loadFromData(data);
if(degrees > 0)
{
QMatrix m;
m.rotate(degrees);
img = img.transformed(m,Qt::SmoothTransformation);
}
for(int i=0;i<filters.size();i++)
{
img = filters[i]->setFilter(img);
}
*page = img;
emit pageReady(numPage);
}
//-----------------------------------------------------------------------------
// DoublePageRender
//-----------------------------------------------------------------------------
DoublePageRender::DoublePageRender(int np, const QByteArray & rd, const QByteArray & rd2, QImage * p,unsigned int d, QVector<ImageFilter *> f)
:PageRender(),
numPage(np),
data(rd),
data2(rd2),
page(p),
degrees(d),
filters(f)
{
}
void DoublePageRender::run()
{
//QImage result;
//QMutexLocker locker(&mutex);
QImage img, img2;
if(!data.isEmpty())
img.loadFromData(data);
if(!data2.isEmpty())
img2.loadFromData(data2);
/*if(img.isNull())
img = QPixmap(img2.width(),img2.height());
if(img2.isNull())
img2 = QPixmap(img.width(),img.height());*/
int x,y;
x = img.width()+img2.width();
y = qMax(img.height(),img2.height());
QImage auxImg(x,y,QImage::Format_RGB32);
QPainter painter(&auxImg);
painter.drawImage(0,0,img);
painter.drawImage(img.width(),0,img2);
painter.end();
if(degrees > 0)
{
QMatrix m;
m.rotate(degrees);
auxImg = auxImg.transformed(m,Qt::SmoothTransformation);
}
for(int i=0;i<filters.size();i++)
{
auxImg = filters[i]->setFilter(auxImg);
}
*page = auxImg;
emit pageReady(numPage);
}
//-----------------------------------------------------------------------------
// Render
//-----------------------------------------------------------------------------
Render::Render()
:currentIndex(0),doublePage(false),comic(0),loadedComic(false),imageRotation(0),numLeftPages(NL),numRightPages(NR)
{
int size = numLeftPages+numRightPages+1;
currentPageBufferedIndex = numLeftPages;
for(int i = 0; i<size; i++)
{
buffer.push_back(new QImage());
pageRenders.push_back(0);
}
//filters.push_back(new ContrastFilter());
}
//Este m<>todo se encarga de forzar el renderizado de las p<>ginas.
//Actualiza el buffer seg<65>n es necesario.
//si la pagina actual no est<73> renderizada, se lanza un hilo que la renderize (double or single page mode) y se emite una se<73>al que indica que se est<73> renderizando.
void Render::render()
{
updateBuffer();
if(buffer[currentPageBufferedIndex]->isNull())
{
if(pagesReady.size()>0)
{
if(doublePage)
{
if(pagesReady[currentIndex] && pagesReady[qMin(currentIndex+1,(int)comic->numPages()-1)])
if(currentIndex+1 > comic->numPages()-1)
pageRenders[currentPageBufferedIndex] = new DoublePageRender(currentIndex,comic->getRawData()->at(currentIndex),QByteArray(),buffer[currentPageBufferedIndex],imageRotation,filters);
else
pageRenders[currentPageBufferedIndex] = new DoublePageRender(currentIndex,comic->getRawData()->at(currentIndex),comic->getRawData()->at(currentIndex+1),buffer[currentPageBufferedIndex],imageRotation,filters);
else
//las p<>ginas no est<73>n listas, y se est<73>n cargando en el c<>mic
emit processingPage(); //para evitar confusiones esta se<73>al deber<65>a llamarse de otra forma
}
else
if(pagesReady[currentIndex])
pageRenders[currentPageBufferedIndex] = new PageRender(currentIndex,comic->getRawData()->at(currentIndex),buffer[currentPageBufferedIndex],imageRotation,filters);
else
//las p<>ginas no est<73>n listas, y se est<73>n cargando en el c<>mic
emit processingPage(); //para evitar confusiones esta se<73>al deber<65>a llamarse de otra forma
//si se ha creado un hilo para renderizar la p<>gina actual, se arranca
if(pageRenders[currentPageBufferedIndex]!=0)
{
//se conecta la se<73>al pageReady del hilo, con el SLOT prepareAvailablePage
connect(pageRenders[currentPageBufferedIndex],SIGNAL(pageReady(int)),this,SLOT(prepareAvailablePage(int)));
//se emite la se<73>al de procesando, debido a que los hilos se arrancan aqu<71>
if(doublePage || filters.size()>0)
emit processingPage();
pageRenders[currentPageBufferedIndex]->start();
pageRenders[currentPageBufferedIndex]->setPriority(QThread::TimeCriticalPriority);
}
else
//en qu<71> caso ser<65>a necesario hacer esto??? //TODO: IMPORTANTE, puede que no sea necesario.
emit processingPage();
}
else
//no hay ninguna p<>gina lista para ser renderizada, es necesario esperar.
emit processingPage();
}
else
// la p<>gina actual est<73> lista
emit currentPageReady();
//se renderizan las p<>ginas restantes para llenar el buffer.
if(doublePage)
fillBufferDoublePage();
else
fillBuffer();
}
QPixmap * Render::getCurrentPage()
{
QPixmap * page = new QPixmap();
*page = page->fromImage(*buffer[currentPageBufferedIndex]);
return page;
}
void Render::setRotation(int degrees)
{
}
void Render::setComic(Comic * c)
{
if(comic !=0)
delete comic;
comic = c;
}
void Render::prepareAvailablePage(int page)
{
if(currentIndex == page)
emit currentPageReady();
}
void Render::update()
{
render();
}
//-----------------------------------------------------------------------------
// Comic interface
//-----------------------------------------------------------------------------
void Render::load(const QString & path)
{
if(comic!=0)
delete comic;
comic = new Comic();
previousIndex = currentIndex = 0;
connect(comic,SIGNAL(errorOpening()),this,SIGNAL(errorOpening()));
connect(comic,SIGNAL(errorOpening()),this,SLOT(reset()));
connect(comic,SIGNAL(imageLoaded(int)),this,SIGNAL(imageLoaded(int)));
connect(comic,SIGNAL(imageLoaded(int)),this,SLOT(pageRawDataReady(int)));
//connect(comic,SIGNAL(pageChanged(int)),this,SIGNAL(pageChanged(int)));
connect(comic,SIGNAL(numPages(unsigned int)),this,SIGNAL(numPages(unsigned int)));
connect(comic,SIGNAL(numPages(unsigned int)),this,SLOT(setNumPages(unsigned int)));
connect(comic,SIGNAL(imageLoaded(int,QByteArray)),this,SIGNAL(imageLoaded(int,QByteArray)));
connect(comic,SIGNAL(isBookmark(bool)),this,SIGNAL(currentPageIsBookmark(bool)));
connect(comic,SIGNAL(bookmarksLoaded(const Bookmarks &)),this,SIGNAL(bookmarksLoaded(const Bookmarks &)));
pagesReady.clear();
if(comic->load(path)) //garantiza que se va a intentar abrir el c<>mic
{
invalidate();
loadedComic = true;
update();
}
}
void Render::reset()
{
loadedComic = false;
invalidate();
}
//si se solicita la siguiente p<>gina, se calcula cu<63>l debe ser en funci<63>n de si se lee en modo a doble p<>gina o no.
//la p<>gina s<>lo se renderiza, si realmente ha cambiado.
void Render::nextPage()
{
int nextPage; //indica cu<63>l ser<65> la pr<70>xima p<>gina
if(doublePage)
{
nextPage = currentIndex;
if(currentIndex+2<comic->numPages())
{
nextPage = currentIndex+2;
if(currentIndex != nextPage)
comic->setIndex(nextPage);
}
}
else
{
nextPage = comic->nextPage();
}
//se fuerza renderizado si la p<>gina ha cambiado
if(currentIndex != nextPage)
{
previousIndex = currentIndex;
currentIndex = nextPage;
update();
}
}
//si se solicita la p<>gina anterior, se calcula cu<63>l debe ser en funci<63>n de si se lee en modo a doble p<>gina o no.
//la p<>gina s<>lo se renderiza, si realmente ha cambiado.
void Render::previousPage()
{
int previousPage; //indica cu<63>l ser<65> la pr<70>xima p<>gina
if(doublePage)
{
if(currentIndex == 1)
invalidate();
previousPage = qMax(currentIndex-2,0);
if(currentIndex != previousPage)
{
comic->setIndex(previousPage);
}
}
else
{
previousPage = comic->previousPage();
}
//se fuerza renderizado si la p<>gina ha cambiado
if(currentIndex != previousPage)
{
previousIndex = currentIndex;
currentIndex = previousPage;
update();
}
}
unsigned int Render::getIndex()
{
return comic->getIndex();
}
unsigned int Render::numPages()
{
return comic->numPages();
}
bool Render::hasLoadedComic()
{
if(comic!=0)
return comic->loaded();
return false;
}
void Render::setNumPages(unsigned int numPages)
{
pagesReady.fill(false,numPages);
}
void Render::pageRawDataReady(int page)
{
pagesEmited.push_back(page);
if(pageRenders.size()>0)
{
for(int i=0;i<pagesEmited.size();i++)
{
pagesReady[pagesEmited.at(i)] = true;
if(pagesEmited.at(i) == currentIndex)
update();
if(doublePage)
{
if(pagesEmited.at(i)==currentIndex+1)
update();
if ( ((pagesEmited.at(i) < currentIndex) && (pagesEmited.at(i) > currentIndex-2*numLeftPages)) ||
((pagesEmited.at(i) > currentIndex+1) && (pagesEmited.at(i) < currentIndex+1+2*numRightPages)) )
{
fillBufferDoublePage();
}
}
else
{
if ( ((pagesEmited.at(i) < currentIndex) && (pagesEmited.at(i) > currentIndex-numLeftPages)) ||
((pagesEmited.at(i) > currentIndex) && (pagesEmited.at(i) < currentIndex+numRightPages)) )
{
fillBuffer();
}
}
}
pagesEmited.clear();
}
}
//s<>lo se renderiza la p<>gina, si ha habido un cambio de p<>gina
void Render::goTo(int index)
{
if(currentIndex != index)
{
comic->setIndex(index);
previousIndex = currentIndex;
currentIndex = index;
//si cambia la paridad de las p<>gina en modo a doble p<>gina, se rellena el buffer.
//esto solo deber<65>a orcurrir al llegar al principio o al final
if(doublePage && ((previousIndex - index) % 2)!=0)
invalidate();
update();
}
}
void Render::rotateRight()
{
imageRotation = (imageRotation+90) % 360;
invalidate();
update();
}
void Render::rotateLeft()
{
if(imageRotation == 0)
imageRotation = 270;
else
imageRotation = imageRotation - 90;
invalidate();
update();
}
//Actualiza el buffer, a<>adiendo las im<69>genes (vac<61>as) necesarias para su posterior renderizado y
//eliminado aquellas que ya no sean necesarias. Tambi<62>n libera los hilos (no estoy seguro de que sea responsabilidad suya)
//Calcula el n<>mero de nuevas p<>ginas que hay que buferear y si debe hacerlo por la izquierda o la derecha (seg<65>n sea el sentido de la lectura)
void Render::updateBuffer()
{
//QMutexLocker locker(&mutex);
int windowSize = currentIndex - previousIndex;
if(doublePage)
{
windowSize = windowSize/2;
if(currentIndex == 0 && windowSize == 0 && previousIndex == 1)
windowSize = -1;
}
if(windowSize > 0)//add pages to right pages and remove on the left
{
windowSize = qMin(windowSize,buffer.size());
for(int i = 0; i < windowSize; i++)
{
//renders
PageRender * pr = pageRenders.front();
pageRenders.pop_front();
if(pr !=0)
{
if(pr->wait())
delete pr;
}
pageRenders.push_back(0);
//images
if(buffer.front()!=0)
delete buffer.front();
buffer.pop_front();
buffer.push_back(new QImage());
}
}
else //add pages to left pages and remove on the right
if(windowSize<0)
{
windowSize = -windowSize;
windowSize = qMin(windowSize,buffer.size());
for(int i = 0; i < windowSize; i++)
{
//renders
PageRender * pr = pageRenders.back();
pageRenders.pop_back();
if(pr !=0)
{
if(pr->wait())
delete pr;
}
pageRenders.push_front(0);
//images
buffer.push_front(new QImage());
QImage * p = buffer.back();
if(p!=0)
delete p;
buffer.pop_back();
}
}
previousIndex = currentIndex;
}
void Render::fillBuffer()
{
for(int i = 1; i <= qMax(numLeftPages,numRightPages); i++)
{
if ((currentIndex+i < comic->numPages()) &&
buffer[currentPageBufferedIndex+i]->isNull() &&
i <= numRightPages &&
pageRenders[currentPageBufferedIndex+i]==0 &&
pagesReady[currentIndex+1]) //preload next pages
{
pageRenders[currentPageBufferedIndex+i] = new PageRender(currentIndex+i,comic->getRawData()->at(currentIndex+i),buffer[currentPageBufferedIndex+i],imageRotation);
connect(pageRenders[currentPageBufferedIndex],SIGNAL(pageReady(int)),this,SLOT(prepareAvailablePage(int)));
pageRenders[currentPageBufferedIndex+i]->start();
}
if ((currentIndex-i > 0) &&
buffer[currentPageBufferedIndex-i]->isNull() &&
i <= numLeftPages &&
pageRenders[currentPageBufferedIndex-i]==0 &&
pagesReady[currentIndex-1]) //preload previous pages
{
pageRenders[currentPageBufferedIndex-i] = new PageRender(currentIndex-i,comic->getRawData()->at(currentIndex-i),buffer[currentPageBufferedIndex-i],imageRotation);
connect(pageRenders[currentPageBufferedIndex],SIGNAL(pageReady(int)),this,SLOT(prepareAvailablePage(int)));
pageRenders[currentPageBufferedIndex-i]->start();
}
}
}
void Render::fillBufferDoublePage()
{
for(int i = 1; i <= qMax(numLeftPages,numRightPages); i++)
{
if ((currentIndex+2*i < comic->numPages()) &&
buffer[currentPageBufferedIndex+i]->isNull() &&
i <= numRightPages &&
pageRenders[currentPageBufferedIndex+i]==0 &&
(pagesReady[currentIndex+2*i] && pagesReady[qMin(currentIndex+(2*i)+1,(int)comic->numPages()-1)])) //preload next pages
{
if(currentIndex+(2*i)+1 > comic->numPages()-1)
pageRenders[currentPageBufferedIndex+i] = new DoublePageRender(currentIndex+2*i,comic->getRawData()->at(currentIndex+(2*i)),QByteArray(),buffer[currentPageBufferedIndex+i],imageRotation);
else
pageRenders[currentPageBufferedIndex+i] = new DoublePageRender(currentIndex+2*i,comic->getRawData()->at(currentIndex+(2*i)),comic->getRawData()->at(currentIndex+(2*i)+1),buffer[currentPageBufferedIndex+i],imageRotation);
connect(pageRenders[currentPageBufferedIndex],SIGNAL(pageReady(int)),this,SLOT(prepareAvailablePage(int)));
pageRenders[currentPageBufferedIndex+i]->start();
}
if ((currentIndex-2*i >= -1) &&
buffer[currentPageBufferedIndex-i]->isNull() &&
i <= numLeftPages &&
pageRenders[currentPageBufferedIndex-i]==0 &&
(pagesReady[qMax(currentIndex-2*i,0)] && pagesReady[qMin(currentIndex-(2*i)+1,(int)comic->numPages()-1)])) //preload previous pages
{
if(currentIndex-2*i == -1)
pageRenders[currentPageBufferedIndex-i] = new DoublePageRender(0,QByteArray(),comic->getRawData()->at(0),buffer[currentPageBufferedIndex-i],imageRotation);
else
pageRenders[currentPageBufferedIndex-i] = new DoublePageRender(currentIndex-2*i,comic->getRawData()->at(currentIndex-(2*i)),comic->getRawData()->at(currentIndex-(2*i)+1),buffer[currentPageBufferedIndex-i],imageRotation);
connect(pageRenders[currentPageBufferedIndex],SIGNAL(pageReady(int)),this,SLOT(prepareAvailablePage(int)));
pageRenders[currentPageBufferedIndex-i]->start();
}
}
}
//M<>todo que debe ser llamado cada vez que la estructura del buffer se vuelve inconsistente con el modo de lectura actual.
//se terminan todos los hilos en ejecuci<63>n y se libera la memoria (de hilos e im<69>genes)
void Render::invalidate()
{
for(int i=0;i<pageRenders.size();i++)
{
if(pageRenders[i]!=0)
{
pageRenders[i]->terminate();
delete pageRenders[i];
pageRenders[i] = 0;
}
}
for(int i=0;i<buffer.size();i++)
{
delete buffer[i];
buffer[i] = new QImage();
}
}
void Render::doublePageSwitch()
{
doublePage = !doublePage;
if(comic)
{
invalidate();
update();
}
}
QString Render::getCurrentPagesInformation()
{
QString s = QString::number(currentIndex+1);
if (doublePage && (currentIndex+1 < comic->numPages()))
s += "-"+QString::number(currentIndex+2);
s += "/"+QString::number(comic->numPages());
return s;
}
void Render::setBookmark()
{
comic->setBookmark();
}
void Render::removeBookmark()
{
comic->removeBookmark();
}
void Render::save()
{
comic->saveBookmarks();
}

178
YACReader/render.h Normal file
View File

@ -0,0 +1,178 @@
#ifndef RENDER_H
#define RENDER_H
#include <QImage>
#include <QPixmap>
#include <QPainter>
#include <QThread>
#include <QByteArray>
#include <QVector>
#include "comic.h"
//-----------------------------------------------------------------------------
// FILTERS
//-----------------------------------------------------------------------------
#include <QThread>
class Comic;
class ImageFilter {
public:
ImageFilter(){};
virtual QImage setFilter(const QImage & image) = 0;
};
class MeanNoiseReductionFilter : public ImageFilter {
public:
enum NeighborghoodSize{SMALL=9, LARGE=25 };
MeanNoiseReductionFilter(enum NeighborghoodSize ns = SMALL);
virtual QImage setFilter(const QImage & image);
private:
enum NeighborghoodSize neighborghoodSize;
};
class MedianNoiseReductionFilter : public ImageFilter {
public:
enum NeighborghoodSize{SMALL=9, LARGE=25 };
MedianNoiseReductionFilter(enum NeighborghoodSize ns = SMALL);
virtual QImage setFilter(const QImage & image);
private:
enum NeighborghoodSize neighborghoodSize;
};
class BrightnessFilter : public ImageFilter {
public:
BrightnessFilter(int l=150);
virtual QImage setFilter(const QImage & image);
private:
int level;
};
class ContrastFilter : public ImageFilter {
public:
ContrastFilter();
virtual QImage setFilter(const QImage & image);
private:
int level;
};
//-----------------------------------------------------------------------------
// RENDER
//-----------------------------------------------------------------------------
class PageRender : public QThread
{
Q_OBJECT
public:
PageRender();
PageRender(int numPage, const QByteArray & rawData, QImage * page,unsigned int degrees=0, QVector<ImageFilter *> filters = QVector<ImageFilter *>());
int getNumPage(){return numPage;};
void setData(const QByteArray & rawData){data = rawData;};
void setPage(QImage * p){page = p;};
void setRotation(unsigned int d){degrees = d;};
void setFilters(QVector<ImageFilter *> f){filters = f;};
private:
int numPage;
QByteArray data;
QImage * page;
unsigned int degrees;
QVector<ImageFilter *> filters;
void run();
signals:
void pageReady(int);
};
//-----------------------------------------------------------------------------
// RENDER
//-----------------------------------------------------------------------------
class DoublePageRender : public PageRender
{
Q_OBJECT
public:
DoublePageRender(int firstPage, const QByteArray & firstPageData,const QByteArray & secondPageData, QImage * page,unsigned int degrees=0, QVector<ImageFilter *> filters = QVector<ImageFilter *>());
private:
int numPage;
QByteArray data;
QByteArray data2;
QImage * page;
unsigned int degrees;
QVector<ImageFilter *> filters;
void run();
signals:
void pageReady(int);
};
class Render : public QObject {
Q_OBJECT
public:
Render();
public slots:
void render();
QPixmap * getCurrentPage();
void goTo(int index);
void doublePageSwitch();
void setRotation(int degrees);
void setComic(Comic * c);
void prepareAvailablePage(int page);
void update();
void setNumPages(unsigned int numPages);
void pageRawDataReady(int page);
//--comic interface
void nextPage();
void previousPage();
void load(const QString & path);
void rotateRight();
void rotateLeft();
unsigned int getIndex();
unsigned int numPages();
bool hasLoadedComic();
void updateBuffer();
void fillBuffer();
void fillBufferDoublePage();
void invalidate();
QString getCurrentPagesInformation();
void setBookmark();
void removeBookmark();
void save();
void reset();
signals:
void currentPageReady();
void processingPage();
void imagesLoaded();
void imageLoaded(int index);
void imageLoaded(int index,const QByteArray & image);
void pageChanged(int index);
void numPages(unsigned int numPages);
void errorOpening();
void currentPageIsBookmark(bool);
void bookmarksLoaded(const Bookmarks &);
private:
Comic * comic;
bool doublePage;
int previousIndex;
int currentIndex;
//QPixmap * currentPage;
int currentPageBufferedIndex;
int numLeftPages;
int numRightPages;
QList<PageRender *> pageRenders;
QList<QImage *> buffer;
void loadAll();
void updateRightPages();
void updateLeftPages();
bool loadedComic;
QList<int> pagesEmited;
QVector<bool> pagesReady;
int imageRotation;
QVector<ImageFilter *> filters;
};
#endif // RENDER_H

View File

@ -0,0 +1,67 @@
#include "shortcuts_dialog.h"
#include <QVBoxLayout>
#include <QPushButton>
#include <QTextEdit>
#include <QLabel>
#include <QPixmap>
#include <QFile>
#include <QTextStream>
#include <QTextCodec>
ShortcutsDialog::ShortcutsDialog(QWidget * parent)
:QDialog(parent)//,Qt::FramelessWindowHint)
{
setModal(true);
setWindowIcon(QIcon(":/images/shortcuts.png"));
setWindowTitle(tr("YACReader keyboard shortcuts"));
QVBoxLayout * mainLayout = new QVBoxLayout;
close = new QPushButton(tr("Close"));
connect(close,SIGNAL(clicked()),this,SLOT(close()));
QHBoxLayout *bottomLayout = new QHBoxLayout;
bottomLayout->addStretch();
bottomLayout->addWidget(close);
QHBoxLayout * shortcutsLayout = new QHBoxLayout;
shortcuts = new QTextEdit();
shortcuts->setFrameStyle(QFrame::NoFrame);
//"<p><b>General functions:</b><hr/><b>O</b> : Open comic<br/><b>Esc</b> : Exit</p>"
shortcuts->setReadOnly(true);
shortcutsLayout->addWidget(shortcuts);
//shortcutsLayout->addWidget(shortcuts2);
shortcutsLayout->setSpacing(0);
mainLayout->addLayout(shortcutsLayout);
mainLayout->addLayout(bottomLayout);
QHBoxLayout *imgMainLayout = new QHBoxLayout;
QLabel * imgLabel = new QLabel();
QPixmap p(":/images/shortcuts.png");
imgLabel->setPixmap(p);
QVBoxLayout * imgLayout = new QVBoxLayout;
imgLayout->addWidget(imgLabel);
imgLayout->addStretch();
imgMainLayout->addLayout(imgLayout);
imgMainLayout->addLayout(mainLayout);
setLayout(imgMainLayout);
setFixedSize(QSize(700,500));
QFile f(":/files/shortcuts.html");
f.open(QIODevice::ReadOnly);
QTextStream txtS(&f);
txtS.setCodec(QTextCodec::codecForName("UTF-8"));
QString content = txtS.readAll();
f.close();
shortcuts->setHtml(content);
setWindowTitle(tr("Keyboard Shortcuts"));
}

View File

@ -0,0 +1,19 @@
#ifndef SHORTCUTS_DIALOG_H
#define SHORTCUTS_DIALOG_H
#include <QDialog>
#include <QTextEdit>
#include <QPushButton>
class ShortcutsDialog : public QDialog
{
Q_OBJECT
public:
ShortcutsDialog(QWidget * parent = 0);
private:
QTextEdit * shortcuts;
QPushButton * close;
public slots:
};
#endif // SHORTCUTS_DIALOG_H

90
YACReader/translator.cpp Normal file
View File

@ -0,0 +1,90 @@
#include <QUrl>
#include <Phonon/MediaObject>
#include <Phonon/MediaSource>
#include <QPushButton>
#include <QPalette>
#include <QMouseEvent>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QWebView>
#include <QFile>
#include <QPoint>
#include <QWidget>
#include <QTextCodec>
#include "translator.h"
YACReaderTranslator::YACReaderTranslator(QWidget * parent)
:QWidget(parent)
{
this->setCursor(QCursor(Qt::ArrowCursor));
this->setAutoFillBackground(true);
this->setBackgroundRole(QPalette::Window);
QPalette p(this->palette());
p.setColor(QPalette::Window, QColor(96,96,96));
this->setPalette(p);
QVBoxLayout *layout = new QVBoxLayout(this);
QWebView * view = new QWebView();
QFile f(":/files/translator.html");
f.open(QIODevice::ReadOnly);
QTextStream txtS(&f);
txtS.setCodec(QTextCodec::codecForName("UTF-8"));
QString contentHTML = txtS.readAll();
view->setHtml(contentHTML);
view->page()->setLinkDelegationPolicy(QWebPage::DelegateExternalLinks);
connect(view->page(),SIGNAL(linkClicked(QUrl)),this,SLOT(play(QUrl)));
QHBoxLayout * buttonBar = new QHBoxLayout();
QPushButton * close = new QPushButton(QIcon(QPixmap(":/images/close.png")),"");
close->setFlat(true);
buttonBar->addStretch();
close->resize(18,18);
buttonBar->addWidget(close);
buttonBar->setMargin(0);
connect(close,SIGNAL(clicked()),this->parent(),SLOT(animateHideTranslator()));
layout->setMargin(0);
layout->setSpacing(0);
layout->addLayout(buttonBar);
layout->addWidget(view);
resize(view->size().width()/1.60,view->size().height());
music = createPlayer(MusicCategory);
show();
}
void YACReaderTranslator::play(const QUrl & url)
{
MediaSource src(url);
src.setAutoDelete(true);
music->setCurrentSource(src);
music->play();
}
YACReaderTranslator::~YACReaderTranslator()
{
delete music;
}
void YACReaderTranslator::mousePressEvent(QMouseEvent *event)
{
drag = true;
click = event->pos();
}
void YACReaderTranslator::mouseReleaseEvent(QMouseEvent *event)
{
drag = false;
}
void YACReaderTranslator::mouseMoveEvent(QMouseEvent * event)
{
if(drag)
this->move(QPoint(mapToParent(event->pos())-click));
}

32
YACReader/translator.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef __TRANSLATOR_H
#define __TRANSLATOR_H
class QUrl;
class QMouseEvent;
class QPoint;
#include<QWidget>
#include<Phonon/MediaObject>
using namespace Phonon;
class YACReaderTranslator : public QWidget
{
Q_OBJECT
public:
YACReaderTranslator(QWidget * parent = 0);
~YACReaderTranslator();
public slots:
void play(const QUrl & url);
protected:
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void mouseMoveEvent ( QMouseEvent * event );
bool drag;
QPoint click;
private:
MediaObject * music;
};
#endif

675
YACReader/viewer.cpp Normal file
View File

@ -0,0 +1,675 @@
#include "viewer.h"
#include "magnifying_glass.h"
#include "configuration.h"
#include "magnifying_glass.h"
#include "goto_flow.h"
#include "bookmarks_dialog.h"
#include "render.h"
#include "goto_dialog.h"
#include "translator.h"
#include <QWebView>
#include <QFile>
#define STEPS 22
Viewer::Viewer(QWidget * parent)
:QScrollArea(parent),
currentPage(0),
magnifyingGlassShowed(false),
fullscreen(false),
information(false),
adjustToWidthRatio(1),
doublePage(false),
wheelStop(false),
direction(1),
restoreMagnifyingGlass(false),
drag(false)
{
translator = new YACReaderTranslator(this);
translator->hide();
translatorAnimation = new QPropertyAnimation(translator,"pos");
translatorAnimation->setDuration(150);
translatorXPos = -10000;
translator->move(-translator->width(),10);
//current comic page
content = new QLabel(this);
configureContent(tr("Press 'O' to open comic."));
//scroll area configuration
setBackgroundRole(QPalette::Dark);
setWidget(content);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setFrameStyle(QFrame::NoFrame);
setAlignment(Qt::AlignCenter);
QPalette palette;
palette.setColor(backgroundRole(), Configuration::getConfiguration().getBackgroundColor());
setPalette(palette);
//---------------------------------------
mglass = new MagnifyingGlass(Configuration::getConfiguration().getMagnifyingGlassSize(),this);
mglass->hide();
content->setMouseTracking(true);
setMouseTracking(true);
informationLabel = new QLabel(this);
informationLabel->setAlignment(Qt::AlignVCenter|Qt::AlignHCenter);
informationLabel->setAutoFillBackground(true);
informationLabel->setFont(QFont("courier new", 12));
informationLabel->hide();
informationLabel->resize(100,25);
showCursor();
goToDialog = new GoToDialog(this);
goToFlow = new GoToFlow(this,Configuration::getConfiguration().getFlowType());
goToFlow->hide();
showGoToFlowAnimation = new QPropertyAnimation(goToFlow,"pos");
showGoToFlowAnimation->setDuration(150);
bd = new BookmarksDialog(this->parentWidget());
render = new Render();
scroller = new QTimer(this);
hideCursorTimer = new QTimer();
hideCursorTimer->setSingleShot(true);
if(Configuration::getConfiguration().getDoublePage())
doublePageSwitch();
createConnections();
hideCursorTimer->start(2500);
setMouseTracking(true);
}
void Viewer::createConnections()
{
//magnifyingGlass (update mg after a background change
connect(this,SIGNAL(backgroundChanges()),mglass,SLOT(updateImage()));
//goToDialog
connect(goToDialog,SIGNAL(goToPage(unsigned int)),this,SLOT(goTo(unsigned int)));
//goToFlow goTo
connect(goToFlow,SIGNAL(goToPage(unsigned int)),this,SLOT(goTo(unsigned int)));
//current time
QTimer * t = new QTimer();
connect(t,SIGNAL(timeout()),this,SLOT(updateInformation()));
t->start(1000);
//hide cursor
connect(hideCursorTimer,SIGNAL(timeout()),this,SLOT(hideCursor()));
//bookmarks
connect(bd,SIGNAL(goToPage(unsigned int)),this,SLOT(goTo(unsigned int)));
//render
connect(render,SIGNAL(errorOpening()),this,SLOT(resetContent()));
connect(render,SIGNAL(numPages(unsigned int)),goToFlow,SLOT(setNumSlides(unsigned int)));
connect(render,SIGNAL(numPages(unsigned int)),goToDialog,SLOT(setNumPages(unsigned int)));
connect(render,SIGNAL(imageLoaded(int,QByteArray)),goToFlow,SLOT(setImageReady(int,QByteArray)));
connect(render,SIGNAL(currentPageReady()),this,SLOT(updatePage()));
connect(render,SIGNAL(processingPage()),this,SLOT(setLoadingMessage()));
connect(render,SIGNAL(currentPageIsBookmark(bool)),this,SIGNAL(pageIsBookmark(bool)));
connect(render,SIGNAL(bookmarksLoaded(const Bookmarks &)),bd,SLOT(setBookmarks(const Bookmarks &)));
}
void Viewer::open(QString pathFile)
{
if(render->hasLoadedComic())
save();
//bd->setBookmarks(*bm);
goToFlow->reset();
render->load(pathFile);
//render->update();
verticalScrollBar()->setSliderPosition(verticalScrollBar()->minimum());
}
void Viewer::next()
{
direction = 1;
render->nextPage();
}
void Viewer::prev()
{
direction = -1;
render->previousPage();
}
void Viewer::showGoToDialog()
{
goToDialog->show();
}
void Viewer::goTo(unsigned int page)
{
direction = 1; //in "go to" direction is always fordward
render->goTo(page-1);
}
void Viewer::updatePage()
{
QPixmap * previousPage = currentPage;
currentPage = render->getCurrentPage();
content->setPixmap(*currentPage);
updateContentSize();
updateVerticalScrollBar();
emit backgroundChanges();
emit(pageAvailable(true));
//TODO -> update bookmark action
setFocus(Qt::ShortcutFocusReason);
delete previousPage;
if(restoreMagnifyingGlass)
{
restoreMagnifyingGlass = false;
showMagnifyingGlass();
}
}
void Viewer::updateContentSize()
{
//there is an image to resize
if(currentPage !=0 && !currentPage->isNull())
{
if(Configuration::getConfiguration().getAdjustToFullSize())
{
content->resize(currentPage->width(),currentPage->height());
}
else
{
float aspectRatio = (float)currentPage->width()/currentPage->height();
//Fit to width
if(Configuration::getConfiguration().getAdjustToWidth())
{
adjustToWidthRatio = Configuration::getConfiguration().getFitToWidthRatio();
if(static_cast<int>(width()*adjustToWidthRatio/aspectRatio)<height())
if(static_cast<int>(height()*aspectRatio)>width())
content->resize(width(),static_cast<int>(width()/aspectRatio));
else
content->resize(static_cast<int>(height()*aspectRatio),height());
else
content->resize(width()*adjustToWidthRatio,static_cast<int>(width()*adjustToWidthRatio/aspectRatio));
}
//Fit to height or fullsize/custom size
else
{
if(static_cast<int>(height()*aspectRatio)>width()) //page width exceeds window width
content->resize(width(),static_cast<int>(width()/aspectRatio));
else
content->resize(static_cast<int>(height()*aspectRatio),height());
}
}
emit backgroundChanges();
}
content->update(); //TODO, it shouldn't be neccesary
}
void Viewer::updateVerticalScrollBar()
{
if(direction > 0)
verticalScrollBar()->setSliderPosition(verticalScrollBar()->minimum());
else
verticalScrollBar()->setSliderPosition(verticalScrollBar()->maximum());
}
void Viewer::scrollDown()
{
if(verticalScrollBar()->sliderPosition()==verticalScrollBar()->maximum())
{
next();
scroller->stop();
}
else
{
int currentPos = verticalScrollBar()->sliderPosition();
verticalScrollBar()->setSliderPosition(currentPos=currentPos+posByStep);
if((verticalScrollBar()->sliderPosition()==verticalScrollBar()->maximum())
||(verticalScrollBar()->sliderPosition()>=nextPos))
scroller->stop();
emit backgroundChanges();
}
}
void Viewer::scrollUp()
{
if(verticalScrollBar()->sliderPosition()==verticalScrollBar()->minimum())
{
prev();
scroller->stop();
}
else
{
int currentPos = verticalScrollBar()->sliderPosition();
verticalScrollBar()->setSliderPosition(currentPos=currentPos-posByStep);
if((verticalScrollBar()->sliderPosition()==verticalScrollBar()->minimum())
||(verticalScrollBar()->sliderPosition()<=nextPos))
scroller->stop();
emit backgroundChanges();
}
}
void Viewer::keyPressEvent(QKeyEvent *event)
{
if(render->hasLoadedComic())
{
if(goToFlow->isVisible() && event->key()!=Qt::Key_S)
QCoreApplication::sendEvent(goToFlow,event);
else
switch (event->key())
{
case Qt::Key_Space:
disconnect(scroller,SIGNAL(timeout()),this,0);
connect(scroller,SIGNAL(timeout()),this,SLOT(scrollDown()));
posByStep = height()/STEPS;
nextPos=verticalScrollBar()->sliderPosition()+static_cast<int>((height()*0.80));
scroller->start(20);
break;
case Qt::Key_B:
disconnect(scroller,SIGNAL(timeout()),this,0);
connect(scroller,SIGNAL(timeout()),this,SLOT(scrollUp()));
posByStep = height()/STEPS;
nextPos=verticalScrollBar()->sliderPosition()-static_cast<int>((height()*0.80));
scroller->start(20);
break;
case Qt::Key_S:
goToFlowSwitch();
break;
case Qt::Key_T:
translatorSwitch();
break;
case Qt::Key_Down:
/*if(verticalScrollBar()->sliderPosition()==verticalScrollBar()->maximum())
next();
else*/
QAbstractScrollArea::keyPressEvent(event);
emit backgroundChanges();
break;
case Qt::Key_Up:
/*if(verticalScrollBar()->sliderPosition()==verticalScrollBar()->minimum())
prev();
else*/
QAbstractScrollArea::keyPressEvent(event);
emit backgroundChanges();
break;
case Qt::Key_Home:
goTo(1);
break;
case Qt::Key_End:
goTo(this->render->numPages());
break;
default:
QAbstractScrollArea::keyPressEvent(event);
break;
}
if(mglass->isVisible())
switch(event->key())
{
case Qt::Key_Plus: case Qt::Key_Minus: case Qt::Key_Underscore: case Qt::Key_Asterisk:
QCoreApplication::sendEvent(mglass,event);
}
}
}
void Viewer::wheelEvent(QWheelEvent * event)
{
if(render->hasLoadedComic())
{
if((event->delta()<0)&&(verticalScrollBar()->sliderPosition()==verticalScrollBar()->maximum()))
{
if(wheelStop)
{
next();
event->accept();
wheelStop = false;
return;
}
else
wheelStop = true;
}
else
if((event->delta()>0)&&(verticalScrollBar()->sliderPosition()==verticalScrollBar()->minimum()))
{
if(wheelStop)
{
prev();
event->accept();
wheelStop = false;
return;
}
else
wheelStop = true;
}
QAbstractScrollArea::wheelEvent(event);
emit backgroundChanges();
}
}
void Viewer::resizeEvent(QResizeEvent * event)
{
updateContentSize();
goToFlow->move(QPoint((width()-goToFlow->width())/2,height()-goToFlow->height()));
informationLabel->move(QPoint((width()-informationLabel->width())/2,0));
QScrollArea::resizeEvent(event);
}
void Viewer::mouseMoveEvent(QMouseEvent * event)
{
showCursor();
hideCursorTimer->start(2500);
if(magnifyingGlassShowed)
mglass->move(static_cast<int>(event->x()-float(mglass->width())/2),static_cast<int>(event->y()-float(mglass->height())/2));
if(render->hasLoadedComic())
{
if(showGoToFlowAnimation->state()!=QPropertyAnimation::Running)
{
if(goToFlow->isVisible())
{
animateHideGoToFlow();
//goToFlow->hide();
}
else
{
int umbral = (width()-goToFlow->width())/2;
if((event->y()>height()-15)&&(event->x()>umbral)&&(event->x()<width()-umbral))
{
animateShowGoToFlow();
hideCursorTimer->stop();
}
}
}
if(drag)
{
int currentPosY = verticalScrollBar()->sliderPosition();
int currentPosX = horizontalScrollBar()->sliderPosition();
verticalScrollBar()->setSliderPosition(currentPosY=currentPosY+(yDragOrigin-event->y()));
horizontalScrollBar()->setSliderPosition(currentPosX=currentPosX+(xDragOrigin-event->x()));
yDragOrigin = event->y();
xDragOrigin = event->x();
}
}
}
const QPixmap * Viewer::pixmap()
{
return content->pixmap();
}
void Viewer::magnifyingGlassSwitch()
{
magnifyingGlassShowed?hideMagnifyingGlass():showMagnifyingGlass();
}
void Viewer::showMagnifyingGlass()
{
if(render->hasLoadedComic())
{
QPoint p = QPoint(cursor().pos().x(),cursor().pos().y());
p = this->parentWidget()->mapFromGlobal(p);
mglass->move(static_cast<int>(p.x()-float(mglass->width())/2)
,static_cast<int>(p.y()-float(mglass->height())/2));
mglass->show();
mglass->updateImage(mglass->x()+mglass->width()/2,mglass->y()+mglass->height()/2);
magnifyingGlassShowed = true;
}
}
void Viewer::hideMagnifyingGlass()
{
mglass->hide();
magnifyingGlassShowed = false;
}
void Viewer::informationSwitch()
{
information?informationLabel->hide():informationLabel->show();
informationLabel->move(QPoint((width()-informationLabel->width())/2,0));
information=!information;
//TODO it shouldn't be neccesary
informationLabel->adjustSize();
informationLabel->update();
}
void Viewer::updateInformation()
{
if(render->hasLoadedComic())
{
informationLabel->setText(render->getCurrentPagesInformation()+" - "+QTime::currentTime().toString("HH:mm"));
informationLabel->adjustSize();
informationLabel->update(); //TODO it shouldn't be neccesary
}
}
void Viewer::goToFlowSwitch()
{
goToFlow->isVisible()?animateHideGoToFlow():showGoToFlow();
}
void Viewer::translatorSwitch()
{
translator->isVisible()?animateHideTranslator():animateShowTranslator();
}
void Viewer::showGoToFlow()
{
if(render->hasLoadedComic())
{
animateShowGoToFlow();
}
}
void Viewer::animateShowGoToFlow()
{
if(goToFlow->isHidden() && showGoToFlowAnimation->state()!=QPropertyAnimation::Running)
{
disconnect(showGoToFlowAnimation,SIGNAL(finished()),goToFlow,SLOT(hide()));
connect(showGoToFlowAnimation,SIGNAL(finished()),this,SLOT(moveCursoToGoToFlow()));
showGoToFlowAnimation->setStartValue(QPoint((width()-goToFlow->width())/2,height()-10));
showGoToFlowAnimation->setEndValue(QPoint((width()-goToFlow->width())/2,height()-goToFlow->height()));
showGoToFlowAnimation->start();
goToFlow->centerSlide(render->getIndex());
goToFlow->setPageNumber(render->getIndex());
goToFlow->show();
goToFlow->setFocus(Qt::OtherFocusReason);
}
}
void Viewer::animateHideGoToFlow()
{
if(goToFlow->isVisible() && showGoToFlowAnimation->state()!=QPropertyAnimation::Running)
{
connect(showGoToFlowAnimation,SIGNAL(finished()),goToFlow,SLOT(hide()));
disconnect(showGoToFlowAnimation,SIGNAL(finished()),this,SLOT(moveCursoToGoToFlow()));
showGoToFlowAnimation->setStartValue(QPoint((width()-goToFlow->width())/2,height()-goToFlow->height()));
showGoToFlowAnimation->setEndValue(QPoint((width()-goToFlow->width())/2,height()));
showGoToFlowAnimation->start();
goToFlow->centerSlide(render->getIndex());
goToFlow->setPageNumber(render->getIndex());
this->setFocus(Qt::OtherFocusReason);
}
}
void Viewer::moveCursoToGoToFlow()
{
//Move cursor to goToFlow widget on show (this avoid hide when mouse is moved)
int y = goToFlow->pos().y();
int x1 = goToFlow->pos().x();
int x2 = x1 + goToFlow->width();
QPoint cursorPos = mapFromGlobal(cursor().pos());
int cursorX = cursorPos.x();
int cursorY = cursorPos.y();
if(cursorY <= y)
cursorY = y + 10;
if(cursorX <= x1)
cursorX = x1 + 10;
if(cursorX >= x2)
cursorX = x2 - 10;
cursor().setPos(mapToGlobal(QPoint(cursorX,cursorY)));
hideCursorTimer->stop();
showCursor();
}
void Viewer::rotateLeft()
{
render->rotateLeft();
}
void Viewer::rotateRight()
{
render->rotateRight();
}
//TODO
void Viewer::setBookmark(bool set)
{
render->setBookmark();
if(set) //add bookmark
{
render->setBookmark();
}
else //remove bookmark
{
render->removeBookmark();
}
}
void Viewer::save ()
{
if(render->hasLoadedComic())
render->save();
}
void Viewer::doublePageSwitch()
{
doublePage = !doublePage;
render->doublePageSwitch();
Configuration::getConfiguration().setDoublePage(doublePage);
}
void Viewer::resetContent()
{
configureContent(tr("Press 'O' to open comic."));
goToFlow->reset();
emit reset();
}
void Viewer::setLoadingMessage()
{
if(magnifyingGlassShowed)
{
hideMagnifyingGlass();
restoreMagnifyingGlass = true;
}
emit(pageAvailable(false));
configureContent(tr("Loading...please wait!"));
}
void Viewer::configureContent(QString msg)
{
content->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
content->setScaledContents(true);
content->setAlignment(Qt::AlignTop|Qt::AlignHCenter);
content->setText(msg);
content->setFont(QFont("courier new", 12));
content->adjustSize();
setFocus(Qt::ShortcutFocusReason);
//emit showingText();
}
void Viewer::hideCursor()
{
#ifdef Q_WS_MAC
setCursor(QCursor(QBitmap(1,1),QBitmap(1,1)));
#else
setCursor(Qt::BlankCursor);
#endif
}
void Viewer::showCursor()
{
if(drag)
setCursor(Qt::ClosedHandCursor);
else
setCursor(Qt::OpenHandCursor);
}
void Viewer::updateOptions()
{
goToFlow->setFlowType(Configuration::getConfiguration().getFlowType());
updateBackgroundColor(Configuration::getConfiguration().getBackgroundColor());
updateContentSize();
//goToFlow->updateSize();
}
void Viewer::updateBackgroundColor(const QColor & color)
{
QPalette palette;
palette.setColor(backgroundRole(), color);
setPalette(palette);
}
void Viewer::animateShowTranslator()
{
if(translator->isHidden() && translatorAnimation->state()!=QPropertyAnimation::Running)
{
disconnect(translatorAnimation,SIGNAL(finished()),translator,SLOT(hide()));
if(translatorXPos == -10000)
translatorXPos = (width()-translator->width())/2;
int x = qMax(0,qMin(translatorXPos,width()-translator->width()));
if(translator->pos().x()<0)
{
translatorAnimation->setStartValue(QPoint(-translator->width(),translator->pos().y()));
}
else
{
translatorAnimation->setStartValue(QPoint(width()+translator->width(),translator->pos().y()));
}
translatorAnimation->setEndValue(QPoint(x,translator->pos().y()));
translatorAnimation->start();
translator->show();
translator->setFocus(Qt::OtherFocusReason);
}
}
void Viewer::animateHideTranslator()
{
if(translator->isVisible() && translatorAnimation->state()!=QPropertyAnimation::Running)
{
connect(translatorAnimation,SIGNAL(finished()),translator,SLOT(hide()));
translatorAnimation->setStartValue(QPoint(translatorXPos = translator->pos().x(),translator->pos().y()));
if((translator->width()/2)+translator->pos().x() <= width()/2)
translatorAnimation->setEndValue(QPoint(-translator->width(),translator->pos().y()));
else
translatorAnimation->setEndValue(QPoint(width()+translator->width(),translator->pos().y()));
translatorAnimation->start();
this->setFocus(Qt::OtherFocusReason);
}
}
void Viewer::mousePressEvent ( QMouseEvent * event )
{
drag = true;
yDragOrigin = event->y();
xDragOrigin = event->x();
setCursor(Qt::ClosedHandCursor);
}
void Viewer::mouseReleaseEvent ( QMouseEvent * event )
{
drag = false;
setCursor(Qt::OpenHandCursor);
}

131
YACReader/viewer.h Normal file
View File

@ -0,0 +1,131 @@
#ifndef __VIEWER_H
#define __VIEWER_H
#include <QMainWindow>
#include <QScrollArea>
#include <QAction>
#include <QTimer>
#include <QLabel>
#include <QPixmap>
#include <QKeyEvent>
#include <QResizeEvent>
#include <QWheelEvent>
#include <QMouseEvent>
#include <QCloseEvent>
#include <QPropertyAnimation>
class Comic;
class MagnifyingGlass;
class GoToFlow;
class BookmarksDialog;
class Render;
class GoToDialog;
class YACReaderTranslator;
class Viewer : public QScrollArea
{
Q_OBJECT
public:
bool fullscreen; //TODO, change by the right use of windowState();
public slots:
void open(QString pathFile);
void prev();
void next();
void showGoToDialog();
void goTo(unsigned int page);
void updatePage();
void updateContentSize();
void updateVerticalScrollBar();
void updateOptions();
void scrollDown();
void scrollUp();
void magnifyingGlassSwitch();
void showMagnifyingGlass();
void hideMagnifyingGlass();
void informationSwitch();
void updateInformation();
void goToFlowSwitch();
void showGoToFlow();
void moveCursoToGoToFlow();
void animateShowGoToFlow();
void animateHideGoToFlow();
void rotateLeft();
void rotateRight();
bool magnifyingGlassIsVisible() {return magnifyingGlassShowed;}
void setBookmark(bool);
void save();
void doublePageSwitch();
void resetContent();
void setLoadingMessage();
void configureContent(QString msg);
void hideCursor();
void showCursor();
void createConnections();
void translatorSwitch();
void animateShowTranslator();
void animateHideTranslator();
virtual void mousePressEvent ( QMouseEvent * event );
virtual void mouseReleaseEvent ( QMouseEvent * event );
void updateBackgroundColor(const QColor & color);
private:
bool information;
bool doublePage;
QLabel * informationLabel;
QTimer * scroller;
int posByStep;
int nextPos;
GoToFlow * goToFlow;
QPropertyAnimation * showGoToFlowAnimation;
GoToDialog * goToDialog;
//!Image properties
float adjustToWidthRatio;
//! Comic
//Comic * comic;
int index;
QPixmap *currentPage;
BookmarksDialog * bd;
bool wheelStop;
Render * render;
QTimer * hideCursorTimer;
int direction;
bool drag;
//!Widgets
QLabel *content;
YACReaderTranslator * translator;
int translatorXPos;
QPropertyAnimation * translatorAnimation;
int yDragOrigin;
int xDragOrigin;
private:
//!Magnifying glass
MagnifyingGlass *mglass;
bool magnifyingGlassShowed;
bool restoreMagnifyingGlass;
//! Manejadores de evento:
void keyPressEvent(QKeyEvent * event);
void resizeEvent(QResizeEvent * event);
void wheelEvent(QWheelEvent * event);
void mouseMoveEvent(QMouseEvent * event);
public:
Viewer(QWidget * parent = 0);
void toggleFullScreen();
const QPixmap * pixmap();
//Comic * getComic(){return comic;}
const BookmarksDialog * getBookmarksDialog(){return bd;}
signals:
void backgroundChanges();
void pageAvailable(bool);
void pageIsBookmark(bool);
void reset();
};
#endif

BIN
YACReader/yacreader_es.qm Normal file

Binary file not shown.

609
YACReader/yacreader_es.ts Normal file
View File

@ -0,0 +1,609 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="es_ES">
<context>
<name>BookmarksDialog</name>
<message>
<location filename="bookmarks_dialog.cpp" line="25"/>
<source>Lastest Page</source>
<translation>Última página</translation>
</message>
<message>
<location filename="bookmarks_dialog.cpp" line="66"/>
<source>Close</source>
<translation>Cerrar</translation>
</message>
<message>
<location filename="bookmarks_dialog.cpp" line="74"/>
<source>Click on any image to go to the bookmark</source>
<translation>Pulsa en cualquier imagen para ir al marcador</translation>
</message>
<message>
<location filename="bookmarks_dialog.cpp" line="92"/>
<location filename="bookmarks_dialog.cpp" line="116"/>
<source>Loading...</source>
<translation>Cargando...</translation>
</message>
</context>
<context>
<name>Comic</name>
<message>
<location filename="comic.cpp" line="57"/>
<source>Not found</source>
<translation>No encontrado</translation>
</message>
<message>
<location filename="comic.cpp" line="57"/>
<source>Comic not found</source>
<translation>Cómic no encontrado</translation>
</message>
<message>
<location filename="comic.cpp" line="98"/>
<source>No images found</source>
<translation>No se han encontrado imágenes</translation>
</message>
<message>
<location filename="comic.cpp" line="98"/>
<source>There are not images on the selected folder</source>
<translation>No hay imágenes en el directorio seleccionado</translation>
</message>
<message>
<location filename="comic.cpp" line="139"/>
<source>File error</source>
<translation>Error en archivo</translation>
</message>
<message>
<location filename="comic.cpp" line="139"/>
<source>File not found or not images in file</source>
<translation>Archivo no encontrado o no hay imágenes en él</translation>
</message>
<message>
<location filename="comic.cpp" line="192"/>
<source>7z not found</source>
<translation>7z no encontrado</translation>
</message>
<message>
<location filename="comic.cpp" line="192"/>
<source>7z wasn&apos;t found in your PATH.</source>
<translation>7z no se ha encontrado en el PATH.</translation>
</message>
<message>
<location filename="comic.cpp" line="195"/>
<source>7z crashed</source>
<translation>7z falló</translation>
</message>
<message>
<location filename="comic.cpp" line="195"/>
<source>7z crashed.</source>
<translation>7z falló.</translation>
</message>
<message>
<location filename="comic.cpp" line="198"/>
<source>7z reading</source>
<translation>7z leyendo</translation>
</message>
<message>
<location filename="comic.cpp" line="198"/>
<source>problem reading from 7z</source>
<translation>Problema leyendo desde 7z</translation>
</message>
<message>
<location filename="comic.cpp" line="201"/>
<source>7z problem</source>
<translation>7z problema</translation>
</message>
<message>
<location filename="comic.cpp" line="201"/>
<source>Unknown error 7z</source>
<translation>Error desconocido 7z</translation>
</message>
</context>
<context>
<name>Configuration</name>
<message>
<location filename="configuration.cpp" line="148"/>
<source>Saving config file....</source>
<translation>Guardando el archivo de configuración...</translation>
</message>
<message>
<location filename="configuration.cpp" line="148"/>
<source>There was a problem saving YACReader configuration. Please, check if you have enough permissions in the YACReader root folder.</source>
<translation>Hubo un problema al guardar la configuración de YACReader. Por favor, comprueba si tienes suficientes permisos en el directorio raíz de YACReader.</translation>
</message>
</context>
<context>
<name>GoToDialog</name>
<message>
<location filename="goto_dialog.cpp" line="17"/>
<source>Page : </source>
<translation>Página :</translation>
</message>
<message>
<location filename="goto_dialog.cpp" line="25"/>
<source>Go To</source>
<translation>Ir a</translation>
</message>
<message>
<location filename="goto_dialog.cpp" line="27"/>
<source>Cancel</source>
<translation>Cancelar</translation>
</message>
<message>
<location filename="goto_dialog.cpp" line="41"/>
<location filename="goto_dialog.cpp" line="73"/>
<source>Total pages : </source>
<translation>Páginas totales:</translation>
</message>
<message>
<location filename="goto_dialog.cpp" line="55"/>
<source>Go to...</source>
<translation>Ir a...</translation>
</message>
</context>
<context>
<name>GoToFlow</name>
<message>
<location filename="goto_flow.cpp" line="40"/>
<source>Page : </source>
<translation>Página:</translation>
</message>
<message>
<source>Total pages : </source>
<translation type="obsolete">Page:</translation>
</message>
</context>
<context>
<name>HelpAboutDialog</name>
<message>
<location filename="../common/custom_widgets.cpp" line="32"/>
<source>About</source>
<translation>Acerca de</translation>
</message>
<message>
<location filename="../common/custom_widgets.cpp" line="35"/>
<source>Help</source>
<translation>Ayuda</translation>
</message>
</context>
<context>
<name>MainWindowViewer</name>
<message>
<location filename="main_window_viewer.cpp" line="104"/>
<source>&amp;Open</source>
<translation>&amp;Abrir</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="105"/>
<source>O</source>
<translation>O</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="107"/>
<source>Open a comic</source>
<translation>Abrir cómic</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="110"/>
<source>Open Folder</source>
<translation>Abrir carpeta</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="111"/>
<source>Ctrl+O</source>
<translation>Ctrl+O</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="113"/>
<source>Open image folder</source>
<oldsource>Open images in a folder</oldsource>
<translation>Abrir carpeta de imágenes</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="116"/>
<source>Save</source>
<translation>Guardar</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="118"/>
<location filename="main_window_viewer.cpp" line="400"/>
<source>Save current page</source>
<translation>Guardar la página actual</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="122"/>
<source>Previous Comic</source>
<translation>Cómic anterior</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="125"/>
<source>Open previous comic</source>
<translation>Abrir cómic anterior</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="129"/>
<source>Next Comic</source>
<translation>Siguiente Cómic</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="132"/>
<source>Open next comic</source>
<translation>Abrir siguiente cómic</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="136"/>
<source>&amp;Previous</source>
<translation>A&amp;nterior</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="139"/>
<source>Go to previous page</source>
<translation>Ir a la página anterior</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="143"/>
<source>&amp;Next</source>
<translation>Siguie&amp;nte</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="146"/>
<source>Go to next page</source>
<translation>Ir a la página siguiente</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="150"/>
<source>Fit Width</source>
<translation>Ajustar anchura</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="151"/>
<source>A</source>
<translation>A</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="156"/>
<source>Fit image to ...</source>
<translation>Ajustar imagen a...</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="160"/>
<source>Rotate image to the left</source>
<translation>Rotar imagen a la izquierda</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="161"/>
<source>L</source>
<translation>L</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="166"/>
<source>Rotate image to the right</source>
<translation>Rotar imagen a la derecha</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="167"/>
<source>R</source>
<translation>R</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="172"/>
<source>Double page mode</source>
<translation>Modo a doble página</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="173"/>
<source>Switch to double page mode</source>
<translation>Cambiar a modo de doble página</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="174"/>
<source>D</source>
<translation>D</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="181"/>
<source>Go To</source>
<translation>Ir a</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="182"/>
<source>G</source>
<translation>G</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="185"/>
<source>Go to page ...</source>
<translation>Ir a página...</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="188"/>
<source>Options</source>
<translation>Opciones</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="189"/>
<source>C</source>
<translation>C</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="190"/>
<source>YACReader options</source>
<translation>Opciones de YACReader</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="195"/>
<source>Help</source>
<translation>Ayuda</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="196"/>
<source>Help, About YACReader</source>
<translation>Ayuda, Sobre YACReader</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="201"/>
<source>Magnifying glass</source>
<translation>Lupa</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="202"/>
<source>Switch Magnifying glass</source>
<translation>Lupa On/Off</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="203"/>
<source>Z</source>
<translation>Z</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="209"/>
<source>Set bookmark</source>
<translation>Añadir marcador</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="210"/>
<source>Set a bookmark on the current page</source>
<translation>Añadir un marcador en la página actual</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="219"/>
<source>Show bookmarks</source>
<translation>Mostrar marcadores</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="220"/>
<source>Show the bookmarks of the current comic</source>
<translation>Mostrar los marcadores del cómic actual</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="221"/>
<source>M</source>
<translation>M</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="226"/>
<source>Show keyboard shortcuts</source>
<translation>Mostrar atajos de teclado</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="230"/>
<source>Show Info</source>
<translation>Mostrar información</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="231"/>
<source>I</source>
<translation>I</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="236"/>
<source>Close</source>
<translation>Cerrar</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="241"/>
<source>Show Dictionary</source>
<translation>Mostrar diccionario</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="248"/>
<source>Always on top</source>
<translation>Siempre visible</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="256"/>
<source>Show full size</source>
<translation>Mostrar a tamaño original</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="267"/>
<source>&amp;File</source>
<translation>&amp;Archivo</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="362"/>
<source>Open Comic</source>
<translation>Abrir cómic</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="362"/>
<source>Comic files (*.cbr *.cbz *.rar *.zip *.tar *.arj)</source>
<translation>Archivos de cómic (*.cbr *.cbz *.rar *.zip *.tar *.arj)</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="381"/>
<source>Open folder</source>
<translation>Abrir carpeta</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="400"/>
<source>Image files (*.jpg)</source>
<translation>Archivos de imagen (*.jpg)</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="533"/>
<source>There is a new version avaliable</source>
<translation>Hay una nueva versión disponible</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="534"/>
<source>Do you want to download the new version?</source>
<translation>¿Desea descargar la nueva versión?</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="593"/>
<source>Saving error log file....</source>
<translation>Guardando el archivo de log...</translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="593"/>
<source>There was a problem saving YACReader error log file. Please, check if you have enough permissions in the YACReader root folder.</source>
<translation>Hubo un problema al guardar el archivo de log de YACReader. Por favor, comprueba si tienes suficientes permisos en el directorio raíz de YACReader.</translation>
</message>
</context>
<context>
<name>OptionsDialog</name>
<message>
<location filename="options_dialog.cpp" line="15"/>
<source>&quot;Go to flow&quot; size</source>
<translation>Tamaño de &quot;Go to flow&quot;</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="26"/>
<source>My comics path</source>
<translation>Ruta a mis cómics</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="35"/>
<source>Save</source>
<translation>Guardar</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="36"/>
<source>Cancel</source>
<translation>Cancelar</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="41"/>
<source>How to show pages in GoToFlow:</source>
<translation>¿Cómo deseas que se muestren las páginas en &quot;Go To Flow&quot;:</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="43"/>
<source>CoverFlow look</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="44"/>
<source>Stripe look</source>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="45"/>
<source>Overlapped Stripe look</source>
<oldsource>Overlaped Stripe look</oldsource>
<translation></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="78"/>
<source>Page width stretch</source>
<translation>Ajuste en anchura de la página</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="98"/>
<source>Background color</source>
<translation>Color de fondo</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="101"/>
<source>Choose</source>
<translation>Elegir</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="108"/>
<source>Restart is needed</source>
<translation>Es necesario reiniciar</translation>
</message>
<message>
<location filename="options_dialog.cpp" line="134"/>
<source>Comics directory</source>
<translation>Directorio de cómics</translation>
</message>
</context>
<context>
<name>QPushButton</name>
<message>
<source>Hello world!</source>
<translation type="obsolete">Hola mundo!</translation>
</message>
</context>
<context>
<name>ShortcutsDialog</name>
<message>
<location filename="shortcuts_dialog.cpp" line="16"/>
<source>YACReader keyboard shortcuts</source>
<translation>Atajos de teclado de YACReader</translation>
</message>
<message>
<location filename="shortcuts_dialog.cpp" line="20"/>
<source>Close</source>
<translation>Cerrar</translation>
</message>
<message>
<location filename="shortcuts_dialog.cpp" line="66"/>
<source>Keyboard Shortcuts</source>
<translation>Atajos de teclado</translation>
</message>
</context>
<context>
<name>Viewer</name>
<message>
<location filename="viewer.cpp" line="39"/>
<location filename="viewer.cpp" line="567"/>
<source>Press &apos;O&apos; to open comic.</source>
<translation>Pulsa &apos;O&apos; para abrir un fichero.</translation>
</message>
<message>
<source>Show Info</source>
<translation type="obsolete">Mostrar información</translation>
</message>
<message>
<source>I</source>
<translation type="obsolete">I</translation>
</message>
<message>
<location filename="viewer.cpp" line="580"/>
<source>Loading...please wait!</source>
<translation>Cargando...espere, por favor!</translation>
</message>
</context>
<context>
<name>YACReaderFieldEdit</name>
<message>
<location filename="../common/custom_widgets.cpp" line="383"/>
<location filename="../common/custom_widgets.cpp" line="403"/>
<source>Click to overwrite</source>
<translation>Click para sobreescribir</translation>
</message>
<message>
<location filename="../common/custom_widgets.cpp" line="385"/>
<source>Restore to default</source>
<translation>Restaurar valor por defecto</translation>
</message>
</context>
<context>
<name>YACReaderFieldPlainTextEdit</name>
<message>
<location filename="../common/custom_widgets.cpp" line="421"/>
<location filename="../common/custom_widgets.cpp" line="432"/>
<location filename="../common/custom_widgets.cpp" line="457"/>
<location filename="../common/custom_widgets.cpp" line="463"/>
<source>Click to overwrite</source>
<translation>Click para sobreescribir</translation>
</message>
<message>
<location filename="../common/custom_widgets.cpp" line="422"/>
<source>Restore to default</source>
<translation>Restaurar valor por defecto</translation>
</message>
</context>
</TS>

588
YACReader/yacreader_fr.ts Normal file
View File

@ -0,0 +1,588 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.0" language="fr_FR">
<context>
<name>BookmarksDialog</name>
<message>
<location filename="bookmarks_dialog.cpp" line="25"/>
<source>Lastest Page</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="bookmarks_dialog.cpp" line="66"/>
<source>Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="bookmarks_dialog.cpp" line="74"/>
<source>Click on any image to go to the bookmark</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="bookmarks_dialog.cpp" line="92"/>
<location filename="bookmarks_dialog.cpp" line="116"/>
<source>Loading...</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Comic</name>
<message>
<location filename="comic.cpp" line="57"/>
<source>Not found</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="comic.cpp" line="57"/>
<source>Comic not found</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="comic.cpp" line="98"/>
<source>No images found</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="comic.cpp" line="98"/>
<source>There are not images on the selected folder</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="comic.cpp" line="139"/>
<source>File error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="comic.cpp" line="139"/>
<source>File not found or not images in file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="comic.cpp" line="192"/>
<source>7z not found</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="comic.cpp" line="192"/>
<source>7z wasn&apos;t found in your PATH.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="comic.cpp" line="195"/>
<source>7z crashed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="comic.cpp" line="195"/>
<source>7z crashed.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="comic.cpp" line="198"/>
<source>7z reading</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="comic.cpp" line="198"/>
<source>problem reading from 7z</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="comic.cpp" line="201"/>
<source>7z problem</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="comic.cpp" line="201"/>
<source>Unknown error 7z</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Configuration</name>
<message>
<location filename="configuration.cpp" line="148"/>
<source>Saving config file....</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="configuration.cpp" line="148"/>
<source>There was a problem saving YACReader configuration. Please, check if you have enough permissions in the YACReader root folder.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>GoToDialog</name>
<message>
<location filename="goto_dialog.cpp" line="17"/>
<source>Page : </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="goto_dialog.cpp" line="25"/>
<source>Go To</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="goto_dialog.cpp" line="27"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="goto_dialog.cpp" line="41"/>
<location filename="goto_dialog.cpp" line="73"/>
<source>Total pages : </source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="goto_dialog.cpp" line="55"/>
<source>Go to...</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>GoToFlow</name>
<message>
<location filename="goto_flow.cpp" line="40"/>
<source>Page : </source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>HelpAboutDialog</name>
<message>
<location filename="../common/custom_widgets.cpp" line="32"/>
<source>About</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../common/custom_widgets.cpp" line="35"/>
<source>Help</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>MainWindowViewer</name>
<message>
<location filename="main_window_viewer.cpp" line="104"/>
<source>&amp;Open</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="105"/>
<source>O</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="107"/>
<source>Open a comic</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="110"/>
<source>Open Folder</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="111"/>
<source>Ctrl+O</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="113"/>
<source>Open image folder</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="116"/>
<source>Save</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="118"/>
<location filename="main_window_viewer.cpp" line="400"/>
<source>Save current page</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="122"/>
<source>Previous Comic</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="125"/>
<source>Open previous comic</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="129"/>
<source>Next Comic</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="132"/>
<source>Open next comic</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="136"/>
<source>&amp;Previous</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="139"/>
<source>Go to previous page</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="143"/>
<source>&amp;Next</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="146"/>
<source>Go to next page</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="150"/>
<source>Fit Width</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="151"/>
<source>A</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="156"/>
<source>Fit image to ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="160"/>
<source>Rotate image to the left</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="161"/>
<source>L</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="166"/>
<source>Rotate image to the right</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="167"/>
<source>R</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="172"/>
<source>Double page mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="173"/>
<source>Switch to double page mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="174"/>
<source>D</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="181"/>
<source>Go To</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="182"/>
<source>G</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="185"/>
<source>Go to page ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="188"/>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="189"/>
<source>C</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="190"/>
<source>YACReader options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="195"/>
<source>Help</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="196"/>
<source>Help, About YACReader</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="201"/>
<source>Magnifying glass</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="202"/>
<source>Switch Magnifying glass</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="203"/>
<source>Z</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="209"/>
<source>Set bookmark</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="210"/>
<source>Set a bookmark on the current page</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="219"/>
<source>Show bookmarks</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="220"/>
<source>Show the bookmarks of the current comic</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="221"/>
<source>M</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="226"/>
<source>Show keyboard shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="230"/>
<source>Show Info</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="231"/>
<source>I</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="236"/>
<source>Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="241"/>
<source>Show Dictionary</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="248"/>
<source>Always on top</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="256"/>
<source>Show full size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="267"/>
<source>&amp;File</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="362"/>
<source>Open Comic</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="362"/>
<source>Comic files (*.cbr *.cbz *.rar *.zip *.tar *.arj)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="381"/>
<source>Open folder</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="400"/>
<source>Image files (*.jpg)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="533"/>
<source>There is a new version avaliable</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="534"/>
<source>Do you want to download the new version?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="593"/>
<source>Saving error log file....</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="main_window_viewer.cpp" line="593"/>
<source>There was a problem saving YACReader error log file. Please, check if you have enough permissions in the YACReader root folder.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>OptionsDialog</name>
<message>
<location filename="options_dialog.cpp" line="15"/>
<source>&quot;Go to flow&quot; size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="26"/>
<source>My comics path</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="35"/>
<source>Save</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="36"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="41"/>
<source>How to show pages in GoToFlow:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="43"/>
<source>CoverFlow look</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="44"/>
<source>Stripe look</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="45"/>
<source>Overlapped Stripe look</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="78"/>
<source>Page width stretch</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="98"/>
<source>Background color</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="101"/>
<source>Choose</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="108"/>
<source>Restart is needed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="options_dialog.cpp" line="134"/>
<source>Comics directory</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ShortcutsDialog</name>
<message>
<location filename="shortcuts_dialog.cpp" line="16"/>
<source>YACReader keyboard shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="shortcuts_dialog.cpp" line="20"/>
<source>Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="shortcuts_dialog.cpp" line="66"/>
<source>Keyboard Shortcuts</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Viewer</name>
<message>
<location filename="viewer.cpp" line="39"/>
<location filename="viewer.cpp" line="567"/>
<source>Press &apos;O&apos; to open comic.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="viewer.cpp" line="580"/>
<source>Loading...please wait!</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>YACReaderFieldEdit</name>
<message>
<location filename="../common/custom_widgets.cpp" line="383"/>
<location filename="../common/custom_widgets.cpp" line="403"/>
<source>Click to overwrite</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../common/custom_widgets.cpp" line="385"/>
<source>Restore to default</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>YACReaderFieldPlainTextEdit</name>
<message>
<location filename="../common/custom_widgets.cpp" line="421"/>
<location filename="../common/custom_widgets.cpp" line="432"/>
<location filename="../common/custom_widgets.cpp" line="457"/>
<location filename="../common/custom_widgets.cpp" line="463"/>
<source>Click to overwrite</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../common/custom_widgets.cpp" line="422"/>
<source>Restore to default</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>