notebook.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. #include "notebook.h"
  2. #include <QFileInfo>
  3. #include <versioncontroller/iversioncontroller.h>
  4. #include <notebookbackend/inotebookbackend.h>
  5. #include <notebookconfigmgr/inotebookconfigmgr.h>
  6. #include <utils/pathutils.h>
  7. #include <utils/fileutils.h>
  8. #include "exception.h"
  9. using namespace vnotex;
  10. const QString Notebook::c_defaultAttachmentFolder = QStringLiteral("vx_attachments");
  11. const QString Notebook::c_defaultImageFolder = QStringLiteral("vx_images");
  12. static vnotex::ID generateNotebookID()
  13. {
  14. static vnotex::ID id = Notebook::InvalidId;
  15. return ++id;
  16. }
  17. Notebook::Notebook(const NotebookParameters &p_paras,
  18. QObject *p_parent)
  19. : QObject(p_parent),
  20. m_id(generateNotebookID()),
  21. m_type(p_paras.m_type),
  22. m_name(p_paras.m_name),
  23. m_description(p_paras.m_description),
  24. m_rootFolderPath(p_paras.m_rootFolderPath),
  25. m_icon(p_paras.m_icon),
  26. m_imageFolder(p_paras.m_imageFolder),
  27. m_attachmentFolder(p_paras.m_attachmentFolder),
  28. m_createdTimeUtc(p_paras.m_createdTimeUtc),
  29. m_backend(p_paras.m_notebookBackend),
  30. m_versionController(p_paras.m_versionController),
  31. m_configMgr(p_paras.m_notebookConfigMgr)
  32. {
  33. if (m_imageFolder.isEmpty()) {
  34. m_imageFolder = c_defaultImageFolder;
  35. }
  36. if (m_attachmentFolder.isEmpty()) {
  37. m_attachmentFolder = c_defaultAttachmentFolder;
  38. }
  39. m_configMgr->setNotebook(this);
  40. }
  41. Notebook::~Notebook()
  42. {
  43. }
  44. vnotex::ID Notebook::getId() const
  45. {
  46. return m_id;
  47. }
  48. const QString &Notebook::getType() const
  49. {
  50. return m_type;
  51. }
  52. const QString &Notebook::getName() const
  53. {
  54. return m_name;
  55. }
  56. void Notebook::setName(const QString &p_name)
  57. {
  58. m_name = p_name;
  59. }
  60. void Notebook::updateName(const QString &p_name)
  61. {
  62. Q_ASSERT(!p_name.isEmpty());
  63. if (p_name == m_name) {
  64. return;
  65. }
  66. m_name = p_name;
  67. updateNotebookConfig();
  68. emit updated();
  69. }
  70. const QString &Notebook::getDescription() const
  71. {
  72. return m_description;
  73. }
  74. void Notebook::setDescription(const QString &p_description)
  75. {
  76. m_description = p_description;
  77. }
  78. void Notebook::updateDescription(const QString &p_description)
  79. {
  80. if (p_description == m_description) {
  81. return;
  82. }
  83. m_description = p_description;
  84. updateNotebookConfig();
  85. emit updated();
  86. }
  87. const QString &Notebook::getRootFolderPath() const
  88. {
  89. return m_rootFolderPath;
  90. }
  91. QString Notebook::getRootFolderAbsolutePath() const
  92. {
  93. return PathUtils::absolutePath(m_rootFolderPath);
  94. }
  95. const QIcon &Notebook::getIcon() const
  96. {
  97. return m_icon;
  98. }
  99. void Notebook::setIcon(const QIcon &p_icon)
  100. {
  101. m_icon = p_icon;
  102. }
  103. const QString &Notebook::getImageFolder() const
  104. {
  105. return m_imageFolder;
  106. }
  107. const QString &Notebook::getAttachmentFolder() const
  108. {
  109. return m_attachmentFolder;
  110. }
  111. const QSharedPointer<INotebookBackend> &Notebook::getBackend() const
  112. {
  113. return m_backend;
  114. }
  115. const QSharedPointer<IVersionController> &Notebook::getVersionController() const
  116. {
  117. return m_versionController;
  118. }
  119. const QSharedPointer<INotebookConfigMgr> &Notebook::getConfigMgr() const
  120. {
  121. return m_configMgr;
  122. }
  123. const QSharedPointer<Node> &Notebook::getRootNode() const
  124. {
  125. if (!m_root) {
  126. const_cast<Notebook *>(this)->m_root = m_configMgr->loadRootNode();
  127. Q_ASSERT(m_root->isRoot());
  128. }
  129. return m_root;
  130. }
  131. QSharedPointer<Node> Notebook::getRecycleBinNode() const
  132. {
  133. auto root = getRootNode();
  134. const auto &children = root->getChildrenRef();
  135. auto it = std::find_if(children.begin(),
  136. children.end(),
  137. [this](const QSharedPointer<Node> &p_node) {
  138. return isRecycleBinNode(p_node.data());
  139. });
  140. if (it != children.end()) {
  141. return *it;
  142. }
  143. return nullptr;
  144. }
  145. QSharedPointer<Node> Notebook::newNode(Node *p_parent,
  146. Node::Flags p_flags,
  147. const QString &p_name,
  148. const QString &p_content)
  149. {
  150. return m_configMgr->newNode(p_parent, p_flags, p_name, p_content);
  151. }
  152. const QDateTime &Notebook::getCreatedTimeUtc() const
  153. {
  154. return m_createdTimeUtc;
  155. }
  156. QSharedPointer<Node> Notebook::loadNodeByPath(const QString &p_path)
  157. {
  158. if (!PathUtils::pathContains(m_rootFolderPath, p_path)) {
  159. return nullptr;
  160. }
  161. QString relativePath;
  162. QFileInfo fi(p_path);
  163. if (fi.isAbsolute()) {
  164. if (!fi.exists()) {
  165. return nullptr;
  166. }
  167. relativePath = PathUtils::relativePath(m_rootFolderPath, p_path);
  168. } else {
  169. relativePath = p_path;
  170. }
  171. return m_configMgr->loadNodeByPath(getRootNode(), relativePath);
  172. }
  173. QSharedPointer<Node> Notebook::copyNodeAsChildOf(const QSharedPointer<Node> &p_src, Node *p_dest, bool p_move)
  174. {
  175. Q_ASSERT(p_src != p_dest);
  176. Q_ASSERT(p_dest->getNotebook() == this);
  177. if (Node::isAncestor(p_src.data(), p_dest)) {
  178. Exception::throwOne(Exception::Type::InvalidArgument,
  179. QString("source (%1) is the ancestor of destination (%2)")
  180. .arg(p_src->fetchPath(), p_dest->fetchPath()));
  181. return nullptr;
  182. }
  183. if (p_src->getParent() == p_dest && p_move) {
  184. return p_src;
  185. }
  186. return m_configMgr->copyNodeAsChildOf(p_src, p_dest, p_move);
  187. }
  188. void Notebook::removeNode(const QSharedPointer<Node> &p_node, bool p_force, bool p_configOnly)
  189. {
  190. Q_ASSERT(p_node && !p_node->isRoot());
  191. Q_ASSERT(p_node->getNotebook() == this);
  192. m_configMgr->removeNode(p_node, p_force, p_configOnly);
  193. }
  194. void Notebook::removeNode(Node *p_node, bool p_force, bool p_configOnly)
  195. {
  196. Q_ASSERT(p_node);
  197. removeNode(p_node->sharedFromThis(), p_force, p_configOnly);
  198. }
  199. bool Notebook::isRecycleBinNode(const Node *p_node) const
  200. {
  201. return p_node && p_node->getUse() == Node::Use::RecycleBin;
  202. }
  203. bool Notebook::isNodeInRecycleBin(const Node *p_node) const
  204. {
  205. if (p_node) {
  206. p_node = p_node->getParent();
  207. while (p_node) {
  208. if (isRecycleBinNode(p_node)) {
  209. return true;
  210. }
  211. p_node = p_node->getParent();
  212. }
  213. }
  214. return false;
  215. }
  216. void Notebook::moveNodeToRecycleBin(Node *p_node)
  217. {
  218. moveNodeToRecycleBin(p_node->sharedFromThis());
  219. }
  220. void Notebook::moveNodeToRecycleBin(const QSharedPointer<Node> &p_node)
  221. {
  222. Q_ASSERT(p_node && !p_node->isRoot());
  223. auto destNode = getOrCreateRecycleBinDateNode();
  224. copyNodeAsChildOf(p_node, destNode.data(), true);
  225. }
  226. QSharedPointer<Node> Notebook::getOrCreateRecycleBinDateNode()
  227. {
  228. // Name after date.
  229. auto dateNodeName = QDate::currentDate().toString(QStringLiteral("yyyyMMdd"));
  230. auto recycleBinNode = getRecycleBinNode();
  231. auto dateNode = recycleBinNode->findChild(dateNodeName,
  232. FileUtils::isPlatformNameCaseSensitive());
  233. if (!dateNode) {
  234. // Create a date node.
  235. dateNode = newNode(recycleBinNode.data(), Node::Flag::Container, dateNodeName);
  236. }
  237. return dateNode;
  238. }
  239. void Notebook::emptyNode(const Node *p_node, bool p_force)
  240. {
  241. // Copy the children.
  242. auto children = p_node->getChildren();
  243. for (const auto &child : children) {
  244. removeNode(child, p_force);
  245. }
  246. }
  247. void Notebook::moveFileToRecycleBin(const QString &p_filePath)
  248. {
  249. auto node = getOrCreateRecycleBinDateNode();
  250. auto destFilePath = PathUtils::concatenateFilePath(node->fetchPath(),
  251. PathUtils::fileName(p_filePath));
  252. destFilePath = getBackend()->renameIfExistsCaseInsensitive(destFilePath);
  253. m_backend->copyFile(p_filePath, destFilePath);
  254. getBackend()->removeFile(p_filePath);
  255. emit nodeUpdated(node.data());
  256. }
  257. void Notebook::moveDirToRecycleBin(const QString &p_dirPath)
  258. {
  259. auto node = getOrCreateRecycleBinDateNode();
  260. auto destDirPath = PathUtils::concatenateFilePath(node->fetchPath(),
  261. PathUtils::fileName(p_dirPath));
  262. destDirPath = getBackend()->renameIfExistsCaseInsensitive(destDirPath);
  263. m_backend->copyDir(p_dirPath, destDirPath);
  264. getBackend()->removeDir(p_dirPath);
  265. emit nodeUpdated(node.data());
  266. }
  267. QSharedPointer<Node> Notebook::addAsNode(Node *p_parent,
  268. Node::Flags p_flags,
  269. const QString &p_name,
  270. const NodeParameters &p_paras)
  271. {
  272. return m_configMgr->addAsNode(p_parent, p_flags, p_name, p_paras);
  273. }
  274. bool Notebook::isBuiltInFile(const Node *p_node, const QString &p_name) const
  275. {
  276. return m_configMgr->isBuiltInFile(p_node, p_name);
  277. }
  278. bool Notebook::isBuiltInFolder(const Node *p_node, const QString &p_name) const
  279. {
  280. return m_configMgr->isBuiltInFolder(p_node, p_name);
  281. }
  282. QSharedPointer<Node> Notebook::copyAsNode(Node *p_parent,
  283. Node::Flags p_flags,
  284. const QString &p_path)
  285. {
  286. return m_configMgr->copyAsNode(p_parent, p_flags, p_path);
  287. }
  288. void Notebook::reloadNodes()
  289. {
  290. m_root.clear();
  291. getRootNode();
  292. }
  293. QJsonObject Notebook::getExtraConfig(const QString &p_key) const
  294. {
  295. const auto &configs = getExtraConfigs();
  296. return configs.value(p_key).toObject();
  297. }
  298. QList<QSharedPointer<File>> Notebook::collectFiles()
  299. {
  300. QList<QSharedPointer<File>> files;
  301. auto rootNode = getRootNode();
  302. const auto &children = rootNode->getChildrenRef();
  303. for (const auto &child : children) {
  304. if (child->getUse() != Node::Use::Normal) {
  305. continue;
  306. }
  307. files.append(child->collectFiles());
  308. }
  309. return files;
  310. }