vnotebook.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. #include "vnotebook.h"
  2. #include <QDir>
  3. #include <QDebug>
  4. #include "vdirectory.h"
  5. #include "utils/vutils.h"
  6. #include "vconfigmanager.h"
  7. #include "vnotefile.h"
  8. extern VConfigManager *g_config;
  9. VNotebook::VNotebook(const QString &name, const QString &path, QObject *parent)
  10. : QObject(parent), m_name(name), m_valid(false)
  11. {
  12. m_path = QDir::cleanPath(path);
  13. m_recycleBinFolder = g_config->getRecycleBinFolder();
  14. m_rootDir = new VDirectory(this,
  15. NULL,
  16. VUtils::directoryNameFromPath(path),
  17. QDateTime::currentDateTimeUtc());
  18. }
  19. VNotebook::~VNotebook()
  20. {
  21. delete m_rootDir;
  22. }
  23. bool VNotebook::readConfigNotebook()
  24. {
  25. QJsonObject configJson = VConfigManager::readDirectoryConfig(m_path);
  26. if (configJson.isEmpty()) {
  27. qWarning() << "fail to read notebook configuration" << m_path;
  28. m_valid = false;
  29. return false;
  30. }
  31. // [image_folder] section.
  32. auto it = configJson.find(DirConfig::c_imageFolder);
  33. if (it != configJson.end()) {
  34. m_imageFolder = it.value().toString();
  35. }
  36. // [recycle_bin_folder] section.
  37. it = configJson.find(DirConfig::c_recycleBinFolder);
  38. if (it != configJson.end()) {
  39. m_recycleBinFolder = it.value().toString();
  40. }
  41. // [attachment_folder] section.
  42. // SHOULD be processed at last.
  43. it = configJson.find(DirConfig::c_attachmentFolder);
  44. if (it != configJson.end()) {
  45. m_attachmentFolder = it.value().toString();
  46. }
  47. // We do not allow empty attachment folder.
  48. if (m_attachmentFolder.isEmpty()) {
  49. m_attachmentFolder = g_config->getAttachmentFolder();
  50. Q_ASSERT(!m_attachmentFolder.isEmpty());
  51. writeConfigNotebook();
  52. }
  53. m_valid = true;
  54. return true;
  55. }
  56. QJsonObject VNotebook::toConfigJsonNotebook() const
  57. {
  58. QJsonObject json;
  59. // [image_folder] section.
  60. json[DirConfig::c_imageFolder] = m_imageFolder;
  61. // [attachment_folder] section.
  62. json[DirConfig::c_attachmentFolder] = m_attachmentFolder;
  63. // [recycle_bin_folder] section.
  64. json[DirConfig::c_recycleBinFolder] = m_recycleBinFolder;
  65. return json;
  66. }
  67. QJsonObject VNotebook::toConfigJson() const
  68. {
  69. QJsonObject json = m_rootDir->toConfigJson();
  70. QJsonObject nbJson = toConfigJsonNotebook();
  71. // Merge nbJson to json.
  72. for (auto it = nbJson.begin(); it != nbJson.end(); ++it) {
  73. V_ASSERT(!json.contains(it.key()));
  74. json[it.key()] = it.value();
  75. }
  76. return json;
  77. }
  78. bool VNotebook::writeToConfig() const
  79. {
  80. return VConfigManager::writeDirectoryConfig(m_path, toConfigJson());
  81. }
  82. bool VNotebook::writeConfigNotebook() const
  83. {
  84. QJsonObject nbJson = toConfigJsonNotebook();
  85. QJsonObject configJson = VConfigManager::readDirectoryConfig(m_path);
  86. if (configJson.isEmpty()) {
  87. qWarning() << "fail to read notebook configuration" << m_path;
  88. return false;
  89. }
  90. for (auto it = nbJson.begin(); it != nbJson.end(); ++it) {
  91. configJson[it.key()] = it.value();
  92. }
  93. return VConfigManager::writeDirectoryConfig(m_path, configJson);
  94. }
  95. const QString &VNotebook::getName() const
  96. {
  97. return m_name;
  98. }
  99. const QString &VNotebook::getPath() const
  100. {
  101. return m_path;
  102. }
  103. void VNotebook::close()
  104. {
  105. m_rootDir->close();
  106. }
  107. bool VNotebook::open()
  108. {
  109. QString recycleBinPath = getRecycleBinFolderPath();
  110. if (!QFileInfo::exists(recycleBinPath)) {
  111. QDir dir(m_path);
  112. if (!dir.mkpath(recycleBinPath)) {
  113. qWarning() << "fail to create recycle bin folder" << recycleBinPath
  114. << "for notebook" << m_name;
  115. return false;
  116. }
  117. }
  118. return m_rootDir->open();
  119. }
  120. VNotebook *VNotebook::createNotebook(const QString &p_name,
  121. const QString &p_path,
  122. bool p_import,
  123. const QString &p_imageFolder,
  124. const QString &p_attachmentFolder,
  125. QObject *p_parent)
  126. {
  127. VNotebook *nb = new VNotebook(p_name, p_path, p_parent);
  128. // If @p_imageFolder is empty, it will report global configured folder as
  129. // its image folder.
  130. nb->setImageFolder(p_imageFolder);
  131. // If @p_attachmentFolder is empty, use global configured folder.
  132. QString attachmentFolder = p_attachmentFolder;
  133. if (attachmentFolder.isEmpty()) {
  134. attachmentFolder = g_config->getAttachmentFolder();
  135. }
  136. nb->setAttachmentFolder(attachmentFolder);
  137. // Check if there alread exists a config file.
  138. if (p_import && VConfigManager::directoryConfigExist(p_path)) {
  139. qDebug() << "import existing notebook";
  140. nb->readConfigNotebook();
  141. return nb;
  142. }
  143. VUtils::makePath(p_path);
  144. if (!nb->writeToConfig()) {
  145. delete nb;
  146. return NULL;
  147. }
  148. return nb;
  149. }
  150. bool VNotebook::deleteNotebook(VNotebook *p_notebook, bool p_deleteFiles)
  151. {
  152. bool ret = true;
  153. if (!p_notebook) {
  154. return true;
  155. }
  156. if (p_deleteFiles) {
  157. if (!p_notebook->open()) {
  158. qWarning() << "fail to open notebook" << p_notebook->getName()
  159. << "to delete";
  160. ret = false;
  161. goto exit;
  162. }
  163. // Delete sub directories.
  164. VDirectory *rootDir = p_notebook->getRootDir();
  165. QVector<VDirectory *> subdirs = rootDir->getSubDirs();
  166. for (auto dir : subdirs) {
  167. // Skip recycle bin.
  168. VDirectory::deleteDirectory(dir, true);
  169. }
  170. // Delete the recycle bin.
  171. QDir recycleDir(p_notebook->getRecycleBinFolderPath());
  172. if (!recycleDir.removeRecursively()) {
  173. qWarning() << "fail to delete notebook recycle bin folder"
  174. << p_notebook->getRecycleBinFolderPath();
  175. ret = false;
  176. }
  177. // Delete the config file.
  178. if (!VConfigManager::deleteDirectoryConfig(p_notebook->getPath())) {
  179. ret = false;
  180. goto exit;
  181. }
  182. // If it is now an empty directory, delete it.
  183. QDir dir(p_notebook->getPath());
  184. dir.cdUp();
  185. if (!dir.rmdir(rootDir->getName())) {
  186. qWarning() << "fail to delete notebook root folder" << rootDir->getName();
  187. ret = false;
  188. }
  189. }
  190. exit:
  191. p_notebook->close();
  192. delete p_notebook;
  193. return ret;
  194. }
  195. void VNotebook::rename(const QString &p_name)
  196. {
  197. if (p_name == m_name || p_name.isEmpty()) {
  198. return;
  199. }
  200. m_name = p_name;
  201. }
  202. bool VNotebook::containsFile(const VFile *p_file) const
  203. {
  204. return m_rootDir->containsFile(p_file);
  205. }
  206. VNoteFile *VNotebook::tryLoadFile(const QString &p_path)
  207. {
  208. QFileInfo fi(p_path);
  209. Q_ASSERT(fi.isAbsolute());
  210. if (!fi.exists()) {
  211. return NULL;
  212. }
  213. QStringList filePath;
  214. if (VUtils::splitPathInBasePath(m_path, p_path, filePath)) {
  215. if (filePath.isEmpty()) {
  216. return NULL;
  217. }
  218. bool opened = isOpened();
  219. if (!open()) {
  220. return NULL;
  221. }
  222. VNoteFile *file = m_rootDir->tryLoadFile(filePath);
  223. if (!file && !opened) {
  224. close();
  225. }
  226. return file;
  227. }
  228. return NULL;
  229. }
  230. VDirectory *VNotebook::tryLoadDirectory(const QString &p_path)
  231. {
  232. QFileInfo fi(p_path);
  233. Q_ASSERT(fi.isAbsolute());
  234. if (!fi.exists()) {
  235. return NULL;
  236. }
  237. QStringList filePath;
  238. if (VUtils::splitPathInBasePath(m_path, p_path, filePath)) {
  239. if (filePath.isEmpty()) {
  240. return NULL;
  241. }
  242. bool opened = isOpened();
  243. if (!open()) {
  244. return NULL;
  245. }
  246. VDirectory *dir = m_rootDir->tryLoadDirectory(filePath);
  247. if (!dir && !opened) {
  248. close();
  249. }
  250. return dir;
  251. }
  252. return NULL;
  253. }
  254. const QString &VNotebook::getImageFolder() const
  255. {
  256. if (m_imageFolder.isEmpty()) {
  257. return g_config->getImageFolder();
  258. } else {
  259. return m_imageFolder;
  260. }
  261. }
  262. void VNotebook::setImageFolder(const QString &p_imageFolder)
  263. {
  264. m_imageFolder = p_imageFolder;
  265. }
  266. const QString &VNotebook::getImageFolderConfig() const
  267. {
  268. return m_imageFolder;
  269. }
  270. const QString &VNotebook::getAttachmentFolder() const
  271. {
  272. return m_attachmentFolder;
  273. }
  274. void VNotebook::setAttachmentFolder(const QString &p_attachmentFolder)
  275. {
  276. m_attachmentFolder = p_attachmentFolder;
  277. }
  278. bool VNotebook::isOpened() const
  279. {
  280. return m_rootDir->isOpened();
  281. }
  282. QDateTime VNotebook::getCreatedTimeUtc()
  283. {
  284. if (!isOpened()) {
  285. if (!open()) {
  286. return QDateTime();
  287. }
  288. }
  289. return m_rootDir->getCreatedTimeUtc();
  290. }
  291. QString VNotebook::getRecycleBinFolderPath() const
  292. {
  293. QFileInfo fi(m_recycleBinFolder);
  294. if (fi.isAbsolute()) {
  295. return m_recycleBinFolder;
  296. } else {
  297. return QDir(m_path).filePath(m_recycleBinFolder);
  298. }
  299. }
  300. QList<QString> VNotebook::collectFiles()
  301. {
  302. QList<QString> files;
  303. bool opened = isOpened();
  304. if (!opened && !open()) {
  305. qWarning() << "fail to open notebook %1" << m_path;
  306. return files;
  307. }
  308. files = m_rootDir->collectFiles();
  309. if (!opened) {
  310. close();
  311. }
  312. return files;
  313. }