diff --git a/YACReaderLibrary/YACReaderLibrary.pro b/YACReaderLibrary/YACReaderLibrary.pro index e2a52e2e..aaba7a2f 100644 --- a/YACReaderLibrary/YACReaderLibrary.pro +++ b/YACReaderLibrary/YACReaderLibrary.pro @@ -12,7 +12,7 @@ INCLUDEPATH += ../common \ ../YACReader CONFIG += release CONFIG -= flat -QT += sql network +QT += sql network opengl # Input HEADERS += comic_flow.h \ @@ -43,7 +43,9 @@ HEADERS += comic_flow.h \ ../common/check_new_version.h \ ../YACReader/comic.h \ ../YACReader/bookmarks.h \ - server_config_dialog.h + server_config_dialog.h \ + ../common/comic_flow_widget.h \ + ../common/yacreader_flow_gl.h SOURCES += comic_flow.cpp \ create_library_dialog.cpp \ @@ -74,7 +76,9 @@ SOURCES += comic_flow.cpp \ ../common/check_new_version.cpp \ ../YACReader/comic.cpp \ ../YACReader/bookmarks.cpp \ - server_config_dialog.cpp + server_config_dialog.cpp \ + ../common/comic_flow_widget.cpp \ + ../common/yacreader_flow_gl.cpp include(./server/server.pri) diff --git a/YACReaderLibrary/library_window.cpp b/YACReaderLibrary/library_window.cpp index 25a946f2..6050cfc6 100644 --- a/YACReaderLibrary/library_window.cpp +++ b/YACReaderLibrary/library_window.cpp @@ -51,7 +51,7 @@ void LibraryWindow::doLayout() QSplitter * sHorizontal = new QSplitter(Qt::Horizontal); //spliter principal //TODO: flowType is a global variable //CONFIG COMIC_FLOW-------------------------------------------------------- - comicFlow = new ComicFlow(0,flowType); + comicFlow = new ComicFlowWidgetGL(0); comicFlow->setFocusPolicy(Qt::StrongFocus); comicFlow->setShowMarks(true); QMatrix m; diff --git a/YACReaderLibrary/library_window.h b/YACReaderLibrary/library_window.h index f04403d3..f3857ceb 100644 --- a/YACReaderLibrary/library_window.h +++ b/YACReaderLibrary/library_window.h @@ -15,7 +15,8 @@ #include "create_library_dialog.h" #include "add_library_dialog.h" #include "library_creator.h" -#include "comic_flow.h" +//#include "comic_flow.h" +#include "comic_flow_widget.h" #include "custom_widgets.h" #include "rename_library_dialog.h" #include "properties_dialog.h" @@ -53,7 +54,7 @@ private: YACReaderSortComics * proxySort; PackageManager * packageManager; - ComicFlow * comicFlow; + ComicFlowWidget * comicFlow; QSize slideSizeW; QSize slideSizeF; //search filter diff --git a/YACReaderLibrary/server/controllers/comiccontroller.cpp b/YACReaderLibrary/server/controllers/comiccontroller.cpp index 46f80369..2c81f152 100644 --- a/YACReaderLibrary/server/controllers/comiccontroller.cpp +++ b/YACReaderLibrary/server/controllers/comiccontroller.cpp @@ -42,7 +42,8 @@ void ComicController::service(HttpRequest& request, HttpResponse& response) { HttpSession session=Static::sessionStore->getSession(request,response); - QStringList pathElements = ((QString)request.getPath()).split('/'); + QString path = QUrl::fromPercentEncoding(request.getPath()).toLatin1(); + QStringList pathElements = path.split('/'); QString libraryName = pathElements.at(2); qulonglong comicId = pathElements.at(4).toULongLong(); diff --git a/YACReaderLibrary/server/controllers/covercontroller.cpp b/YACReaderLibrary/server/controllers/covercontroller.cpp index b2e34186..08ce5ebf 100644 --- a/YACReaderLibrary/server/controllers/covercontroller.cpp +++ b/YACReaderLibrary/server/controllers/covercontroller.cpp @@ -16,7 +16,7 @@ void CoverController::service(HttpRequest& request, HttpResponse& response) QMap libraries = mw->getLibraries(); - QString path = request.getPath(); + QString path = QUrl::fromPercentEncoding(request.getPath()).toLatin1(); QStringList pathElements = path.split('/'); QString libraryName = pathElements.at(2); QString fileName = pathElements.at(4); diff --git a/YACReaderLibrary/server/controllers/errorcontroller.cpp b/YACReaderLibrary/server/controllers/errorcontroller.cpp index e967d572..02ae039c 100644 --- a/YACReaderLibrary/server/controllers/errorcontroller.cpp +++ b/YACReaderLibrary/server/controllers/errorcontroller.cpp @@ -12,6 +12,16 @@ ErrorController::ErrorController(int errorCode) void ErrorController::service(HttpRequest& request, HttpResponse& response) { - response.setStatus(300,"redirect"); - response.write(" ", true); + switch(error) + { + case 300: + response.setStatus(300,"redirect"); + response.write(" ", true); + break; + case 404: + response.setStatus(404,"not found"); + response.write("404 not found",true); + break; + } + } \ No newline at end of file diff --git a/YACReaderLibrary/server/controllers/foldercontroller.cpp b/YACReaderLibrary/server/controllers/foldercontroller.cpp index 389afb42..d54b5b3d 100644 --- a/YACReaderLibrary/server/controllers/foldercontroller.cpp +++ b/YACReaderLibrary/server/controllers/foldercontroller.cpp @@ -29,25 +29,24 @@ void FolderController::service(HttpRequest& request, HttpResponse& response) QString y = session.get("xxx").toString(); //response.writeText(QString("session xxx : %1
").arg(y)); - Template t=Static::templateLoader->getTemplate("folder",request.getHeader("Accept-Language")); + Template t=Static::templateLoader->getTemplate("folder_"+session.getDeviceType(),request.getHeader("Accept-Language")); t.enableWarnings(); - QString path = request.getPath(); + QString path = QUrl::fromPercentEncoding(request.getPath()).toLatin1(); QStringList pathElements = path.split('/'); QString libraryName = pathElements.at(2); qulonglong parentId = pathElements.at(4).toULongLong(); QList folderContent = mw->getFolderContentFromLibrary(libraryName,parentId); QList folderComics = mw->getFolderComicsFromLibrary(libraryName,parentId); + response.writeText(libraryName); + folderContent.append(folderComics); qSort(folderContent.begin(),folderContent.end(),LibraryItemSorter()); folderComics.clear(); - - qulonglong backId = mw->getParentFromComicFolderId(libraryName,parentId); - int page = 0; QByteArray p = request.getParameter("page"); if(p.length() != 0) @@ -57,11 +56,10 @@ void FolderController::service(HttpRequest& request, HttpResponse& response) //QString currentPath = session.get("currentPath").toString(); //QStringList pathSize = currentPath.split("/").last().toInt; - if(backId == 1 && parentId == 1) t.setVariable(QString("upurl"),"/?page=0"); else - t.setVariable(QString("upurl"),"/library/" + libraryName + "/folder/" +QString("%1").arg(backId));//.arg(upPage)); + t.setVariable(QString("upurl"),"/library/" + QUrl::toPercentEncoding(libraryName) + "/folder/" +QString("%1").arg(backId));//.arg(upPage)); /*if(currentPath.length()>0) { @@ -115,19 +113,23 @@ void FolderController::service(HttpRequest& request, HttpResponse& response) t.setVariable(QString("element%1.browse").arg(i),QString("Browse").arg(QString("/library/%1/folder/%2").arg(libraryName).arg(item->id))); //t.setVariable(QString("element%1.url").arg(i),"/library/"+libraryName+"/folder/"+QString("%1").arg(folderContent.at(i + (page*10))->id)); - t.setVariable(QString("element%1.downloadurl").arg(i),"/library/"+libraryName+"/folder/"+QString("%1/info").arg(folderContent.at(i + (page*elementsPerPage))->id)); + //t.setVariable(QString("element%1.downloadurl").arg(i),"/library/"+libraryName+"/folder/"+QString("%1/info").arg(folderContent.at(i + (page*elementsPerPage))->id)); + t.setVariable(QString("element%1.download").arg(i),QString("Download").arg("/library/"+QUrl::toPercentEncoding(libraryName)+"/folder/"+QString("%1/info").arg(folderContent.at(i + (page*elementsPerPage))->id))); } else { const ComicDB * comic = (ComicDB *)item; t.setVariable(QString("element%1.browse").arg(i),""); t.setVariable(QString("element%1.image.width").arg(i),"80px"); - t.setVariable(QString("element%1.downloadurl").arg(i),"/library/"+libraryName+"/comic/"+QString("%1").arg(comic->id)); - //t.setVariable(QString("element%1.image.url").arg(i),"/images/f.png"); - if(session.isComicOnDevice(comic->info.hash)) - t.setVariable(QString("element%1.image.url").arg(i),"/images/f.png"); + //t.setVariable(QString("element%1.downloadurl").arg(i),"/library/"+libraryName+"/comic/"+QString("%1").arg(comic->id)); + if(!session.isComicOnDevice(comic->info.hash)) + t.setVariable(QString("element%1.download").arg(i),QString("Download").arg("/library/"+QUrl::toPercentEncoding(libraryName)+"/comic/"+QString("%1").arg(comic->id))); else - t.setVariable(QString("element%1.image.url").arg(i),QString("/library/%1/cover/%2.jpg").arg(libraryName).arg(comic->info.hash)); + t.setVariable(QString("element%1.download").arg(i),QString("")); + + //t.setVariable(QString("element%1.image.url").arg(i),"/images/f.png"); + + t.setVariable(QString("element%1.image.url").arg(i),QString("/library/%1/cover/%2.jpg").arg(QString(QUrl::toPercentEncoding(libraryName))).arg(comic->info.hash)); } i++; } @@ -172,8 +174,8 @@ void FolderController::service(HttpRequest& request, HttpResponse& response) t.setVariable(QString("elementcomic%1.name").arg(j),comic->name); //else // t.setVariable(QString("elementcomic%1.name").arg(i),*comic->info.title); - t.setVariable(QString("elementcomic%1.url").arg(j),"/library/"+libraryName+"/comic/"+QString("%1").arg(comic->id)); - t.setVariable(QString("elementcomic%1.coverulr").arg(j),"/library/"+libraryName+"/cover/"+QString("%1").arg(comic->info.hash + ".jpg")); + t.setVariable(QString("elementcomic%1.url").arg(j),"/library/"+QUrl::toPercentEncoding(libraryName)+"/comic/"+QString("%1").arg(comic->id)); + t.setVariable(QString("elementcomic%1.coverulr").arg(j),"/library/"+QUrl::toPercentEncoding(libraryName)+"/cover/"+QString("%1").arg(comic->info.hash + ".jpg")); j++; } @@ -210,7 +212,7 @@ void FolderController::service(HttpRequest& request, HttpResponse& response) { //response.writeText(QString("%1 - %2
").arg(*itr).arg(count)); t.setVariable(QString("index%1.indexname").arg(i), *itr); - t.setVariable(QString("index%1.url").arg(i),QString("/library/%1/folder/%2?page=%3").arg(libraryName).arg(parentId).arg(indexPage)); + t.setVariable(QString("index%1.url").arg(i),QString("/library/%1/folder/%2?page=%3").arg(QString(QUrl::toPercentEncoding(libraryName))).arg(parentId).arg(indexPage)); i++; count += indexCount.value(*itr); indexPage = count/elementsPerPage; @@ -222,13 +224,19 @@ void FolderController::service(HttpRequest& request, HttpResponse& response) while(z < numPages) { - t.setVariable(QString("page%1.url").arg(z),QString("/library/%1/folder/%2?page=%3").arg(libraryName).arg(parentId).arg(z)); + t.setVariable(QString("page%1.url").arg(z),QString("/library/%1/folder/%2?page=%3").arg(QString(QUrl::toPercentEncoding(libraryName))).arg(parentId).arg(z)); + t.setVariable(QString("page%1.number").arg(z),QString("%1").arg(z)); if(page == z) - t.setVariable(QString("page%1.number").arg(z),QString("%1").arg(z)); + t.setVariable(QString("page%1.current").arg(z),"current"); else - t.setVariable(QString("page%1.number").arg(z),QString("%1").arg(z)); + t.setVariable(QString("page%1.current").arg(z),""); z++; } + + t.setVariable("page.first",QString("/library/%1/folder/%2?page=%3").arg(QString(QUrl::toPercentEncoding(libraryName))).arg(parentId).arg(0)); + t.setVariable("page.previous",QString("/library/%1/folder/%2?page=%3").arg(QString(QUrl::toPercentEncoding(libraryName))).arg(parentId).arg((page==0)?page:page-1)); + t.setVariable("page.next",QString("/library/%1/folder/%2?page=%3").arg(QString(QUrl::toPercentEncoding(libraryName))).arg(parentId).arg((page==numPages-1)?page:page+1)); + t.setVariable("page.last",QString("/library/%1/folder/%2?page=%3").arg(QString(QUrl::toPercentEncoding(libraryName))).arg(parentId).arg(numPages-1)); } else { diff --git a/YACReaderLibrary/server/controllers/folderinfocontroller.cpp b/YACReaderLibrary/server/controllers/folderinfocontroller.cpp index 07312e8c..f9404a27 100644 --- a/YACReaderLibrary/server/controllers/folderinfocontroller.cpp +++ b/YACReaderLibrary/server/controllers/folderinfocontroller.cpp @@ -15,7 +15,7 @@ void FolderInfoController::service(HttpRequest& request, HttpResponse& response) { response.setHeader("Content-Type", "plain/text; charset=ISO-8859-1"); - QString path = request.getPath(); + QString path = QUrl::fromPercentEncoding(request.getPath()).toLatin1(); QStringList pathElements = path.split('/'); QString libraryName = pathElements.at(2); qulonglong parentId = pathElements.at(4).toULongLong(); @@ -26,14 +26,14 @@ void FolderInfoController::service(HttpRequest& request, HttpResponse& response) for(QList::const_iterator itr = folderContent.constBegin();itr!=folderContent.constEnd();itr++) { currentFolder = (Folder *)(*itr); - response.writeText(QString("/library/%1/folder/%2/info\n").arg(libraryName).arg(currentFolder->id)); + response.writeText(QString("/library/%1/folder/%2/info\n").arg(QString(QUrl::toPercentEncoding(libraryName))).arg(currentFolder->id)); } ComicDB * currentComic; for(QList::const_iterator itr = folderComics.constBegin();itr!=folderComics.constEnd();itr++) { currentComic = (ComicDB *)(*itr); - response.writeText(QString("/library/%1/comic/%2\n").arg(libraryName).arg(currentComic->id)); + response.writeText(QString("/library/%1/comic/%2\n").arg(QString(QUrl::toPercentEncoding(libraryName))).arg(currentComic->id)); } } \ No newline at end of file diff --git a/YACReaderLibrary/server/controllers/librariescontroller.cpp b/YACReaderLibrary/server/controllers/librariescontroller.cpp index 6951afc1..fc71a239 100644 --- a/YACReaderLibrary/server/controllers/librariescontroller.cpp +++ b/YACReaderLibrary/server/controllers/librariescontroller.cpp @@ -13,21 +13,28 @@ void LibrariesController::service(HttpRequest& request, HttpResponse& response) response.setHeader("Content-Type", "text/html; charset=ISO-8859-1"); HttpSession session=Static::sessionStore->getSession(request,response); - - session.set("xxx","yyy"); + session.set("ySession","ok"); QString postData = QString::fromUtf8(request.getBody()); response.writeText(postData); QList data = postData.split("\n"); - session.setDeviceType(data.at(0).split(":").at(1)); - session.setDisplayType(data.at(1).split(":").at(1)); - QList comics = data.at(2).split(":").at(1).split("\t"); - foreach(QString hash,comics) + if(data.length() > 2) { - session.setComicOnDevice(hash); + session.setDeviceType(data.at(0).split(":").at(1)); + session.setDisplayType(data.at(1).split(":").at(1)); + QList comics = data.at(2).split(":").at(1).split("\t"); + foreach(QString hash,comics) + { + session.setComicOnDevice(hash); + } + } + else //valores por defecto, con propositos de depuración + { + session.setDeviceType("iphone"); + session.setDisplayType("retina"); } - Template t=Static::templateLoader->getTemplate("libraries",request.getHeader("Accept-Language")); + Template t=Static::templateLoader->getTemplate("libraries_"+session.getDeviceType(),request.getHeader("Accept-Language")); t.enableWarnings(); QMap libraries = mw->getLibraries(); @@ -36,7 +43,7 @@ void LibrariesController::service(HttpRequest& request, HttpResponse& response) t.loop("library",names.length()); int i=0; while (igetSession(request,response); - QStringList pathElements = ((QString)request.getPath()).split('/'); + QString path = QUrl::fromPercentEncoding(request.getPath()).toLatin1(); + QStringList pathElements = path.split('/'); QString libraryName = pathElements.at(2); qulonglong comicId = pathElements.at(4).toULongLong(); unsigned int page = pathElements.at(6).toUInt(); diff --git a/YACReaderLibrary/server/lib/bfHttpServer/staticfilecontroller.cpp b/YACReaderLibrary/server/lib/bfHttpServer/staticfilecontroller.cpp index 08293989..c8c6ace7 100644 --- a/YACReaderLibrary/server/lib/bfHttpServer/staticfilecontroller.cpp +++ b/YACReaderLibrary/server/lib/bfHttpServer/staticfilecontroller.cpp @@ -7,6 +7,8 @@ #include #include #include +#include "httpsession.h" +#include "static.h" StaticFileController::StaticFileController(QSettings* settings, QObject* parent) :HttpRequestHandler(parent) @@ -61,12 +63,14 @@ void StaticFileController::service(HttpRequest& request, HttpResponse& response) path+="/index.html"; } - //TODO(DONE) carga sensible a la localización + //TODO(DONE) carga sensible al dispositivo y a la localización QString stringPath = path; QStringList paths = QString(path).split('/'); QString fileName = paths.last(); stringPath.remove(fileName); - fileName = getLocalizedFileName(fileName, request.getHeader("Accept-Language"), stringPath); + HttpSession session=Static::sessionStore->getSession(request,response); + QString device = session.getDeviceType(); + fileName = getDeviceAwareFileName(fileName, device, request.getHeader("Accept-Language"), stringPath); QString newPath = stringPath.append(fileName); //END_TODO QFile file(docroot+path); @@ -171,3 +175,17 @@ QString StaticFileController::getLocalizedFileName(QString fileName, QString loc return fileName; } + +QString StaticFileController::getDeviceAwareFileName(QString fileName, QString device, QString locales, QString path) const +{ + QFileInfo fi(fileName); + QString baseName = fi.baseName(); + QString extension = fi.completeSuffix(); + + QString completeFileName = getLocalizedFileName(fileName+"_"+device+"."+extension,locales,path); + + if(QFile(docroot+"/"+path+completeFileName).exists()) + return completeFileName; //existe un archivo específico para este dispositivo y locales + else + return getLocalizedFileName(fileName,locales,path); //no hay archivo específico para el dispositivo, pero puede haberlo para estas locales +} \ No newline at end of file diff --git a/YACReaderLibrary/server/lib/bfHttpServer/staticfilecontroller.h b/YACReaderLibrary/server/lib/bfHttpServer/staticfilecontroller.h index 9987378a..178cc226 100644 --- a/YACReaderLibrary/server/lib/bfHttpServer/staticfilecontroller.h +++ b/YACReaderLibrary/server/lib/bfHttpServer/staticfilecontroller.h @@ -69,6 +69,7 @@ private: /** Timeout for each cached file */ int cacheTimeout; + /** Maximum size of files in cache, larger files are not cached */ int maxCachedFileSize; @@ -81,7 +82,8 @@ private: /** Set a content-type header in the response depending on the ending of the filename */ void setContentType(QString file, HttpResponse& response) const; - QString StaticFileController::getLocalizedFileName(QString fileName, QString locales, QString path) const; + QString getLocalizedFileName(QString fileName, QString locales, QString path) const; + QString getDeviceAwareFileName(QString fileName, QString device, QString locales, QString path) const; bool exists(QString localizedName, QString path) const; }; diff --git a/YACReaderLibrary/server/requestmapper.cpp b/YACReaderLibrary/server/requestmapper.cpp index bb2600ea..31fc39be 100644 --- a/YACReaderLibrary/server/requestmapper.cpp +++ b/YACReaderLibrary/server/requestmapper.cpp @@ -20,6 +20,10 @@ #include "controllers/pagecontroller.h" #include "controllers/errorcontroller.h" +#include "library_window.h" + +extern LibraryWindow * mw; + RequestMapper::RequestMapper(QObject* parent) :HttpRequestHandler(parent) {} @@ -34,6 +38,10 @@ void RequestMapper::service(HttpRequest& request, HttpResponse& response) { QRegExp cover("/library/.+/cover/[0-9a-f]+.jpg"); QRegExp comicPage("/library/.+/comic/[0-9]+/page/[0-9]+/?"); + QRegExp library("/library/([^/.]+)/.+"); + + path = QUrl::fromPercentEncoding(path).toLatin1(); + //primera petición, se ha hecho un post, se sirven las bibliotecas si la seguridad mediante login no está habilitada if(path == "/") { @@ -41,42 +49,44 @@ void RequestMapper::service(HttpRequest& request, HttpResponse& response) { } else - { //se comprueba que la sesión sea la correcta con el fin de evitar accesos no autorizados HttpSession session=Static::sessionStore->getSession(request,response); - if(session.contains("xxx")) + if(session.contains("ySession")) { - - //listar el contenido del folder - if(folder.exactMatch(path)) + if(library.indexIn(path)!=-1 && mw->getLibraries().contains(library.cap(1)) ) { - FolderController().service(request, response); - } - else if (folderInfo.exactMatch(path)) - { - FolderInfoController().service(request, response); - } - else if(cover.exactMatch(path)) - { - CoverController().service(request, response); - } - else if(comic.exactMatch(path)) - { - ComicController().service(request, response); - } - else if(comicPage.exactMatch(path)) - { - PageController().service(request,response); + //listar el contenido del folder + if(folder.exactMatch(path)) + { + FolderController().service(request, response); + } + else if (folderInfo.exactMatch(path)) + { + FolderInfoController().service(request, response); + } + else if(cover.exactMatch(path)) + { + CoverController().service(request, response); + } + else if(comic.exactMatch(path)) + { + ComicController().service(request, response); + } + else if(comicPage.exactMatch(path)) + { + PageController().service(request,response); + } } else { + response.writeText(library.cap(1)); Static::staticFileController->service(request, response); } } - else //acceso no autorizado + else //acceso no autorizado, redirección { - ErrorController(403).service(request,response); + ErrorController(300).service(request,response); } } diff --git a/YACReaderLibrary/server/server.pri b/YACReaderLibrary/server/server.pri index 4330dbe5..dc1f2466 100644 --- a/YACReaderLibrary/server/server.pri +++ b/YACReaderLibrary/server/server.pri @@ -5,11 +5,6 @@ HEADERS += \ $$PWD/static.h \ $$PWD/startup.h \ $$PWD/requestmapper.h \ - $$PWD/controllers/dumpcontroller.h \ - $$PWD/controllers/templatecontroller.h \ - $$PWD/controllers/formcontroller.h \ - $$PWD/controllers/fileuploadcontroller.h \ - $$PWD/controllers/sessioncontroller.h \ $$PWD/controllers/comiccontroller.h \ $$PWD/controllers/errorcontroller.h \ $$PWD/controllers/foldercontroller.h \ @@ -23,11 +18,6 @@ SOURCES += \ $$PWD/static.cpp \ $$PWD/startup.cpp \ $$PWD/requestmapper.cpp \ - $$PWD/controllers/dumpcontroller.cpp \ - $$PWD/controllers/templatecontroller.cpp \ - $$PWD/controllers/formcontroller.cpp \ - $$PWD/controllers/fileuploadcontroller.cpp \ - $$PWD/controllers/sessioncontroller.cpp \ $$PWD/controllers/comiccontroller.cpp \ $$PWD/controllers/errorcontroller.cpp \ $$PWD/controllers/foldercontroller.cpp \ diff --git a/common/comic_flow_widget.cpp b/common/comic_flow_widget.cpp new file mode 100644 index 00000000..dc944215 --- /dev/null +++ b/common/comic_flow_widget.cpp @@ -0,0 +1,228 @@ +#include "comic_flow_widget.h" + +ComicFlowWidget::ComicFlowWidget(QWidget * parent) + :QWidget(parent) +{ + +} + +ComicFlowWidgetSW::ComicFlowWidgetSW(QWidget * parent) + :ComicFlowWidget(parent) +{ + flow = new ComicFlow(parent); + + connect(flow,SIGNAL(centerIndexChanged(int)),this,SIGNAL(centerIndexChanged(int))); + connect(flow,SIGNAL(selected(unsigned int)),this,SIGNAL(selected(unsigned int))); + + QVBoxLayout * l = new QVBoxLayout; + l->addWidget(flow); + setLayout(l); + + //TODO eleminar "padding" + QPalette Pal(palette()); + // set black background + Pal.setColor(QPalette::Background, Qt::black); + setAutoFillBackground(true); + setPalette(Pal); +} + +QSize ComicFlowWidgetSW::minimumSizeHint() const +{ + return flow->minimumSizeHint(); +} +QSize ComicFlowWidgetSW::sizeHint() const +{ + return flow->sizeHint(); +} + +void ComicFlowWidgetSW::setShowMarks(bool value) +{ + flow->setShowMarks(value); +} +void ComicFlowWidgetSW::setMarks(QVector marks) +{ + flow->setMarks(marks); +} +void ComicFlowWidgetSW::setMarkImage(QImage & image) +{ + flow->setMarkImage(image); +} +void ComicFlowWidgetSW::markSlide(int index) +{ + flow->markSlide(index); +} +void ComicFlowWidgetSW::unmarkSlide(int index) +{ + flow->unmarkSlide(index); +} +void ComicFlowWidgetSW::setSlideSize(QSize size) +{ + flow->setSlideSize(size); +} +void ComicFlowWidgetSW::clear() +{ + flow->clear(); +} +void ComicFlowWidgetSW::setImagePaths(QStringList paths) +{ + flow->setImagePaths(paths); +} +void ComicFlowWidgetSW::setCenterIndex(int index) +{ + flow->setCenterIndex(index); +} +void ComicFlowWidgetSW::showSlide(int index) +{ + flow->showSlide(index); +} +int ComicFlowWidgetSW::centerIndex() +{ + return flow->centerIndex(); +} +void ComicFlowWidgetSW::updateMarks() +{ + flow->updateMarks(); +} +void ComicFlowWidgetSW::setFlowType(PictureFlow::FlowType flowType) +{ + flow->setFlowType(flowType); +} +void ComicFlowWidgetSW::render() +{ + flow->render(); +} +void ComicFlowWidgetSW::keyPressEvent(QKeyEvent* event) +{ + flow->keyPressEvent(event); +} +void ComicFlowWidgetSW::paintEvent(QPaintEvent *event) +{ + flow->paintEvent(event); +} +void ComicFlowWidgetSW::mousePressEvent(QMouseEvent* event) +{ + flow->mousePressEvent(event); +} +void ComicFlowWidgetSW::resizeEvent(QResizeEvent* event) +{ + flow->resizeEvent(event); +} +void ComicFlowWidgetSW::mouseDoubleClickEvent(QMouseEvent* event) +{ + flow->mouseDoubleClickEvent(event); +} + + + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +///OpenGL ComicFlow +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +ComicFlowWidgetGL::ComicFlowWidgetGL(QWidget * parent) + :ComicFlowWidget(parent) +{ + flow = new YACReaderFlowGL(parent); + + connect(flow,SIGNAL(centerIndexChanged(int)),this,SIGNAL(centerIndexChanged(int))); + connect(flow,SIGNAL(selected(unsigned int)),this,SIGNAL(selected(unsigned int))); + + QVBoxLayout * l = new QVBoxLayout; + l->addWidget(flow); + setLayout(l); + + //TODO eleminar "padding" + QPalette Pal(palette()); + // set black background + Pal.setColor(QPalette::Background, Qt::black); + setAutoFillBackground(true); + setPalette(Pal); +} + +QSize ComicFlowWidgetGL::minimumSizeHint() const +{ + return flow->minimumSizeHint(); +} +QSize ComicFlowWidgetGL::sizeHint() const +{ + return flow->sizeHint(); +} + +void ComicFlowWidgetGL::setShowMarks(bool value) +{ + flow->setShowMarks(value); +} +void ComicFlowWidgetGL::setMarks(QVector marks) +{ + flow->setMarks(marks); +} +void ComicFlowWidgetGL::setMarkImage(QImage & image) +{ + flow->setMarkImage(image); +} +void ComicFlowWidgetGL::markSlide(int index) +{ + flow->markSlide(index); +} +void ComicFlowWidgetGL::unmarkSlide(int index) +{ + flow->unmarkSlide(index); +} +void ComicFlowWidgetGL::setSlideSize(QSize size) +{ + flow->setSlideSize(size); +} +void ComicFlowWidgetGL::clear() +{ + flow->clear(); +} +void ComicFlowWidgetGL::setImagePaths(QStringList paths) +{ + flow->setImagePaths(paths); +} +void ComicFlowWidgetGL::setCenterIndex(int index) +{ + flow->setCenterIndex(index); +} +void ComicFlowWidgetGL::showSlide(int index) +{ + flow->showSlide(index); +} +int ComicFlowWidgetGL::centerIndex() +{ + return flow->centerIndex(); +} +void ComicFlowWidgetGL::updateMarks() +{ + flow->updateMarks(); +} +void ComicFlowWidgetGL::setFlowType(PictureFlow::FlowType flowType) +{ + flow->setFlowType(flowType); +} +void ComicFlowWidgetGL::render() +{ + flow->render(); +} +void ComicFlowWidgetGL::keyPressEvent(QKeyEvent* event) +{ + flow->keyPressEvent(event); +} +void ComicFlowWidgetGL::paintEvent(QPaintEvent *event) +{ + //flow->paintEvent(event); +} +void ComicFlowWidgetGL::mousePressEvent(QMouseEvent* event) +{ + flow->mousePressEvent(event); +} +void ComicFlowWidgetGL::resizeEvent(QResizeEvent* event) +{ + flow->resizeGL(event->size().width(),event->size().height()); +} +void ComicFlowWidgetGL::mouseDoubleClickEvent(QMouseEvent* event) +{ + flow->mouseDoubleClickEvent(event); +} \ No newline at end of file diff --git a/common/comic_flow_widget.h b/common/comic_flow_widget.h new file mode 100644 index 00000000..832059f3 --- /dev/null +++ b/common/comic_flow_widget.h @@ -0,0 +1,98 @@ +#pragma once + +#include + +#include "pictureflow.h" +#include "comic_flow.h" +#include "yacreader_flow_gl.h" + +class ComicFlowWidget : public QWidget +{ + Q_OBJECT +public: + ComicFlowWidget(QWidget * paret = 0); + +public slots: + virtual void setShowMarks(bool value) = 0; + virtual void setMarks(QVector marks) = 0; + virtual void setMarkImage(QImage & image) = 0; + virtual void markSlide(int index) = 0; + virtual void unmarkSlide(int index) = 0; + virtual void setSlideSize(QSize size) = 0; + virtual void clear() = 0; + virtual void setImagePaths(QStringList paths) = 0; + virtual void setCenterIndex(int index) = 0; + virtual void showSlide(int index) = 0; + virtual int centerIndex() = 0; + virtual void updateMarks() = 0; + virtual void setFlowType(PictureFlow::FlowType flowType) = 0; + virtual void render() = 0; +signals: + void centerIndexChanged(int); + void selected(unsigned int); +}; + + +class ComicFlowWidgetSW : public ComicFlowWidget +{ + Q_OBJECT +private: + ComicFlow * flow; +public: + ComicFlowWidgetSW(QWidget * parent = 0); + + void setShowMarks(bool value); + void setMarks(QVector marks); + void setMarkImage(QImage & image); + void markSlide(int index); + void unmarkSlide(int index); + void setSlideSize(QSize size); + void clear(); + void setImagePaths(QStringList paths); + void setCenterIndex(int index); + void showSlide(int index); + int centerIndex(); + void updateMarks(); + void setFlowType(PictureFlow::FlowType flowType); + void render(); +protected: + void keyPressEvent(QKeyEvent* event); + void paintEvent(QPaintEvent *event); + void mousePressEvent(QMouseEvent* event); + void resizeEvent(QResizeEvent* event); + void mouseDoubleClickEvent(QMouseEvent* event); + QSize minimumSizeHint() const; + QSize sizeHint() const; +}; + +class ComicFlowWidgetGL : public ComicFlowWidget +{ + Q_OBJECT +private: + YACReaderFlowGL * flow; +public: + ComicFlowWidgetGL(QWidget * parent = 0); + + void setShowMarks(bool value); + void setMarks(QVector marks); + void setMarkImage(QImage & image); + void markSlide(int index); + void unmarkSlide(int index); + void setSlideSize(QSize size); + void clear(); + void setImagePaths(QStringList paths); + void setCenterIndex(int index); + void showSlide(int index); + int centerIndex(); + void updateMarks(); + void setFlowType(PictureFlow::FlowType flowType); + void render(); +protected: + void keyPressEvent(QKeyEvent* event); + void paintEvent(QPaintEvent *event); + void mousePressEvent(QMouseEvent* event); + void resizeEvent(QResizeEvent* event); + void mouseDoubleClickEvent(QMouseEvent* event); + QSize minimumSizeHint() const; + QSize sizeHint() const; +}; \ No newline at end of file diff --git a/common/custom_widgets.h b/common/custom_widgets.h index 5d06566f..d2e0d75a 100644 --- a/common/custom_widgets.h +++ b/common/custom_widgets.h @@ -66,7 +66,7 @@ class YACReaderFlow : public PictureFlow Q_OBJECT public: YACReaderFlow(QWidget * parent,FlowType flowType = CoverFlowLike); -protected: + void mousePressEvent(QMouseEvent* event); void mouseDoubleClickEvent(QMouseEvent* event); diff --git a/common/pictureflow.h b/common/pictureflow.h index abe80073..8e7b6664 100644 --- a/common/pictureflow.h +++ b/common/pictureflow.h @@ -204,7 +204,7 @@ public slots: signals: void centerIndexChanged(int index); -protected: +public: void paintEvent(QPaintEvent *event); void keyPressEvent(QKeyEvent* event); void mousePressEvent(QMouseEvent* event); diff --git a/common/yacreader_flow_gl.cpp b/common/yacreader_flow_gl.cpp new file mode 100644 index 00000000..6b7c8c61 --- /dev/null +++ b/common/yacreader_flow_gl.cpp @@ -0,0 +1,1095 @@ +#include "yacreader_flow_gl.h" + +#include +#include +#include +#include +#include +#include + +/*** Animation Settings ***/ + +/*** Position Configuration ***/ + +struct Preset defaultYACReaderFlowConfig = { + 0.08, //Animation_step sets the speed of the animation + 1.5, //Animation_speedup sets the acceleration of the animation + 0.1, //Animation_step_max sets the maximum speed of the animation + 3, //Animation_Fade_out_dis sets the distance of view + + 1.5, //pre_rotation sets the rotation increasion + 3, //View_rotate_light_strenght sets the light strenght on rotation + 0.01, //View_rotate_add sets the speed of the rotation + 0.02, //View_rotate_sub sets the speed of reversing the rotation + 20, //View_angle sets the maximum view angle + + 0, //CF_X the X Position of the Coverflow + 0, //CF_Y the Y Position of the Coverflow + -10, //CF_Z the Z Position of the Coverflow + + 15, //CF_RX the X Rotation of the Coverflow + 0, //CF_RY the Y Rotation of the Coverflow + 0, //CF_RZ the Z Rotation of the Coverflow + + -50, //Rotation sets the rotation of each cover + 0.18, //X_Distance sets the distance between the covers + 1, //Center_Distance sets the distance between the centered and the non centered covers + 0.1, //Z_Distance sets the pushback amount + 0.0 //Y_Distance sets the elevation amount + +}; + +struct Preset presetYACReaderFlowClassicConfig = { + 0.08, //Animation_step sets the speed of the animation + 1.5, //Animation_speedup sets the acceleration of the animation + 0.1, //Animation_step_max sets the maximum speed of the animation + 2, //Animation_Fade_out_dis sets the distance of view + + 1.5, //pre_rotation sets the rotation increasion + 3, //View_rotate_light_strenght sets the light strenght on rotation + 0.08, //View_rotate_add sets the speed of the rotation + 0.08, //View_rotate_sub sets the speed of reversing the rotation + 30, //View_angle sets the maximum view angle + + 0, //CF_X the X Position of the Coverflow + -0.2, //CF_Y the Y Position of the Coverflow + -7, //CF_Z the Z Position of the Coverflow + + 0, //CF_RX the X Rotation of the Coverflow + 0, //CF_RY the Y Rotation of the Coverflow + 0, //CF_RZ the Z Rotation of the Coverflow + + -40, //Rotation sets the rotation of each cover + 0.18, //X_Distance sets the distance between the covers + 1, //Center_Distance sets the distance between the centered and the non centered covers + 0.1, //Z_Distance sets the pushback amount + 0.0 //Y_Distance sets the elevation amount + +}; + +struct Preset presetYACReaderFlowStripeConfig = { + 0.08, //Animation_step sets the speed of the animation + 1.5, //Animation_speedup sets the acceleration of the animation + 0.1, //Animation_step_max sets the maximum speed of the animation + 6, //Animation_Fade_out_dis sets the distance of view + + 1.5, //pre_rotation sets the rotation increasion + 4, //View_rotate_light_strenght sets the light strenght on rotation + 0.08, //View_rotate_add sets the speed of the rotation + 0.08, //View_rotate_sub sets the speed of reversing the rotation + 30, //View_angle sets the maximum view angle + + 0, //CF_X the X Position of the Coverflow + -0.2, //CF_Y the Y Position of the Coverflow + -7, //CF_Z the Z Position of the Coverflow + + 0, //CF_RX the X Rotation of the Coverflow + 0, //CF_RY the Y Rotation of the Coverflow + 0, //CF_RZ the Z Rotation of the Coverflow + + 0, //Rotation sets the rotation of each cover + 1.1, //X_Distance sets the distance between the covers + 0.2, //Center_Distance sets the distance between the centered and the non centered covers + 0.01, //Z_Distance sets the pushback amount + 0.0 //Y_Distance sets the elevation amount + +}; + +struct Preset presetYACReaderFlowOverlappedStripeConfig = { + 0.08, //Animation_step sets the speed of the animation + 1.5, //Animation_speedup sets the acceleration of the animation + 0.1, //Animation_step_max sets the maximum speed of the animation + 2, //Animation_Fade_out_dis sets the distance of view + + 1.5, //pre_rotation sets the rotation increasion + 3, //View_rotate_light_strenght sets the light strenght on rotation + 0.08, //View_rotate_add sets the speed of the rotation + 0.08, //View_rotate_sub sets the speed of reversing the rotation + 30, //View_angle sets the maximum view angle + + 0, //CF_X the X Position of the Coverflow + -0.2, //CF_Y the Y Position of the Coverflow + -7, //CF_Z the Z Position of the Coverflow + + 0, //CF_RX the X Rotation of the Coverflow + 0, //CF_RY the Y Rotation of the Coverflow + 0, //CF_RZ the Z Rotation of the Coverflow + + 0, //Rotation sets the rotation of each cover + 0.18, //X_Distance sets the distance between the covers + 1, //Center_Distance sets the distance between the centered and the non centered covers + 0.1, //Z_Distance sets the pushback amount + 0.0 //Y_Distance sets the elevation amount + +}; + +struct Preset pressetYACReaderFlowUpConfig = { + 0.08, //Animation_step sets the speed of the animation + 1.5, //Animation_speedup sets the acceleration of the animation + 0.1, //Animation_step_max sets the maximum speed of the animation + 2.5, //Animation_Fade_out_dis sets the distance of view + + 1.5, //pre_rotation sets the rotation increasion + 3, //View_rotate_light_strenght sets the light strenght on rotation + 0.08, //View_rotate_add sets the speed of the rotation + 0.08, //View_rotate_sub sets the speed of reversing the rotation + 30, //View_angle sets the maximum view angle + + 0, //CF_X the X Position of the Coverflow + -0.2, //CF_Y the Y Position of the Coverflow + -7, //CF_Z the Z Position of the Coverflow + + 0, //CF_RX the X Rotation of the Coverflow + 0, //CF_RY the Y Rotation of the Coverflow + 0, //CF_RZ the Z Rotation of the Coverflow + + -50, //Rotation sets the rotation of each cover + 0.18, //X_Distance sets the distance between the covers + 1, //Center_Distance sets the distance between the centered and the non centered covers + 0.1, //Z_Distance sets the pushback amount + -0.1 //Y_Distance sets the elevation amount + +}; + +struct Preset pressetYACReaderFlowDownConfig = { + 0.08, //Animation_step sets the speed of the animation + 1.5, //Animation_speedup sets the acceleration of the animation + 0.1, //Animation_step_max sets the maximum speed of the animation + 2.5, //Animation_Fade_out_dis sets the distance of view + + 1.5, //pre_rotation sets the rotation increasion + 3, //View_rotate_light_strenght sets the light strenght on rotation + 0.08, //View_rotate_add sets the speed of the rotation + 0.08, //View_rotate_sub sets the speed of reversing the rotation + 30, //View_angle sets the maximum view angle + + 0, //CF_X the X Position of the Coverflow + -0.2, //CF_Y the Y Position of the Coverflow + -7, //CF_Z the Z Position of the Coverflow + + 0, //CF_RX the X Rotation of the Coverflow + 0, //CF_RY the Y Rotation of the Coverflow + 0, //CF_RZ the Z Rotation of the Coverflow + + -50, //Rotation sets the rotation of each cover + 0.18, //X_Distance sets the distance between the covers + 1, //Center_Distance sets the distance between the centered and the non centered covers + 0.1, //Z_Distance sets the pushback amount + 0.1 //Y_Distance sets the elevation amount +}; +/*Constructor*/ +YACReaderFlowGL::YACReaderFlowGL(QWidget *parent,struct Preset p) + :QGLWidget(QGLFormat(QGL::DoubleBuffer), parent),numObjects(0) +{ + updateCount = 0; + config = p; + + currentSelected = 0; + + centerPos.x = 0; + centerPos.y = 0; + centerPos.z = 1; + centerPos.rot = 0; + + /*** Style ***/ + shadingTop = 0.8; + shadingBottom = 0.02; + reflectionUp = 0; + reflectionBottom = 0.6; + + /*** System variables ***/ + numObjects = 0; + CFImage Dummy; + viewRotate = 0; + viewRotateActive = 0; + stepBackup = config.animationStep/config.animationSpeedUp; + + worker = new ImageLoaderGL(this); + worker->flow = this; + + /*QTimer * timer = new QTimer(); + connect(timer, SIGNAL(timeout()), this, SLOT(updateImageData())); + timer->start(70); + */ + + /*loader = new WidgetLoader(0,this); + loader->flow = this; + QThread * loaderThread = new QThread(parent); + + loader->moveToThread(loaderThread); + + loaderThread->start();*/ + timerId = startTimer(16); +} + +void YACReaderFlowGL::timerEvent(QTimerEvent * event) +{ + if(timerId == event->timerId()) + update(); + + //if(!worker->isRunning()) + //worker->start(); +} + +YACReaderFlowGL::~YACReaderFlowGL() +{ + +} + +QSize YACReaderFlowGL::minimumSizeHint() const +{ + return QSize(800, 480); +} + +QSize YACReaderFlowGL::sizeHint() const +{ + return QSize(800, 480); +} + +void YACReaderFlowGL::initializeGL() +{ + glEnable(GL_DEPTH_TEST); + glEnable(GL_COLOR_MATERIAL); + glShadeModel(GL_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + //populate(284); //TODO esto es responsabilidad del usuario de la clase + + //float x = 0.5; + //int i; + //int n = 20; + //for(i = 0;iInsert("cover", cover, x, y); + //} + +} + +void YACReaderFlowGL::paintGL() +{ + /*glClearDepth(1.0); + glClearColor(1,1,1,1);*/ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + /*glLoadIdentity(); + glTranslatef(0.0, 0.0, -10.0); + glPopMatrix();*/ + if(numObjects>0) + { + updatePositions(); + draw(); + } +} + +void YACReaderFlowGL::resizeGL(int width, int height) +{ + + fontSize = width * 0.02; + + //int side = qMin(width, height); + glViewport(0, 0, width, height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); +#ifdef QT_OPENGL_ES_1 + //glOrthof(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0); +#else + float sideX = ((float(width)/height)/2)*1.5; + float sideY = 0.5*1.5; + gluPerspective(20.0, (float)width / (float)height, 1.0, 200.0); + //glOrtho(-sideX, sideX, -sideY+0.2, +sideY+0.2, 4, 11.0); + +#endif + glMatrixMode(GL_MODELVIEW); + + updatePositions(); +} + +//----------------------------------------------------------------------------- +/*Private*/ +void YACReaderFlowGL::calcPos(CFImage *CF,int pos) +{ + if(pos == 0){ + CF->current = centerPos; + }else{ + if(pos > 0){ + CF->current.x = (config.centerDistance)+(config.xDistance*pos); + CF->current.y = config.yDistance*pos*-1; + CF->current.z = config.zDistance*pos*-1; + CF->current.rot = config.rotation; + }else{ + CF->current.x = (config.centerDistance)*-1+(config.xDistance*pos); + CF->current.y = config.yDistance*pos; + CF->current.z = config.zDistance*pos; + CF->current.rot = config.rotation*-1; + } + } + +} +void YACReaderFlowGL::calcRV(RVect *RV,int pos) +{ + calcPos(&dummy,pos); + + RV->x = dummy.current.x; + RV->y = dummy.current.y; + RV->z = dummy.current.z; + RV->rot = dummy.current.rot; + +} +void YACReaderFlowGL::animate(RVect *Current,RVect to) +{ + //calculate and apply positions + Current->x = Current->x+(to.x-Current->x)*config.animationStep; + Current->y = Current->y+(to.y-Current->y)*config.animationStep; + Current->z = Current->z+(to.z-Current->z)*config.animationStep; + + if(abs(to.rot-Current->rot) > 0.01){ + Current->rot = Current->rot+(to.rot-Current->rot)*(config.animationStep*config.preRotation); + } + else + viewRotateActive = 0; + +} +void YACReaderFlowGL::drawCover(CFImage *CF) +{ + float w = CF->width; + float h = CF->height; + + //fadeout + float opacity = 1-1/(config.animationFadeOutDist+config.viewRotateLightStrenght*abs(viewRotate))*abs(0-CF->current.x); + + glLoadIdentity(); + glTranslatef(config.cfX,config.cfY,config.cfZ); + glRotatef(config.cfRX,1,0,0); + glRotatef(viewRotate*config.viewAngle+config.cfRY,0,1,0); + glRotatef(config.cfRZ,0,0,1); + + glTranslatef( CF->current.x, CF->current.y, CF->current.z ); + + glPushMatrix(); + glRotatef(CF->current.rot,0,1,0); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, CF->img); + + //calculate shading + float LShading = ((config.rotation != 0 )?((CF->current.rot < 0)?1-1/config.rotation*CF->current.rot:1):1); + float RShading = ((config.rotation != 0 )?((CF->current.rot > 0)?1-1/(config.rotation*-1)*CF->current.rot:1):1); + float LUP = shadingTop+(1-shadingTop)*LShading; + float LDOWN = shadingBottom+(1-shadingBottom)*LShading; + float RUP = shadingTop+(1-shadingTop)*RShading; + float RDOWN = shadingBottom+(1-shadingBottom)*RShading;; + + + //DrawCover + glBegin(GL_QUADS); + + //esquina inferior izquierda + glColor4f(LDOWN*opacity,LDOWN*opacity,LDOWN*opacity,1); + glTexCoord2f(0.0f, 1.0f); + glVertex3f(w/2*-1, -0.5, 0); + + //esquina inferior derecha + glColor4f(RDOWN*opacity,RDOWN*opacity,RDOWN*opacity,1); + glTexCoord2f(1.0f, 1.0f); + glVertex3f(w/2, -0.5, 0); + + //esquina superior derecha + glColor4f(RUP*opacity,RUP*opacity,RUP*opacity,1); + glTexCoord2f(1.0f, 0.0f); + glVertex3f(w/2, -0.5+h, 0); + + //esquina superior izquierda + glColor4f(LUP*opacity,LUP*opacity,LUP*opacity,1); + glTexCoord2f(0.0f, 0.0f); + glVertex3f(w/2*-1, -0.5+h, 0); + + glEnd(); + + + + //Draw reflection + glBegin(GL_QUADS); + + //esquina inferior izquierda + glColor4f(LUP*opacity*reflectionUp,LUP*opacity*reflectionUp,LUP*opacity*reflectionUp,opacity*reflectionUp); + glTexCoord2f(0.0f, 0.0f); + glVertex3f(w/2*-1, -0.5-h, 0); + + //esquina inferior derecha + glTexCoord2f(1.0f, 0.0f); + glVertex3f(w/2, -0.5-h, 0); + + //esquina superior derecha + glColor4f(opacity*reflectionBottom,opacity*reflectionBottom,opacity*reflectionBottom,opacity*reflectionBottom); + glTexCoord2f(1.0f, 1.0f); + glVertex3f(w/2, -0.5, 0); + + //esquina superior izquierda + glTexCoord2f(0.0f, 1.0f); + glVertex3f(w/2*-1, -0.5, 0); + + glEnd(); + glDisable(GL_TEXTURE_2D); + + if(loaded[CF->index] && marks[CF->index]) + { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, markTexture); + glBegin(GL_QUADS); + + //esquina inferior izquierda + glColor4f(LDOWN*opacity,LDOWN*opacity,LDOWN*opacity,1); + glTexCoord2f(0.0f, 1.0f); + glVertex3f(w/2-0.2, -0.5, 0.0001); + + //esquina inferior derecha + glColor4f(RDOWN*opacity,RDOWN*opacity,RDOWN*opacity,1); + glTexCoord2f(1.0f, 1.0f); + glVertex3f(w/2, -0.5, 0.0001); + + //esquina superior derecha + glColor4f(RUP*opacity,RUP*opacity,RUP*opacity,1); + glTexCoord2f(1.0f, 0.0f); + glVertex3f(w/2, -0.3, 0.0001); + + //esquina superior izquierda + glColor4f(LUP*opacity,LUP*opacity,LUP*opacity,1); + glTexCoord2f(0.0f, 0.0f); + glVertex3f(w/2-0.2, -0.3, 0.0001); + + glEnd(); + glDisable(GL_TEXTURE_2D); + } + + + glPopMatrix(); +} + +/*Public*/ +void YACReaderFlowGL::cleanupAnimation() +{ + config.animationStep = stepBackup; + viewRotateActive = 0; +} + +void YACReaderFlowGL::draw() +{ + int CS = currentSelected; + int count; + + + //Draw right Covers + for(count = numObjects-1;count > -1;count--){ + if(count > CS){ + drawCover(&cfImages[count]); + } + } + + //Draw left Covers + for(count = 0;count < numObjects-1;count++){ + if(count < CS){ + drawCover(&cfImages[count]); + } + } + + //Draw Center Cover + drawCover(&cfImages[CS]); + + //glDisable(GL_DEPTH_TEST); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(-(float(width())/height())/2.0,(float(width())/height())/2.0, 0, 1, -10, 10); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + + glBegin( GL_TRIANGLES ); + + glColor4f( 1.0, 1.0, 1.0, 1.0 ); + glVertex2f( -0.03, 0.98); + glVertex2f( 0.03, 0.98); + glVertex2f( 0, 0.95); + + glEnd(); + + renderText(10, fontSize + 10,QString("%1/%2").arg(currentSelected+1).arg(numObjects),QFont("Arial", fontSize)); + + glEnable(GL_DEPTH_TEST); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + +} + +void YACReaderFlowGL::showPrevious() +{ + if(currentSelected > 0){ + + currentSelected--; + emit centerIndexChanged(currentSelected); + config.animationStep *= config.animationSpeedUp; + + if(config.animationStep > config.animationStepMax){ + config.animationStep = config.animationStepMax; + } + + if(viewRotateActive && viewRotate > -1){ + viewRotate -= config.viewRotateAdd; + } + + viewRotateActive = 1; + + } +} + +void YACReaderFlowGL::showNext() +{ + if(currentSelected < numObjects-1){ + + currentSelected++; + emit centerIndexChanged(currentSelected); + config.animationStep *= config.animationSpeedUp; + + if(config.animationStep > config.animationStepMax){ + config.animationStep = config.animationStepMax; + } + + if(viewRotateActive && viewRotate < 1){ + viewRotate += config.viewRotateAdd; + } + + viewRotateActive = 1; + } +} + +void YACReaderFlowGL::setCurrentIndex(int pos) +{ + currentSelected = pos; + + config.animationStep *= config.animationSpeedUp; + + if(config.animationStep > config.animationStepMax){ + config.animationStep = config.animationStepMax; + } + + if(viewRotateActive && viewRotate < 1){ + viewRotate += config.viewRotateAdd; + } + + viewRotateActive = 1; +} + +void YACReaderFlowGL::updatePositions() +{ + int count; + + for(count = numObjects-1;count > -1;count--){ + calcRV(&cfImages[count].animEnd,count-currentSelected); + animate(&cfImages[count].current,cfImages[count].animEnd); + } + + //slowly reset view angle + if(!viewRotateActive){ + viewRotate += (0-viewRotate)*config.viewRotateSub; + } + if(viewRotate < 0.2) + { + if(updateCount >= 0) //TODO parametrizar + { + + updateCount = 0; + updateImageData(); + } + else + updateCount++; + } + else + updateCount++; + +} + +void YACReaderFlowGL::insert(char *name, GLuint Tex, float x, float y,int item) +{ + //set a new entry + if(item == -1){ + + if(numObjects == 0){ + cfImages = (CFImage*)malloc(sizeof(CFImage)); + } + else + { + cfImages = (CFImage*)realloc(cfImages,(numObjects+1)*sizeof(CFImage)); + } + + item = numObjects; + numObjects++; + + calcRV(&cfImages[item].current,item); + cfImages[item].current.x += 1; + cfImages[item].current.rot = 90; + } + + cfImages[item].img = Tex; + cfImages[item].width = x; + cfImages[item].height = y; + cfImages[item].index = item; + strcpy(cfImages[item].name,name); +} + +void YACReaderFlowGL::remove(int item) +{ + //reposition current selection + if(item == currentSelected && currentSelected != 0){ + currentSelected--; + } + + int count = item; + while(count <= numObjects-2){ + cfImages[count] = cfImages[count+1]; + count++; + } + numObjects--; + cfImages = (CFImage*)realloc(cfImages,numObjects*sizeof(CFImage)); +} + +/*Info*/ +CFImage YACReaderFlowGL::getCurrentSelected() +{ + return cfImages[currentSelected]; +} + +void YACReaderFlowGL::replace(char *name, GLuint Tex, float x, float y,int item) +{ + cfImages[item].img = Tex; + cfImages[item].width = x; + cfImages[item].height = y; + strcpy(cfImages[item].name,name); + loaded[item]=true; +} + +void YACReaderFlowGL::populate(int n) +{ + float x = 1; + float y = 1 * (700/480.0); + int i; + GLuint cover = bindTexture(QImage(":/images/notCover.png"),GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption); + markTexture = bindTexture(QImage(":/images/setRead.png"),GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption); + for(i = 0;i(n,false); + marks = QVector(n,false); + + emit centerIndexChanged(0); + + //worker->start(); +} + +void YACReaderFlowGL::reset() //TODO unbind textures +{ + loaded.clear(); + for(int i = 0;i0) + delete[] cfImages; + numObjects = 0; + currentSelected = 0; +} + +//slots +void YACReaderFlowGL::setCF_RX(int value) +{ + config.cfRX = value; +} +void YACReaderFlowGL::setCF_RY(int value) +{ + config.cfRY = value; +} +void YACReaderFlowGL::setCF_RZ(int value) +{ + config.cfRZ = value; +} + +void YACReaderFlowGL::setZoom(int zoom) +{ + + int width = this->width(); + int height = this->height(); + glViewport(0, 0, width, height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + float sideX = ((float(width)/height)/2)*1.5; + float sideY = 0.5*1.5; + gluPerspective(zoom, (float)width / (float)height, 1.0, 200.0); + //glOrtho(-sideX, sideX, -sideY+0.2, +sideY+0.2, 4, 11.0); + + glMatrixMode(GL_MODELVIEW); + +} + +void YACReaderFlowGL::setRotation(int angle) +{ + config.rotation = -angle; +} +//sets the distance between the covers +void YACReaderFlowGL::setX_Distance(int distance) +{ + config.xDistance = distance/100.0; +} +//sets the distance between the centered and the non centered covers +void YACReaderFlowGL::setCenter_Distance(int distance) +{ + config.centerDistance = distance/100.0; +} +//sets the pushback amount +void YACReaderFlowGL::setZ_Distance(int distance) +{ + config.zDistance = distance/100.0; +} + +void YACReaderFlowGL::setCF_Y(int value) +{ + config.cfY = value/100.0; +} + +void YACReaderFlowGL::setY_Distance(int value) +{ + config.yDistance = value / 100.0; +} +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +void YACReaderFlowGL::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(!loaded[idx]) + { + float x = 1; + QImage img = worker->result(); + GLuint cover = bindTexture(img, GL_TEXTURE_2D,GL_RGB,QGLContext::LinearFilteringBindOption); + float y = 1 * (float(img.height())/img.width()); + replace("cover", cover, x, y,idx); + /*CFImages[idx].width = x; + CFImages[idx].height = y; + CFImages[idx].img = worker->resultTexture; + strcpy(CFImages[idx].name,"cover");*/ + loaded[idx] = true; + //numImagesLoaded++; + } + } + + // 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 = currentSelected; + 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 < numObjects)) + if(!loaded[i])//slide(i).isNull()) + { + //loader->loadTexture(i); + //loaded[i]=true; + // schedule thumbnail generation + if(paths.size()>0) + { + QString fname = paths.at(i); + //loaded[i]=true; + + worker->generate(i, fname); + } + return; + } + } +} + +void YACReaderFlowGL::setPreset(const Preset & p) +{ + config = p; +} + +void YACReaderFlowGL::setShowMarks(bool value) +{ + showMarks = value; +} +void YACReaderFlowGL::setMarks(QVector marks) +{ + this->marks = marks; +} +void YACReaderFlowGL::setMarkImage(QImage & image) +{ + //qué pasa la primera vez?? + //deleteTexture(markTexture); + //markTexture = bindTexture(image,GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption); +} +void YACReaderFlowGL::markSlide(int index) +{ + marks[index] = true; +} +void YACReaderFlowGL::unmarkSlide(int index) +{ + marks[index] = false; +} +void YACReaderFlowGL::setSlideSize(QSize size) +{ + //TODO calcular el tamaño del widget +} +void YACReaderFlowGL::clear() +{ + reset(); +} +void YACReaderFlowGL::setImagePaths(QStringList paths) +{ + worker->reset(); + reset(); + numObjects = 0; + populate(paths.size()); + this->paths = paths; + numObjects = paths.size(); +} +void YACReaderFlowGL::setCenterIndex(int index) +{ + setCurrentIndex(index); +} +void YACReaderFlowGL::showSlide(int index) +{ + setCurrentIndex(index); +} +int YACReaderFlowGL::centerIndex() +{ + return currentSelected; +} +void YACReaderFlowGL::updateMarks() +{ + //do nothing +} +void YACReaderFlowGL::setFlowType(PictureFlow::FlowType flowType) +{ + //TODO esperar a que se reimplemente flowtype +} +void YACReaderFlowGL::render() +{ + //do nothing +} + +//EVENTOS +void YACReaderFlowGL::wheelEvent(QWheelEvent * event) +{ + if(event->delta()<0) + showNext(); + else + showPrevious(); + event->accept(); +} + +void YACReaderFlowGL::keyPressEvent(QKeyEvent *event) +{ + if(event->key() == Qt::Key_Left) + { + if(event->modifiers() == Qt::ControlModifier) + setCurrentIndex(currentSelected-10); + else + showPrevious(); + event->accept(); + return; + } + + if(event->key() == Qt::Key_Right) + { + if(event->modifiers() == Qt::ControlModifier) + setCurrentIndex(currentSelected+10); + else + showNext(); + event->accept(); + return; + } + + event->ignore(); +} + +void YACReaderFlowGL::mousePressEvent(QMouseEvent *event) +{ + if(event->button() == Qt::LeftButton) + { + float x,y; + x = event->x(); + y = event->y(); + GLint viewport[4]; + GLdouble modelview[16]; + GLdouble projection[16]; + GLfloat winX, winY, winZ; + GLdouble posX, posY, posZ; + + glGetDoublev( GL_MODELVIEW_MATRIX, modelview ); + glGetDoublev( GL_PROJECTION_MATRIX, projection ); + glGetIntegerv( GL_VIEWPORT, viewport ); + + winX = (float)x; + winY = (float)viewport[3] - (float)y; + glReadPixels( x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ ); + + gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ); + + if(posX >= 0) + { + //int index = currentSelected+1; + //while((cfImages[index].current.x-cfImages[index].width/(2.0*config.rotation)) < posX) + // index++; + //setCurrentIndex(index-1); + showNext(); + } + else + showPrevious(); + } else if(event->button() == Qt::RightButton) + { + marks[currentSelected] = !marks[currentSelected]; + } +} + +void YACReaderFlowGL::mouseDoubleClickEvent(QMouseEvent* event) +{ + emit selected(centerIndex()); +} + +//----------------------------------------------------------------------------- +//ImageLoader +//----------------------------------------------------------------------------- +QImage ImageLoaderGL::loadImage(const QString& fileName) +{ + QImage image; + bool result = image.load(fileName); + + //QGLPixelBuffer * pb = new QGLPixelBuffer(image.size(),flow->format(),flow); + //resultTexture = pb->bindTexture(image,GL_TEXTURE_2D); + + //resultTexture = flow->bindTexture(image,GL_TEXTURE_2D); + + //TODO parametrizar + image = image.scaledToWidth(256,Qt::SmoothTransformation); + + + if(!result) + return QImage(); + + return image; +} + +ImageLoaderGL::ImageLoaderGL(YACReaderFlowGL * flow): +QThread(),flow(flow),restart(false), working(false), idx(-1) +{ + +} + +ImageLoaderGL::~ImageLoaderGL() +{ + mutex.lock(); + condition.wakeOne(); + mutex.unlock(); + wait(); +} + +bool ImageLoaderGL::busy() const +{ + return isRunning() ? working : false; +} + +void ImageLoaderGL::generate(int index, const QString& fileName) +{ + mutex.lock(); + this->idx = index; + this->fileName = fileName; + this->size = size; + this->img = QImage(); + mutex.unlock(); + + if (!isRunning()) + start(); + else + { + // already running, wake up whenever ready + restart = true; + condition.wakeOne(); + } +} + +void ImageLoaderGL::run() +{ + for(;;) + { + // copy necessary data + mutex.lock(); + this->working = true; + QString fileName = this->fileName; + mutex.unlock(); + + QImage image = loadImage(fileName); + + // let everyone knows it is ready + mutex.lock(); + this->working = false; + this->img = image; + mutex.unlock(); + + // put to sleep + mutex.lock(); + if (!this->restart) + condition.wait(&mutex); + restart = false; + mutex.unlock(); + } +} + +QImage ImageLoaderGL::result() +{ + return img; +} + +WidgetLoader::WidgetLoader(QWidget *parent, QGLWidget * shared) + :QGLWidget(parent,shared) +{ +} + +void WidgetLoader::loadTexture(int index) +{ + QImage image; + bool result = image.load(QString("./cover%1.jpg").arg(index+1)); + //image = image.scaledToWidth(128,Qt::SmoothTransformation); //TODO parametrizar + flow->cfImages[index].width = 0.5; + flow->cfImages[index].height = 0.5 * (float(image.height())/image.width()); + flow->cfImages[index].img = bindTexture(image, GL_TEXTURE_2D,GL_RGBA,QGLContext::LinearFilteringBindOption | QGLContext::MipmapBindOption); +} \ No newline at end of file diff --git a/common/yacreader_flow_gl.h b/common/yacreader_flow_gl.h new file mode 100644 index 00000000..4757a0eb --- /dev/null +++ b/common/yacreader_flow_gl.h @@ -0,0 +1,300 @@ +//OpenGL Coverflow API by J.Roth + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +#include "pictureflow.h" //TODO mover los tipos de flow de sitio + +class ImageLoaderGL; +class QGLContext; +class WidgetLoader; + +//Cover Vector +typedef struct RVect{ + float x; + float y; + float z; + float rot; +}; + +//the cover info struct +typedef struct CFImage{ + GLuint img; + char name[256]; + + float width; + float height; + + int index; + + RVect current; + RVect animEnd; +}; + +struct Preset{ + /*** Animation Settings ***/ + //sets the speed of the animation + float animationStep; + //sets the acceleration of the animation + float animationSpeedUp; + //sets the maximum speed of the animation + float animationStepMax; + //sets the distance of view + float animationFadeOutDist; + //sets the rotation increasion + float preRotation; + //sets the light strenght on rotation + float viewRotateLightStrenght; + //sets the speed of the rotation + float viewRotateAdd; + //sets the speed of reversing the rotation + float viewRotateSub; + //sets the maximum view angle + float viewAngle; + + /*** Position Configuration ***/ + //the X Position of the Coverflow + float cfX; + //the Y Position of the Coverflow + float cfY; + //the Z Position of the Coverflow + float cfZ; + //the X Rotation of the Coverflow + float cfRX; + //the Y Rotation of the Coverflow + float cfRY; + //the Z Rotation of the Coverflow + float cfRZ; + //sets the rotation of each cover + float rotation; + //sets the distance between the covers + float xDistance; + //sets the distance between the centered and the non centered covers + float centerDistance; + //sets the pushback amount + float zDistance; + //sets the elevation amount + float yDistance; +}; + +extern struct Preset defaultYACReaderFlowConfig; +extern struct Preset presetYACReaderFlowClassicConfig; +extern struct Preset presetYACReaderFlowStripeConfig; +extern struct Preset presetYACReaderFlowOverlappedStripeConfig; +extern struct Preset pressetYACReaderFlowUpConfig; +extern struct Preset pressetYACReaderFlowDownConfig; + +class YACReaderFlowGL : public QGLWidget +{ + Q_OBJECT +private: + int timerId; + /*** System variables ***/ + CFImage dummy; + int viewRotateActive; + float stepBackup; + + GLuint markTexture; + + /*functions*/ + void calcPos(CFImage *CF,int pos); + void calcRV(RVect *RV,int pos); + void animate(RVect *Current,RVect to); + void drawCover(CFImage *CF); + ImageLoaderGL * worker; + int updateCount; + WidgetLoader * loader; + int fontSize; + +protected: + void initializeGL(); + void paintGL(); + void timerEvent(QTimerEvent *); + + +public: + //number of Covers + int numObjects; + bool showMarks; + QVector loaded; + QVector marks; + QList paths; + CFImage * cfImages; + + /*** Animation Settings ***/ + Preset config; + + //sets/returns the curent selected cover + int currentSelected; + + //defines the position of the centered cover + RVect centerPos; + + /*** Style ***/ + //sets the amount of shading of the covers in the back (0-1) + float shadingTop; + float shadingBottom; + + //sets the reflection strenght (0-1) + float reflectionUp; + float reflectionBottom; + + /*** System info ***/ + float viewRotate; + + /*Constructor*/ + YACReaderFlowGL(QWidget *parent = 0,struct Preset p = defaultYACReaderFlowConfig); + ~YACReaderFlowGL(); + + //size; + QSize minimumSizeHint() const; + QSize sizeHint() const; + + /*functions*/ + + //if called it moves the coverflow to the left + void showPrevious(); + //if called it moves the coverflow to the right + void showNext(); + //go to + void setCurrentIndex(int pos); + //must be called whenever the coverflow animation is stopped + void cleanupAnimation(); + //Draws the coverflow + void draw(); + //updates the coverflow + void updatePositions(); + //inserts a new item to the coverflow + //if item is set to a value > -1 it updates a already set value + //otherwise a new entry is set + void insert(char *name, GLuint Tex, float x, float y,int item = -1); + //removes a item + void remove(int item); + //replaces the texture of the item 'item' with Tex + void replace(char *name, GLuint Tex, float x, float y,int item); + //create n covers with the default nu + void populate(int n); + /*Info*/ + //retuns the CFImage Struct of the current selected item + //to read title or textures + CFImage getCurrentSelected(); + + public slots: + void setCF_RX(int value); + //the Y Rotation of the Coverflow + void setCF_RY(int value); + //the Z Rotation of the Coverflow + void setCF_RZ(int value); + + //perspective + void setZoom(int zoom); + + void setRotation(int angle); + //sets the distance between the covers + void setX_Distance(int distance); + //sets the distance between the centered and the non centered covers + void setCenter_Distance(int distance); + //sets the pushback amount + void setZ_Distance(int distance); + + void setCF_Y(int value); + + void setY_Distance(int value); + + void setPreset(const Preset & p); + + void updateImageData(); + + void reset(); + + //interface with yacreaderlibrary, compatibility + void setShowMarks(bool value); + void setMarks(QVector marks); + void setMarkImage(QImage & image); + void markSlide(int index); + void unmarkSlide(int index); + void setSlideSize(QSize size); + void clear(); + void setImagePaths(QStringList paths); + void setCenterIndex(int index); + void showSlide(int index); + int centerIndex(); + void updateMarks(); + void setFlowType(PictureFlow::FlowType flowType); + void render(); + + //void paintEvent(QPaintEvent *event); + void mouseDoubleClickEvent(QMouseEvent* event); + void mousePressEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent * event); + void keyPressEvent(QKeyEvent *event); + void resizeGL(int width, int height); + +signals: + void centerIndexChanged(int); + void selected(unsigned int); +}; + +class WidgetLoader : public QGLWidget +{ + Q_OBJECT +public: + WidgetLoader(QWidget *parent, QGLWidget * shared); + YACReaderFlowGL * flow; +public slots: + void loadTexture(int index); + +}; + +class ImageLoaderGL : public QThread +{ +public: + ImageLoaderGL(YACReaderFlowGL * flow); + ~ImageLoaderGL(); + // returns FALSE if worker is still busy and can't take the task + bool busy() const; + void generate(int index, const QString& fileName); + void reset(){idx = -1;}; + int index() const { return idx; }; + QImage result(); + YACReaderFlowGL * flow; + GLuint resultTexture; + QImage loadImage(const QString& fileName); + +protected: + void run(); + +private: + QMutex mutex; + QWaitCondition condition; + + + bool restart; + bool working; + int idx; + QString fileName; + QSize size; + QImage img; +}; + +//class TextureLoader : public QThread +//{ +//public: +// TextureLoader(); +// ~TextureLoader(); +// // returns FALSE if worker is still busy and can't take the task +// +// YACReaderFlow * flow; +// ImageLoader * worker; +//protected: +// void run(); +// +//}; \ No newline at end of file diff --git a/release/server/templates/folder.tpl b/release/server/templates/folder_ipad.tpl similarity index 87% rename from release/server/templates/folder.tpl rename to release/server/templates/folder_ipad.tpl index 1583568b..e5e2c3aa 100644 --- a/release/server/templates/folder.tpl +++ b/release/server/templates/folder_ipad.tpl @@ -16,7 +16,7 @@
    {loop element} -
  • {element.name}

    {element.browse} - Download
  • +
  • {element.name}

    {element.browse} - {element.download}
  • {end element}
