DiskScanner.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. #include "DiskScanner.h"
  2. #include "RunnableThread.h"
  3. #include "UserInterfaceUtility.h"
  4. #include <QTimer>
  5. #include <QDir>
  6. #include <QMutex>
  7. #include <QDirIterator>
  8. #include <QCoreApplication>
  9. #include <QMutexLocker>
  10. #include <QQueue>
  11. #include <dirent.h>
  12. #include <sys/stat.h>
  13. #include <unistd.h>
  14. #include <qmath.h>
  15. //计算文件大小 modify by wandz at 20190718
  16. static qint64 CalcFileSize(const QString &filename)
  17. {
  18. QFile file(filename);
  19. if (!file.open(QIODevice::ReadOnly))
  20. {
  21. qDebug()<<"file open failed";
  22. file.close();
  23. return -1;
  24. }
  25. // qDebug() <<"filename :"<<filename<<"filesize ="<< file.size()/(qPow(1024,2))<<"M";
  26. file.close();
  27. return file.size()/(qPow(1024,2));
  28. }
  29. //判断图片的支持格式,进行区分 modify by wandz at 20190718
  30. bool ImagesupportFormat(const QString &filename)
  31. {
  32. bool flag = false;
  33. QString imagename = filename;
  34. imagename = imagename.toLower();
  35. if(imagename.contains(".jpg") || imagename.contains(".bmp") \
  36. || imagename.contains(".jpeg") || imagename.contains(".png") \
  37. || imagename.contains(".gif") || imagename.contains(".tiff") \
  38. || imagename.contains(".pcx") || imagename.contains(".ico") \
  39. || imagename.contains(".tif")){
  40. return !flag;
  41. }
  42. else {
  43. return flag;
  44. }
  45. }
  46. static void scannerThreadCallback(void *paramater);
  47. class DiskScannerPrivate
  48. {
  49. Q_DISABLE_COPY(DiskScannerPrivate)
  50. public:
  51. explicit DiskScannerPrivate(DiskScanner *parent);
  52. ~DiskScannerPrivate();
  53. void initialize();
  54. void connectAllSlots();
  55. bool recursionScan(const QString& path);
  56. void scanFinish();
  57. CustomThread* m_CustomThread;
  58. QMap<int, QStringList> m_FilterMapList;
  59. QStringList m_Filter;
  60. QTimer* m_Timer;
  61. QString m_Path;
  62. bool m_ContinueFlag;
  63. QMutex m_Mutex;
  64. private:
  65. DiskScanner* m_Parent;
  66. };
  67. DiskScanner::DiskScanner(QObject *parent)
  68. : QObject(parent)
  69. , m_Private(new DiskScannerPrivate(this))
  70. {
  71. }
  72. DiskScanner::~DiskScanner()
  73. {
  74. }
  75. void DiskScanner::setScannerSuffixMap(const QMap<int, QStringList> &mapList)
  76. {
  77. m_Private->m_FilterMapList = mapList;
  78. for (QMap< int, QStringList >::iterator suffixIter = m_Private->m_FilterMapList.begin();
  79. suffixIter != m_Private->m_FilterMapList.end();
  80. ++suffixIter) {
  81. for (int i = 0; i < suffixIter.value().size(); ++i) {
  82. m_Private->m_Filter.append(QString("*") + suffixIter.value().at(i));
  83. }
  84. }
  85. }
  86. void DiskScanner::setMinimumScanTime(const int msec)
  87. {
  88. m_Private->m_Timer->setInterval(msec);
  89. }
  90. void DiskScanner::startScanner(const QString &path)
  91. {
  92. QMutexLocker mutexLocker(&m_Private->m_Mutex);
  93. m_Private->m_Timer->start();
  94. m_Private->m_Path = path;
  95. m_Private->m_ContinueFlag = true;
  96. m_Private->m_CustomThread->start(QThread::IdlePriority);
  97. }
  98. void DiskScanner::stopScanner()
  99. {
  100. QMutexLocker mutexLocker(&m_Private->m_Mutex);
  101. m_Private->m_Path.clear();
  102. m_Private->m_Timer->stop();
  103. m_Private->m_ContinueFlag = false;
  104. if (m_Private->m_CustomThread->isRunning()) {
  105. m_Private->m_CustomThread->wait();
  106. }
  107. }
  108. void DiskScanner::onFinish()
  109. {
  110. if (!m_Private->m_Timer->isActive()) {
  111. onTimeout();
  112. }
  113. }
  114. void DiskScanner::onTimeout()
  115. {
  116. if (!m_Private->m_CustomThread->isRunning()) {
  117. m_Private->scanFinish();
  118. }
  119. }
  120. DiskScannerPrivate::DiskScannerPrivate(DiskScanner *parent)
  121. : m_Parent(parent)
  122. {
  123. m_CustomThread = NULL;
  124. m_Timer = NULL;
  125. m_ContinueFlag = true;
  126. initialize();
  127. connectAllSlots();
  128. }
  129. DiskScannerPrivate::~DiskScannerPrivate()
  130. {
  131. m_CustomThread->exit(0);
  132. m_CustomThread->wait();
  133. }
  134. void DiskScannerPrivate::initialize()
  135. {
  136. m_CustomThread = new CustomThread(m_Parent);
  137. m_CustomThread->setCallbackFunction(scannerThreadCallback, static_cast<void *>(this));
  138. m_Timer = new QTimer(m_Parent);
  139. m_Timer->setSingleShot(true);
  140. m_Timer->setInterval(3500);
  141. }
  142. void DiskScannerPrivate::connectAllSlots()
  143. {
  144. Qt::ConnectionType type = static_cast<Qt::ConnectionType>(Qt::UniqueConnection | Qt::AutoConnection);
  145. QObject::connect(m_CustomThread, SIGNAL(finished()),
  146. m_Parent, SLOT(onFinish()),
  147. type);
  148. QObject::connect(m_Timer, SIGNAL(timeout()),
  149. m_Parent, SLOT(onTimeout()),
  150. type);
  151. }
  152. bool DiskScannerPrivate::recursionScan(const QString& path)
  153. {
  154. QString dirPath(path);
  155. QQueue<QString> queue;
  156. queue.enqueue(dirPath);
  157. DIR* dirptr = NULL;
  158. struct dirent* direntptr = NULL;
  159. struct stat64 statbuff;
  160. QString fullname;
  161. QString splliter("/");
  162. while (!queue.isEmpty()) {
  163. dirPath = queue.dequeue() + splliter;
  164. if (NULL != (dirptr = opendir(dirPath.toLocal8Bit().data()))) {
  165. while (NULL != (direntptr = readdir(dirptr))) {
  166. if ((NULL != direntptr->d_name)
  167. && ('.' == direntptr->d_name[0])) {
  168. continue;
  169. } else {
  170. fullname = dirPath + QString::fromLocal8Bit(direntptr->d_name);
  171. if (-1 != stat64(fullname.toLocal8Bit().data(), &statbuff)) {
  172. if(ImagesupportFormat(fullname) && CalcFileSize(fullname) >2.8){//image format >3m not load,modify by wandz at20190718
  173. fullname.clear();
  174. }
  175. if (S_ISDIR(statbuff.st_mode)) {
  176. queue.enqueue(QString(fullname));
  177. } else {
  178. for (QMap< int, QStringList >::iterator suffixIter = m_FilterMapList.begin();
  179. suffixIter != m_FilterMapList.end();
  180. ++suffixIter) {
  181. if (m_ContinueFlag) {
  182. if (suffixIter.value().contains(QString(strrchr(fullname.toLocal8Bit().data(), '.')), Qt::CaseInsensitive)) {
  183. emit m_Parent->filePath(fullname, suffixIter.key());
  184. }
  185. } else {
  186. break;
  187. }
  188. }
  189. }
  190. } else {
  191. qWarning() << "state64 error";
  192. break;
  193. }
  194. }
  195. }
  196. if (0 == closedir(dirptr)) {
  197. dirptr = NULL;
  198. } else {
  199. qWarning() << "closedir error";
  200. break;
  201. }
  202. } else {
  203. qWarning() << "opendir failed";
  204. break;
  205. }
  206. }
  207. return 0;
  208. }
  209. void DiskScannerPrivate::scanFinish()
  210. {
  211. if (!m_Timer->isActive()) {
  212. QMutexLocker mutexLocker(&m_Mutex);
  213. if (!m_Path.isEmpty()) {
  214. emit m_Parent->finish();
  215. }
  216. m_Path.clear();
  217. m_ContinueFlag = false;
  218. }
  219. }
  220. static void scannerThreadCallback(void *paramater)
  221. {
  222. DiskScannerPrivate *ptr = static_cast<DiskScannerPrivate *>(paramater);
  223. if (NULL != ptr) {
  224. if (ptr->m_ContinueFlag) {
  225. ptr->recursionScan(ptr->m_Path);
  226. if (ptr->m_ContinueFlag) {
  227. ptr->scanFinish();
  228. }
  229. }
  230. }
  231. }