vmainwindow.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. #include <QtWidgets>
  2. #include "vmainwindow.h"
  3. #include "vdirectorytree.h"
  4. #include "vnote.h"
  5. #include "vfilelist.h"
  6. #include "vtabwidget.h"
  7. #include "vconfigmanager.h"
  8. #include "dialog/vnewnotebookdialog.h"
  9. extern VConfigManager vconfig;
  10. VMainWindow::VMainWindow(QWidget *parent)
  11. : QMainWindow(parent)
  12. {
  13. // Must be called before those who uses VConfigManager
  14. vnote = new VNote();
  15. setupUI();
  16. initActions();
  17. initToolBar();
  18. initMenuBar();
  19. updateNotebookComboBox(vnote->getNotebooks());
  20. }
  21. VMainWindow::~VMainWindow()
  22. {
  23. delete vnote;
  24. }
  25. void VMainWindow::setupUI()
  26. {
  27. // Notebook directory browser tree
  28. notebookLabel = new QLabel(tr("Notebook"));
  29. directoryLabel = new QLabel(tr("Directory"));
  30. newNotebookBtn = new QPushButton(QIcon(":/resources/icons/create_notebook.png"), "");
  31. newNotebookBtn->setToolTip(tr("Create a new notebook"));
  32. deleteNotebookBtn = new QPushButton(QIcon(":/resources/icons/delete_notebook.png"), "");
  33. deleteNotebookBtn->setToolTip(tr("Delete current notebook"));
  34. notebookInfoBtn = new QPushButton(QIcon(":/resources/icons/notebook_info.png"), "");
  35. notebookInfoBtn->setToolTip(tr("View and edit current notebook's information"));
  36. notebookComboBox = new QComboBox();
  37. notebookComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
  38. directoryTree = new VDirectoryTree();
  39. QHBoxLayout *nbBtnLayout = new QHBoxLayout;
  40. nbBtnLayout->addWidget(notebookLabel);
  41. nbBtnLayout->addStretch();
  42. nbBtnLayout->addWidget(newNotebookBtn);
  43. nbBtnLayout->addWidget(deleteNotebookBtn);
  44. nbBtnLayout->addWidget(notebookInfoBtn);
  45. QVBoxLayout *nbLayout = new QVBoxLayout;
  46. nbLayout->addLayout(nbBtnLayout);
  47. nbLayout->addWidget(notebookComboBox);
  48. nbLayout->addWidget(directoryLabel);
  49. nbLayout->addWidget(directoryTree);
  50. QWidget *nbContainer = new QWidget();
  51. nbContainer->setLayout(nbLayout);
  52. nbContainer->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
  53. // File list widget
  54. fileList = new VFileList();
  55. fileList->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
  56. // Editor tab widget
  57. tabs = new VTabWidget();
  58. tabs->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  59. tabs->setTabBarAutoHide(true);
  60. // Main Splitter
  61. mainSplitter = new QSplitter();
  62. mainSplitter->addWidget(nbContainer);
  63. mainSplitter->addWidget(fileList);
  64. mainSplitter->addWidget(tabs);
  65. mainSplitter->setStretchFactor(0, 1);
  66. mainSplitter->setStretchFactor(1, 1);
  67. mainSplitter->setStretchFactor(2, 10);
  68. // Signals
  69. connect(notebookComboBox, SIGNAL(currentIndexChanged(int)), this,
  70. SLOT(setCurNotebookIndex(int)));
  71. connect(this, SIGNAL(curNotebookIndexChanged(const QString&)), directoryTree,
  72. SLOT(setTreePath(const QString&)));
  73. connect(directoryTree, &VDirectoryTree::currentDirectoryChanged,
  74. fileList, &VFileList::setDirectory);
  75. connect(fileList, &VFileList::fileClicked,
  76. tabs, &VTabWidget::openFile);
  77. connect(newNotebookBtn, &QPushButton::clicked,
  78. this, &VMainWindow::onNewNotebookBtnClicked);
  79. connect(deleteNotebookBtn, &QPushButton::clicked,
  80. this, &VMainWindow::onDeleteNotebookBtnClicked);
  81. connect(vnote, &VNote::notebooksChanged,
  82. this, &VMainWindow::updateNotebookComboBox);
  83. setCentralWidget(mainSplitter);
  84. // Create and show the status bar
  85. statusBar();
  86. }
  87. void VMainWindow::initActions()
  88. {
  89. editNoteAct = new QAction(tr("&Edit"), this);
  90. editNoteAct->setStatusTip(tr("Edit current note"));
  91. connect(editNoteAct, &QAction::triggered,
  92. tabs, &VTabWidget::editFile);
  93. readNoteAct = new QAction(tr("&Read"), this);
  94. readNoteAct->setStatusTip(tr("Open current note in read mode"));
  95. connect(readNoteAct, &QAction::triggered,
  96. tabs, &VTabWidget::readFile);
  97. saveNoteAct = new QAction(tr("&Save"), this);
  98. saveNoteAct->setStatusTip(tr("Save current note"));
  99. connect(saveNoteAct, &QAction::triggered,
  100. tabs, &VTabWidget::saveFile);
  101. importNoteAct = new QAction(tr("&Import note from file"), this);
  102. importNoteAct->setStatusTip(tr("Import notes into current directory from files"));
  103. connect(importNoteAct, &QAction::triggered,
  104. this, &VMainWindow::importNoteFromFile);
  105. }
  106. void VMainWindow::initToolBar()
  107. {
  108. QToolBar *fileToolBar = addToolBar(tr("Note"));
  109. fileToolBar->setMovable(false);
  110. fileToolBar->addAction(editNoteAct);
  111. fileToolBar->addAction(readNoteAct);
  112. fileToolBar->addAction(saveNoteAct);
  113. }
  114. void VMainWindow::initMenuBar()
  115. {
  116. QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
  117. QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
  118. // To be implemented
  119. fileMenu->addAction(importNoteAct);
  120. }
  121. void VMainWindow::updateNotebookComboBox(const QVector<VNotebook> &notebooks)
  122. {
  123. // Clearing and inserting items will emit the signal which corrupt the vconfig's
  124. // current index. We save it first and then set the combobox index to the
  125. // right one to resrote it.
  126. int curIndex = vconfig.getCurNotebookIndex();
  127. notebookComboBox->clear();
  128. if (notebooks.isEmpty()) {
  129. return;
  130. }
  131. for (int i = 0; i <notebooks.size(); ++i) {
  132. notebookComboBox->addItem(notebooks[i].getName());
  133. }
  134. qDebug() << "update notebook combobox with" << notebookComboBox->count()
  135. << "items, current notebook" << curIndex;
  136. notebookComboBox->setCurrentIndex(curIndex);
  137. }
  138. void VMainWindow::setCurNotebookIndex(int index)
  139. {
  140. Q_ASSERT(index < vnote->getNotebooks().size());
  141. // Update directoryTree
  142. QString treePath;
  143. if (index > -1) {
  144. vconfig.setCurNotebookIndex(index);
  145. treePath = vnote->getNotebooks()[index].getPath();
  146. }
  147. emit curNotebookIndexChanged(treePath);
  148. }
  149. void VMainWindow::onNewNotebookBtnClicked()
  150. {
  151. qDebug() << "request to create a notebook";
  152. QString info;
  153. QString defaultName("new_notebook");
  154. QString defaultPath;
  155. do {
  156. VNewNotebookDialog dialog(tr("Create a new notebook"), info, defaultName,
  157. defaultPath, this);
  158. if (dialog.exec() == QDialog::Accepted) {
  159. QString name = dialog.getNameInput();
  160. QString path = dialog.getPathInput();
  161. if (isConflictWithExistingNotebooks(name, path)) {
  162. info = "Name already exists or the path already has a notebook.";
  163. defaultName = name;
  164. defaultPath = path;
  165. continue;
  166. }
  167. vnote->createNotebook(name, path);
  168. }
  169. break;
  170. } while (true);
  171. }
  172. bool VMainWindow::isConflictWithExistingNotebooks(const QString &name, const QString &path)
  173. {
  174. const QVector<VNotebook> &notebooks = vnote->getNotebooks();
  175. for (int i = 0; i < notebooks.size(); ++i) {
  176. if (notebooks[i].getName() == name || notebooks[i].getPath() == path) {
  177. return true;
  178. }
  179. }
  180. return false;
  181. }
  182. void VMainWindow::onDeleteNotebookBtnClicked()
  183. {
  184. int curIndex = notebookComboBox->currentIndex();
  185. QString curName = vnote->getNotebooks()[curIndex].getName();
  186. QString curPath = vnote->getNotebooks()[curIndex].getPath();
  187. QMessageBox msgBox(QMessageBox::Warning, tr("Warning"), QString("Are you sure you want to delete notebook \"%1\"?")
  188. .arg(curName));
  189. msgBox.setInformativeText(QString("This will delete any files in this notebook (\"%1\").").arg(curPath));
  190. msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
  191. msgBox.setDefaultButton(QMessageBox::Ok);
  192. if (msgBox.exec() == QMessageBox::Ok) {
  193. vnote->removeNotebook(curName);
  194. }
  195. }
  196. void VMainWindow::importNoteFromFile()
  197. {
  198. QStringList files = QFileDialog::getOpenFileNames(this,tr("Select files(HTML or Markdown) to be imported as notes"),
  199. QDir::homePath());
  200. if (files.isEmpty()) {
  201. return;
  202. }
  203. QStringList failedFiles;
  204. for (int i = 0; i < files.size(); ++i) {
  205. bool ret = fileList->importFile(files[i]);
  206. if (!ret) {
  207. failedFiles.append(files[i]);
  208. }
  209. }
  210. QMessageBox msgBox(QMessageBox::Information, tr("Import note from file"),
  211. QString("Imported notes: %1 succeed, %2 failed.")
  212. .arg(files.size() - failedFiles.size()).arg(failedFiles.size()));
  213. if (!failedFiles.isEmpty()) {
  214. msgBox.setInformativeText(tr("Failed to import files may be due to name conflicts."));
  215. }
  216. msgBox.setStandardButtons(QMessageBox::Ok);
  217. msgBox.exec();
  218. }