diff --git a/release/server/templates/folder_iphone.tpl b/release/server/templates/folder_iphone.tpl new file mode 100644 index 00000000..a193ad6d --- /dev/null +++ b/release/server/templates/folder_iphone.tpl @@ -0,0 +1,53 @@ + + + + + + Folder + + +
+ +

BROWSE AND IMPORT

+

nombre folder?

+ + Libraries up + + +
    + {loop element} +
  • {element.name}

    {element.browse} - {element.download}
  • + {end element} +
+
+
 
+ +
+ +
 
+
+
 
+ + +
+ +
 
+
+
 
+ + + diff --git a/release/server/templates/libraries-es.tpl b/release/server/templates/libraries_ipad-es.tpl similarity index 100% rename from release/server/templates/libraries-es.tpl rename to release/server/templates/libraries_ipad-es.tpl diff --git a/release/server/templates/libraries.tpl b/release/server/templates/libraries_ipad.tpl similarity index 100% rename from release/server/templates/libraries.tpl rename to release/server/templates/libraries_ipad.tpl diff --git a/release/server/templates/libraries_iphone-es.tpl b/release/server/templates/libraries_iphone-es.tpl new file mode 100644 index 00000000..b6fd5661 --- /dev/null +++ b/release/server/templates/libraries_iphone-es.tpl @@ -0,0 +1,22 @@ + + + + + + Login + + +
+

BIBLIOTECAS

+

Selecciona una biblioteca

+

+

+

+
+
 
+ + \ No newline at end of file diff --git a/release/server/templates/libraries_iphone.tpl b/release/server/templates/libraries_iphone.tpl new file mode 100644 index 00000000..73821b92 --- /dev/null +++ b/release/server/templates/libraries_iphone.tpl @@ -0,0 +1,22 @@ + + + + + + Login + + +
+

LIBRARIES

+

Select a comic library

+

+

+

+
+
 
+ + \ No newline at end of file