bookitemlist.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. #include "bookitemlist.h"
  2. #include "book.h"
  3. #include "bookunzipper.h"
  4. #include <QtDeclarative/qdeclarative.h>
  5. #include <QDirIterator>
  6. #include "quazipfile.h"
  7. #include "quazip_global.h"
  8. #include <QImageReader>
  9. #include "bookunrar.h"
  10. #include <QTimer>
  11. BookItemList::BookItemList(QDeclarativeItem *parent):
  12. QDeclarativeItem(parent)
  13. {
  14. // By default, QDeclarativeItem does not draw anything. If you subclass
  15. // QDeclarativeItem to create a visual item, you will need to uncomment the
  16. // following line:
  17. // setFlag(ItemHasNoContents, false);
  18. qRegisterMetaType<BookItemList::ErrorCodes>("ErrorCodes");
  19. cleanDirectories(CleanAll);
  20. createPrivateDirectories();
  21. m_unzipper = new BookUnzipper;
  22. connect(m_unzipper,SIGNAL(extractFinished(BookItemList::ErrorCodes)),this,SLOT(onExtractingFinished(BookItemList::ErrorCodes)));
  23. m_unrar = new BookUnrar(this);
  24. connect(m_unrar,SIGNAL(extractFinished(BookItemList::ErrorCodes)),this,SLOT(onExtractingFinished(BookItemList::ErrorCodes)));
  25. connect(m_unrar,SIGNAL(firstImageExtracted(BookItemList::ErrorCodes,Book*)),this,SLOT(onFirstImageExtracted(BookItemList::ErrorCodes,Book*)));
  26. }
  27. BookItemList::~BookItemList()
  28. {
  29. m_unzipper->cancelRun();
  30. cleanDirectories(CleanAll);
  31. while(!m_books.isEmpty()){
  32. Book* b = m_books.takeLast();
  33. delete b;
  34. }
  35. m_books.clear();
  36. delete m_unzipper;
  37. }
  38. void BookItemList::refreshBooks()
  39. {
  40. cleanDirectories(CleanAll);
  41. createPrivateDirectories();
  42. while(!m_books.isEmpty()){
  43. Book* b = m_books.takeLast();
  44. delete b;
  45. }
  46. m_books.clear();
  47. QTimer::singleShot(0,this,SLOT(searchArchives()));
  48. }
  49. void BookItemList::cleanDirectories(CleanDirectories toClean)
  50. {
  51. switch(toClean){
  52. case Extracted:{
  53. QDir dir(PRIVATE_BOOKDIR_EXTRACTED);
  54. QDirIterator fiter(PRIVATE_BOOKDIR_EXTRACTED,QStringList()<<"*",QDir::Files,QDirIterator::Subdirectories);
  55. QDirIterator diter(PRIVATE_BOOKDIR_EXTRACTED,QDir::AllDirs,QDirIterator::Subdirectories);
  56. while(fiter.hasNext()){
  57. QString name = fiter.next();
  58. QFile::remove(name);
  59. }
  60. while(diter.hasNext()){
  61. QString name = diter.next();
  62. if(!name.endsWith('.') && !name.endsWith("..")){
  63. QDir dir(name);
  64. dir.rmpath(name);
  65. }
  66. }
  67. dir.rmpath(PRIVATE_BOOKDIR_EXTRACTED);
  68. }break;
  69. case Thumbs:{
  70. QDir dir(PRIVATE_BOOKDIR_THUMBS);
  71. QDirIterator fiter(PRIVATE_BOOKDIR_THUMBS,QStringList()<<"*",QDir::Files,QDirIterator::Subdirectories);
  72. QDirIterator diter(PRIVATE_BOOKDIR_THUMBS,QDir::AllDirs,QDirIterator::Subdirectories);
  73. while(fiter.hasNext()){
  74. QString name = fiter.next();
  75. QFile::remove(name);
  76. }
  77. while(diter.hasNext()){
  78. QString name = diter.next();
  79. if(!name.endsWith('.') && !name.endsWith("..")){
  80. QDir dir(name);
  81. dir.rmpath(name);
  82. }
  83. }
  84. dir.rmpath(PRIVATE_BOOKDIR_THUMBS);
  85. }break;
  86. case CleanAll:{
  87. QDir dir(PRIVATE_BOOKDIR);
  88. QDirIterator fiter(PRIVATE_BOOKDIR,QStringList()<<"*",QDir::Files,QDirIterator::Subdirectories);
  89. QDirIterator diter(PRIVATE_BOOKDIR,QDir::AllDirs,QDirIterator::Subdirectories);
  90. while(fiter.hasNext()){
  91. QString name = fiter.next();
  92. QFile::remove(name);
  93. }
  94. while(diter.hasNext()){
  95. QString name = diter.next();
  96. if(!name.endsWith('.') && !name.endsWith("..")){
  97. QDir dir(name);
  98. dir.rmpath(name);
  99. }
  100. }
  101. dir.rmpath(PRIVATE_BOOKDIR);
  102. }break;
  103. default:break;
  104. }
  105. }
  106. void BookItemList::createPrivateDirectories()
  107. {
  108. QDir dir(PRIVATE_BOOKDIR);
  109. dir.mkpath(PRIVATE_BOOKDIR);
  110. dir.setPath(PRIVATE_BOOKDIR_EXTRACTED);
  111. dir.mkpath(PRIVATE_BOOKDIR_EXTRACTED);
  112. dir.setPath(PRIVATE_BOOKDIR_THUMBS);
  113. dir.mkpath(PRIVATE_BOOKDIR_THUMBS);
  114. }
  115. QDeclarativeListProperty<Book> BookItemList::books()
  116. {
  117. return QDeclarativeListProperty<Book>(this,0,NULL,&BookItemList::countFunction,&BookItemList::atFunction,NULL);
  118. }
  119. Book* BookItemList::atFunction(QDeclarativeListProperty<Book> *property, int index)
  120. {
  121. BookItemList* list = qobject_cast<BookItemList*>(property->object);
  122. if(list){
  123. return list->m_books.at(index);
  124. }else{
  125. return NULL;
  126. }
  127. }
  128. int BookItemList::countFunction(QDeclarativeListProperty<Book> *property)
  129. {
  130. BookItemList* list = qobject_cast<BookItemList*>(property->object);
  131. if(list){
  132. return list->m_books.count();
  133. }else{
  134. return 0;
  135. }
  136. }
  137. void BookItemList::openBook(int index)
  138. {
  139. Book* b = NULL;
  140. b = m_books.at(index);
  141. m_openedBookIndex=-1;
  142. if(b!=NULL){
  143. cleanDirectories(Extracted);
  144. m_openedBookIndex = index;
  145. switch(b->getArchiveType()){
  146. case Book::Zip:{
  147. m_unzipper->setArchiveName(b->getBookArchiveName());
  148. m_unzipper->start();
  149. }break;
  150. case Book::Rar:{
  151. m_unrar->setArchiveName(b->getBookArchiveName());
  152. m_unrar->extractAll();
  153. }break;
  154. default:break;
  155. }
  156. }
  157. }
  158. void BookItemList::onExtractingFinished(BookItemList::ErrorCodes code)
  159. {
  160. Book* book = m_books.at(m_openedBookIndex);
  161. bool success = false;
  162. if(code==NoError){
  163. QList<QByteArray> arr = QImageReader::supportedImageFormats();
  164. QStringList formats;
  165. foreach(QByteArray ar, arr){
  166. QString fmt("*.%1");
  167. fmt = fmt.arg(QVariant(ar).toString());
  168. formats.append(fmt);
  169. }
  170. QDirIterator diter(PRIVATE_BOOKDIR_EXTRACTED,formats,QDir::Files,QDirIterator::Subdirectories);
  171. QStringList files;
  172. while(diter.hasNext()){
  173. QString name = diter.next();
  174. files.append(name);
  175. }
  176. if(!files.isEmpty()){
  177. files.sort();
  178. book->setFilenameList(files);
  179. }
  180. success = true;
  181. }
  182. emit bookOpen(success, book);
  183. }
  184. void BookItemList::searchArchives()
  185. {
  186. QDirIterator diter(ARCHIVE_DIRECTORY,QStringList()<<"*.cbz"<<"*.zip",QDir::Files,QDirIterator::Subdirectories);
  187. QDirIterator riter(ARCHIVE_DIRECTORY,QStringList()<<"*.rar"<<"*.cbr",QDir::Files,QDirIterator::Subdirectories);
  188. QStringList files;
  189. QStringList rarFiles;
  190. QList<QByteArray> sported = QImageReader::supportedImageFormats();
  191. QDir thumbs(PRIVATE_BOOKDIR_THUMBS);
  192. thumbs.mkpath(PRIVATE_BOOKDIR_THUMBS);
  193. while(diter.hasNext()){
  194. files.append(diter.next());
  195. }
  196. while(riter.hasNext()){
  197. rarFiles.append(riter.next());
  198. }
  199. if(!files.isEmpty()){
  200. foreach(QString fn, files){
  201. QuaZip zip(fn);
  202. if(zip.open(QuaZip::mdUnzip)){
  203. bool found = false;
  204. QList<QuaZipFileInfo> files = zip.getFileInfoList();
  205. foreach(QuaZipFileInfo imgfile, files){
  206. foreach(QByteArray supported, sported ){
  207. QString extension(supported);
  208. QString fname = imgfile.name;
  209. if( fname.endsWith(extension, Qt::CaseInsensitive)){
  210. found = true;
  211. Book* b = new Book();
  212. int start = fn.lastIndexOf('/');
  213. int end = fn.lastIndexOf('.');
  214. QString bname = fn.mid(start+1,end-start-1);
  215. b->setBookName(bname);
  216. b->setBookArchiveName(fn);
  217. zip.setCurrentFile(fname);
  218. QuaZipFile file(&zip);
  219. if(file.open(QIODevice::ReadOnly)){
  220. QImage img;
  221. QString imgname = bname;
  222. imgname = imgname.replace(QRegExp("\\s"),QString("_"));
  223. imgname = imgname.replace(QRegExp("\\W"),QString("_"));
  224. imgname = PRIVATE_BOOKDIR_THUMBS+"/"+imgname+".png";
  225. img.loadFromData(file.readAll());
  226. img = img.scaled(SCALED_ICON_SIZE);
  227. img.save(imgname);
  228. b->setListImage(QUrl(imgname));
  229. file.close();
  230. }
  231. m_books.append(b);
  232. }
  233. }
  234. if(found)
  235. break;
  236. }
  237. zip.close();
  238. }
  239. }
  240. }
  241. m_bookCount = m_books.count();
  242. if(!rarFiles.isEmpty()){
  243. m_bookCount+=rarFiles.count();
  244. foreach(QString fname, rarFiles){
  245. Book* b = new Book();
  246. int start = fname.lastIndexOf('/');
  247. int end = fname.lastIndexOf('.');
  248. QString bname = fname.mid(start+1,end-start-1);
  249. b->setBookName(bname);
  250. b->setBookArchiveName(fname);
  251. m_unrar->getFirstImage(b);
  252. }
  253. }
  254. qDebug() << "bookcount: " << m_bookCount << " mbooks list: " << m_books.count();
  255. if(!m_books.isEmpty() && rarFiles.isEmpty())
  256. emit this->refreshBooksDone(true);
  257. else if(m_books.isEmpty() && rarFiles.isEmpty())
  258. emit this->refreshBooksDone(false);
  259. }
  260. void BookItemList::onFirstImageExtracted(BookItemList::ErrorCodes code, Book* book)
  261. {
  262. qDebug() << "Error: " <<code;
  263. if(code == NoError){
  264. m_books.append(book);
  265. }else{
  266. m_bookCount--;
  267. delete book;
  268. }
  269. if(m_books.count() == m_bookCount){
  270. emit this->refreshBooksDone(true);
  271. }
  272. }