IscanderChe
Шілде 30, 2019, 1:06 Т.Қ.

Қарапайым трекер жобасы. 6-бөлім: сервер. Сервер слоттары

Слоты, имеющие отношение непосредственно к серверу, мы рассмотрим в связке с клиентом. Пока же сосредоточимся на тех слотах, которые относятся к управлению проектами и задачами и общих слотах приложения.

Начнём с соединений. Их я вынес в отдельный метод void TrackerServer::createConnections() .

  1. // trackerserver.cpp
  2.  
  3. // Метод создания подключений
  4. void TrackerServer::createConnections()
  5. {
  6. // Установка текущего проекта
  7. connect(projectView, &QListView::clicked, this, &TrackerServer::slotSetCurrentProject);
  8. connect(projectView, &QListView::activated, this, &TrackerServer::slotSetCurrentProject);
  9.  
  10. // Подключение сигнала о смене статуса к обработчику
  11. connect(statusDelegate, &ComboBoxDelegate::commitData, this, &TrackerServer::slotChangeTaskStatus);
  12.  
  13. // Создание новой задачи
  14. connect(newTaskButton, &QPushButton::clicked, this, &TrackerServer::slotNewTask);
  15.  
  16. // Редактирование существующей задачи
  17. connect(editTaskButton, &QPushButton::clicked, this, &TrackerServer::slotEditTask);
  18. connect(taskView, &QTableView::doubleClicked, this, &TrackerServer::slotEditTask);
  19.  
  20. // Удаление существующей задачи
  21. connect(deleteTaskButton, &QPushButton::clicked, this, &TrackerServer::slotDeleteTask);
  22.  
  23. // Создание нового проекта
  24. connect(newProjectButton, &QPushButton::clicked, this, &TrackerServer::slotNewProject);
  25.  
  26. // Архивация существующего проекта
  27. connect(archiveProjectButton, &QPushButton::clicked, this, &TrackerServer::slotArchiveProject);
  28.  
  29. // Открытие архива проектов
  30. connect(openArchiveButton, &QPushButton::clicked, this, &TrackerServer::slotOpenArchive);
  31.  
  32. // Открытие окна трекера
  33. connect(actionOpenWindow, &QAction::triggered, this, &TrackerServer::slotOpenTrackerWindow);
  34.  
  35. // Открытие окна трекера по двойному клику на иконке в трее
  36. connect(trayIcon, &QSystemTrayIcon::activated, this, &TrackerServer::slotDoubleClickOpenTrackerWindow);
  37.  
  38. // Завершение работы трекера
  39. connect(actionQuit, &QAction::triggered, qApp, &QApplication::quit);
  40.  
  41. // Открытие окна настроек приложения
  42. connect(actionSettings, &QAction::triggered, this, &TrackerServer::slotOpenSettingsWindow);
  43. }

Для упрощения работы с элементами списка проектов определяем перечисление для Qt::DisplayRole и дополнительных ролей Qt::UserRole .

  1. // trackerserver.h
  2.  
  3. enum ProjectProperty
  4. {
  5. VisibleName = Qt::DisplayRole,
  6. Name = Qt::UserRole + 1,
  7. Id = Qt::UserRole + 2,
  8. Manual = Qt::UserRole + 3,
  9. Arch = Qt::UserRole + 4
  10. };
  1. // trackerserver.cpp
  2.  
  3. // Слот установки текущего проекта
  4. void TrackerServer::slotSetCurrentProject(QModelIndex index)
  5. {
  6. // Получаем элемент модели, соответствующий полученному индексу
  7. QStandardItem* item = projectListModel->itemFromIndex(index);
  8. // Получаем id текущего проекта
  9. projectCurrentId = item->data(ProjectProperty::Id).toInt();
  10. // Устанавливаем условие фильтрации таблицы задач по текущему id проекта
  11. taskFilterModel->setFilterFixedString(QString("%1").arg(projectCurrentId));
  12.  
  13. // Обновляем представление таблицы задач
  14. updateTaskView();
  15.  
  16. // Считаем количество строк в модели задач
  17. int rowNumber = taskFilterModel->rowCount();
  18.  
  19. // Если количество строк больше нуля
  20. if(rowNumber > 0)
  21. {
  22. // Получаем индекс нулевого элемента модели задач
  23. int row = 0;
  24. QModelIndex index = taskFilterModel->index(row, CustomSortFilterProxyModel::E_COLUMN_NUMBER);
  25. // Устанавливаем в представлении текущий элемент с этим индексом
  26. taskView->setCurrentIndex(index);
  27. // Делаем доступными кнопки редактирования и удаления задач
  28. editTaskButton->setEnabled(true);
  29. deleteTaskButton->setEnabled(true);
  30. }
  31. else
  32. {
  33. // Иначе блокируем кнопки редактирования и удаления задач
  34. editTaskButton->setDisabled(true);
  35. deleteTaskButton->setDisabled(true);
  36. }
  37.  
  38. // Делаем доступной кнопку создания новой задачи
  39. newTaskButton->setEnabled(true);
  40.  
  41. // Проверяем, закрыты ли все задачи текущего проекта
  42. if(database->isClosedAllTasks(projectCurrentId))
  43. // Если да, то делаем доступной кнопку архивирования проекта
  44. archiveProjectButton->setEnabled(true);
  45. else
  46. // Если нет, то блокируем кнопку архивирования проекта
  47. archiveProjectButton->setDisabled(true);
  48.  
  49. // Устанавливаем в виде текущим элемент с полученным индексом
  50. projectView->setCurrentIndex(index);
  51. }
  52.  
  53. // Слот создания нового проекта
  54. void TrackerServer::slotNewProject()
  55. {
  56. // Объявляем диалог создания нового проекта
  57. QSharedPointer<NewProjectDialog> dialog(new NewProjectDialog());
  58. // Созадаём диалоговое окно
  59. if(dialog->exec() == QDialog::Accepted)
  60. {
  61. // Если в диалоге нажата кнопка "ОК",
  62. // получаем из диалога наименование проекта
  63. QString projectName = dialog->getProjectName();
  64. // Если наименование проекта не пустое
  65. if(!projectName.isEmpty())
  66. {
  67. // Добавляем проект со свойство "без контроля СКВ"
  68. database->insertNewProject(projectName, ProjectVCS::WithoutVCS);
  69. // Обновляем модель проектов
  70. projectTableModel->select();
  71.  
  72. // Устанавливаем свойства элемента
  73. QString visibleProjectName = projectName;
  74. int row = projectTableModel->rowCount() - 1;
  75. int projectId =
  76. projectTableModel->record(row).value(idProjectCol).toInt();
  77. int projectManual = ProjectVCS::WithoutVCS;
  78. int projectArch = ProjectArchive::Active;
  79.  
  80. visibleProjectName = "(M) " + projectName;
  81.  
  82. QStandardItem* item = new QStandardItem();
  83. // Загружаем данные в элемент
  84. item->setData(visibleProjectName, ProjectProperty::VisibleName);
  85. item->setData(projectName, ProjectProperty::Name);
  86. item->setData(projectId, ProjectProperty::Id);
  87. item->setData(projectManual, ProjectProperty::Manual);
  88. item->setData(projectArch, ProjectProperty::Arch);
  89.  
  90. // Загружаем элемент в модель представления проектов
  91. projectListModel->appendRow(item);
  92.  
  93. // Устанавливаем текущий id проекта равный id нового проекта
  94. projectCurrentId = projectId;
  95. // Получаем индекс элемента нового проекта в модели представления
  96. int column = 0;
  97. QModelIndex currentProjectIndex = projectListModel->index(row, column);
  98. // Устанавливаем условие фильтрации таблицы задач по текущему id проекта
  99. taskFilterModel->setFilterFixedString(QString("%1").arg(projectCurrentId));
  100. // Устанвливаем текущий проект по индексу
  101. slotSetCurrentProject(currentProjectIndex);
  102.  
  103. // Поскольку новый проект пустой, блокируем кнопки удаления и редактирования задач,
  104. // и делаем доступной кнопку создания новой задачи
  105. editTaskButton->setDisabled(true);
  106. deleteTaskButton->setDisabled(true);
  107. newTaskButton->setEnabled(true);
  108. }
  109. }
  110. }
  111.  
  112. // Слот архивации проекта
  113. void TrackerServer::slotArchiveProject()
  114. {
  115. // Определяем индекс текущего проекта
  116. QModelIndex currentProjectIndex = projectView->currentIndex();
  117. int row = currentProjectIndex.row();
  118.  
  119. // Скрываем проект в представлении
  120. projectView->setRowHidden(row, true);
  121.  
  122. // Устанавливаем для элемента модели пресдтавления свойство архивации проекта
  123. QStandardItem* item = projectListModel->item(row);
  124. item->setData(ProjectArchive::Archive, ProjectProperty::Arch);
  125. projectListModel->setItem(row, item);
  126.  
  127. // Получаем из элемента модели представления id проекта
  128. int projectId = item->data(ProjectProperty::Id).toInt();
  129. // Архивируем проект
  130. database->archiveProject(projectId);
  131.  
  132. // Блокируем кнопку архивации проектов
  133. archiveProjectButton->setDisabled(true);
  134.  
  135. // Определяем, остались ли видимые элементы в списке проектов
  136. int numberRows = projectListModel->rowCount();
  137. int numberRowsNotHidden = 0;
  138. int firstRowNotHidden = 0;
  139.  
  140. for(int row = 0; row < numberRows; ++row)
  141. {
  142. if(!projectView->isRowHidden(row))
  143. {
  144. ++numberRowsNotHidden;
  145. firstRowNotHidden = row;
  146. break;
  147. }
  148. }
  149.  
  150. if(numberRowsNotHidden > 0)
  151. {
  152. // Если видимые элементы остались, определем индекс первого
  153. QModelIndex index = projectListModel->index(firstRowNotHidden, 0);
  154. // Устанавливаем этот элемент текущим проектом
  155. slotSetCurrentProject(index);
  156. }
  157. else
  158. {
  159. // Если видимых элементов нет, обнуляем текущий id проекта
  160. projectCurrentId = 0;
  161. // Устанавливаем условие фильтрации таблицы задач по текущему id проекта
  162. taskFilterModel->setFilterFixedString(QString("%1").arg(projectCurrentId));
  163. // Обновляем представление таблицы задач
  164. updateTaskView();
  165. }
  166.  
  167. }
  168.  
  169. // Слот открытия архива
  170. void TrackerServer::slotOpenArchive()
  171. {
  172. // Объявляем диалог открытия архива
  173. QSharedPointer<OpenArchiveDialog> dialog(new OpenArchiveDialog(projectListModel));
  174. // Если подтверждено извлечение из архива проекта/проектов
  175. if(dialog->exec() == QDialog::Accepted)
  176. {
  177. // Получаем список id извлекаемых из архива проектов
  178. QList<int> projectIdList = dialog->getListProjectId();
  179. int lastId = projectIdList.last();
  180. // Извлекаем проекты из архива
  181. foreach(int id, projectIdList)
  182. database->extractProject(id);
  183.  
  184. // Обновляем модель списка проектов
  185. updateProjectListModel();
  186. // Обновляем виджет списка проектов
  187. updateProjectView();
  188.  
  189. int numberRows = projectListModel->rowCount();
  190.  
  191. // Определяем индес последнего извлечённого проекта
  192. QModelIndex lastIndex;
  193. for(int row = 0; row < numberRows; ++row)
  194. {
  195. QStandardItem* item = projectListModel->item(row);
  196. int projectId = item->data(ProjectProperty::Id).toInt();
  197. if(projectId == lastId)
  198. lastIndex = projectListModel->indexFromItem(item);
  199. }
  200.  
  201. // Устанавливаем текущим последний извлечённый проект
  202. slotSetCurrentProject(lastIndex);
  203. }
  204. }
  205.  
  206. // Слот изменения состояния задачи
  207. void TrackerServer::slotChangeTaskStatus(QWidget* /* editor */)
  208. {
  209. // Обновляем модель SQL-таблицы задач
  210. taskSqlTableModel->select();
  211.  
  212. if(database->isClosedAllTasks(projectCurrentId))
  213. // Если все задачи закрыты, делаем доступной кнопку архивации проектов
  214. archiveProjectButton->setEnabled(true);
  215. else
  216. // Если нет, блокируем кнопку архивации проектов
  217. archiveProjectButton->setDisabled(true);
  218. }
  219.  
  220. // Слот создания новой задачи
  221. void TrackerServer::slotNewTask()
  222. {
  223. // Объявляем диалог создания / редактирования задачи
  224. QSharedPointer<NewEditTaskDialog> dialog(new NewEditTaskDialog());
  225. // Если создание новой задачи подтверждено
  226. if(dialog->exec() == QDialog::Accepted)
  227. {
  228. // Получаем из диалога тип и описание задачи
  229. QString type = dialog->getType();
  230. QString description = dialog->getDescription();
  231. // Если тип задачи и описание не пустые
  232. if(!type.isEmpty() && !description.isEmpty())
  233. {
  234. // Добавляем новую задачу
  235. database->insertNewTask(projectCurrentId, type, description);
  236. // Обновляем модель SQL-таблицы задач
  237. taskSqlTableModel->select();
  238. // Обновляем представление задач
  239. updateTaskView();
  240. // Определяем номер строки созданной задачи
  241. int row = taskFilterModel->rowCount() - 1;
  242. // Определяем индекс новой задачи в модели представления задач
  243. QModelIndex index = taskFilterModel->index(row, CustomSortFilterProxyModel::E_COLUMN_NUMBER);
  244. // Устанавливаем эту задачу текущей в представлении
  245. taskView->setCurrentIndex(index);
  246. // Делаем доступными кнопки редактирования и удаления задач
  247. editTaskButton->setEnabled(true);
  248. deleteTaskButton->setEnabled(true);
  249. }
  250. }
  251. }
  252.  
  253. // Слот редактирования задачи
  254. void TrackerServer::slotEditTask()
  255. {
  256. // Объявляем диалог создания / редактирования задачи
  257. QSharedPointer<NewEditTaskDialog> dialog(new NewEditTaskDialog());
  258.  
  259. // Извлекаем из текущего индекса задачи id, тип и описание задачи
  260. QModelIndex currentIndex = taskView->currentIndex();
  261. QModelIndex idIndex = taskFilterModel->index(currentIndex.row(), CustomSortFilterProxyModel::E_COLUMN_NUMBER);
  262. QModelIndex typeIndex = taskFilterModel->index(currentIndex.row(), CustomSortFilterProxyModel::E_COLUMN_TYPE);
  263. QModelIndex descriptionIndex = taskFilterModel->index(currentIndex.row(), CustomSortFilterProxyModel::E_COLUMN_DESCRIPTION);
  264.  
  265. QString type = taskFilterModel->data(typeIndex, Qt::DisplayRole).toString();
  266. QString description = taskFilterModel->data(descriptionIndex, Qt::DisplayRole).toString();
  267. int id = taskFilterModel->data(idIndex, Qt::DisplayRole).toInt();
  268.  
  269. // Передаём в диалог тип и описание задачи
  270. dialog->setType(type);
  271. dialog->setDescription(description);
  272.  
  273. // Если редактирование задачи подтверждено
  274. if(dialog->exec() == QDialog::Accepted)
  275. {
  276. // Если тип или описание задачи отредактированы
  277. if(type != dialog->getType() || description != dialog->getDescription())
  278. {
  279. // Редактируем задачу в базе
  280. database->editTask(id, dialog->getType(), dialog->getDescription());
  281. // Обновляем модель SQL-таблицы задач
  282. taskSqlTableModel->select();
  283. // Обновляем представление задач
  284. updateTaskView();
  285. // Устанавливаем отредактированную задачу текущей в представлении
  286. taskView->setCurrentIndex(currentIndex);
  287. }
  288. }
  289. }
  290.  
  291. // Слот удаления задачи
  292. void TrackerServer::slotDeleteTask()
  293. {
  294. // Объявляем диалог удаления задачи
  295. QSharedPointer<DeleteTaskDialog> dialog(new DeleteTaskDialog());
  296.  
  297. // Извлекаем из индекса id задачи
  298. QModelIndex currentIndex = taskView->currentIndex();
  299. QModelIndex idIndex = taskFilterModel->index(currentIndex.row(), CustomSortFilterProxyModel::E_COLUMN_NUMBER);
  300. int id = taskFilterModel->data(idIndex, Qt::DisplayRole).toInt();
  301.  
  302. // Если удаление задачи подтверждено
  303. if(dialog->exec() == QDialog::Accepted)
  304. {
  305. // Удаляем задачу из базы
  306. database->deleteTask(id);
  307. // Обновляем модель SQL-таблицы задач
  308. taskSqlTableModel->select();
  309. // Обновляем представление задач
  310. updateTaskView();
  311. // Определяем, остались ли видимые задачи
  312. int numberRows = taskFilterModel->rowCount();
  313. if(numberRows > 0)
  314. {
  315. // Если остались, делаем текущей первую
  316. int row = 0;
  317. QModelIndex index = taskFilterModel->index(row, CustomSortFilterProxyModel::E_COLUMN_NUMBER);
  318. taskView->setCurrentIndex(index);
  319. }
  320. else if(numberRows == 0)
  321. {
  322. // Если нет, блокируем кнопки редактирования и удаления задач
  323. editTaskButton->setDisabled(true);
  324. deleteTaskButton->setDisabled(true);
  325. }
  326. }
  327. }
  328.  
  329. // Слот открытия окна трекера
  330. void TrackerServer::slotOpenTrackerWindow()
  331. {
  332. setVisible(true);
  333. }
  334.  
  335. // Слот открытия окна трекера по двойному клику на иконке в трее
  336.  
  337. void TrackerServer::slotDoubleClickOpenTrackerWindow(QSystemTrayIcon::ActivationReason reason)
  338. {
  339. if(reason == QSystemTrayIcon::DoubleClick)
  340. setVisible(true);
  341. }
  342.  
  343. // Слот открытия окна настроек программы
  344. void TrackerServer::slotOpenSettingsWindow()
  345. {
  346. QSharedPointer<SettingsDialog> dialog(new SettingsDialog());
  347. dialog->exec();
  348. }

Создание проекта через трекер ограничено только проектами без контроля СКВ. Это сделано для упрощения функционала самого трекера. Проекты под контролем СКВ отслеживаются трекером с помощью следующего кода.

  1. // trackerserver.cpp
  2.  
  3. // Метод инициализации проектов под СКВ
  4. void TrackerServer::initProjectsWithVCS()
  5. {
  6. // В переменную записываем путь к репозиториям из объекта settings класса QSettings
  7. QString pathToProjects = settings.value("PathToProjects", "").toString();
  8. if(!pathToProjects.isEmpty())
  9. {
  10. // Если путь не пустой, формируем из списка репозиториев список проектов под СКВ
  11. QDir dir(pathToProjects);
  12. QStringList projectFileList;
  13.  
  14. foreach(QFileInfo item, dir.entryInfoList())
  15. {
  16. if(item.isDir())
  17. {
  18. QString dirPath = item.absoluteFilePath();
  19. QString dirName = item.fileName();
  20. // Критерием проекта под СКВ является наличие в репозитории в папке hooks
  21. // файла log.txt, куда хуки pre-commit и post-commit вносят информацию
  22. // о номере коммита и текст коммита с номером закрываемой задачи
  23. QString fileNamePath = dirPath + "/hooks/log.txt";
  24. QFile file(fileNamePath);
  25. if(file.exists())
  26. projectFileList << dirName;
  27. }
  28. }
  29.  
  30. if(!projectFileList.isEmpty())
  31. {
  32. // Если список проектов под СКВ не пустой, извлекаем из базы данных
  33. // список проектов и соответствующих им id проектов
  34. QStringList projectNameList;
  35. QList<int> projectIdList;
  36.  
  37. projectTableModel->select();
  38.  
  39. int numberRows = projectTableModel->rowCount();
  40.  
  41. for(int row = 0; row < numberRows; ++row)
  42. {
  43. int projectId =
  44. projectTableModel->record(row).value(idProjectCol).toInt();
  45. QString projectName =
  46. projectTableModel->record(row).value(visibleNameProjectCol).toString();
  47. int manualFlag =
  48. projectTableModel->record(row).value(manualPropertyCol).toInt();
  49. if(manualFlag == ProjectVCS::WithVCS)
  50. {
  51. projectIdList << projectId;
  52. projectNameList << projectName;
  53. }
  54. }
  55.  
  56. // Формируем список новых проектов, отсутствующих в базе
  57. QStringList newProjectList;
  58.  
  59. foreach(QString file, projectFileList)
  60. {
  61. int count = 0;
  62. foreach(QString project, projectNameList)
  63. {
  64. if(file == project)
  65. ++count;
  66. }
  67. if(count == 0)
  68. newProjectList << file;
  69. }
  70.  
  71. // Формируем список проектов, подлежащих автоматической архивации,
  72. // если репозитории этих проектов были удалены
  73. QStringList archiveProjectList;
  74.  
  75. foreach(QString project, projectNameList)
  76. {
  77. int count = 1;
  78. foreach(QString file, projectFileList)
  79. {
  80. if(project == file)
  81. --count;
  82. }
  83. if(count > 0)
  84. archiveProjectList << project;
  85. }
  86.  
  87. // Вносим новые проекты по списку
  88. foreach(QString project, newProjectList)
  89. database->insertNewProject(project, ProjectVCS::WithVCS);
  90.  
  91. // Архивируем проекты по списку
  92. foreach(QString project, archiveProjectList)
  93. {
  94. for(int i = 0; i < projectNameList.size(); ++i)
  95. {
  96. if(project == projectNameList.at(i))
  97. {
  98. database->archiveProject(projectIdList.at(i));
  99. // Получае перечень задач для данного проекта
  100. QList<int> taskIdList = database->getIdListForProject(projectIdList.at(i));
  101. foreach(int taskId, taskIdList)
  102. {
  103. if(!database->isClosed(taskId))
  104. // Если задача не закрыта, закрываем её с пометкой "forced"
  105. database->closeTask(taskId, "forced");
  106. }
  107. }
  108. }
  109. }
  110.  
  111. // Обновляем SQL-модель таблицы задач
  112. taskSqlTableModel->select();
  113. }
  114. }
  115. }

Мақала бойынша сұралады0сұрақтар(лар)

2

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

Evgenii Legotckoi
  • Шілде 30, 2019, 2:24 Т.Қ.

В общем-то достаточно написать так

  1. // trackerserver.h
  2.  
  3. enum ProjectProperty
  4. {
  5. VisibleName = Qt::DisplayRole,
  6. Name = Qt::UserRole + 1,
  7. Id,
  8. Manual,
  9. Arch
  10. };

Все enum после Name будут и так увеличиваться на единицу.

Объявление переменной row не нужно

  1. int row = 0;
  2. QModelIndex index = taskFilterModel->index(row, CustomSortFilterProxyModel::E_COLUMN_NUMBER);
  3. // Устанавливаем в представлении текущий элемент с этим индексом
  4. taskView->setCurrentIndex(index);

Можно переписать так, читабельность от этого не страдает. 0 здесь не будет магической цифрой, поскольку здесь очевидно, что выбирается первая строка.

  1. taskView->setCurrentIndex(taskFilterModel->index(0, CustomSortFilterProxyModel::E_COLUMN_NUMBER));

foreach выполняет глубокое копирование , лучше переходите полноценно на современные стандарты C++. То есть вместо этого

  1. foreach(int id, projectIdList)
  2. database->extractProject(id);

Можно написать так

  1. for(int id : projectIdList)
  2. database->extractProject(id);

К тому же foreach - это макрос, а значит получаем работу препроцессора, которае в случае конструкций языка, например for, не происходит. Конечно есть случае, где foreach ещё оправдан, но их мало на самом деле.

Там где у вас QModelIndex берутся, также можно переписать в одну строку, как в предыдущем варианте. В конечном счёте и так ясно, что за это индексы по enum CustomSortFilterProxyModel::E_COLUMN_TYPE например.

Думаю, что вот это

  1. int numberRows = taskFilterModel->rowCount();
  2. if(numberRows > 0)
  3. {
  4. // Если остались, делаем текущей первую
  5. int row = 0;
  6. QModelIndex index = taskFilterModel->index(row, CustomSortFilterProxyModel::E_COLUMN_NUMBER);
  7. taskView->setCurrentIndex(index);
  8. }
  9. else if(numberRows == 0)
  10. {
  11. // Если нет, блокируем кнопки редактирования и удаления задач
  12. editTaskButton->setDisabled(true);
  13. deleteTaskButton->setDisabled(true);
  14. }

Можно переписать так

  1. // rowCount не должен возвращать -1 в принципе, поэтому второе условие просто лишнее
  2. if (taskFilterModel->rowCount() > 0)
  3. {
  4. // Одной строкой достаточно, и так ясно, что происходит благодаря CustomSortFilterProxyModel::E_COLUMN_NUMBER
  5. taskView->setCurrentIndex(taskFilterModel->index(0, CustomSortFilterProxyModel::E_COLUMN_NUMBER));
  6. }
  7. else
  8. {
  9. editTaskButton->setDisabled(true);
  10. deleteTaskButton->setDisabled(true);
  11. }

Вот это лишнее переусложнение

  1. void TrackerServer::slotOpenSettingsWindow()
  2. {
  3. QSharedPointer<SettingsDialog> dialog(new SettingsDialog());
  4. dialog->exec();
  5. }

Просто создайте на стеке и тогда по окончанию работы диалог сам уничтожиться, не говоря уже о том, что в предыдущем варианте лишнее создание умного указателя с созданием объекта диалога и его копированием.

  1. void TrackerServer::slotOpenSettingsWindow()
  2. {
  3. SettingsDialog dialog;
  4. dialog.exec();
  5. }

Вот это

  1. QList<int> taskIdList = database->getIdListForProject(projectIdList.at(i));
  2. foreach(int taskId, taskIdList)
  3. {
  4. if(!database->isClosed(taskId))
  5. // Если задача не закрыта, закрываем её с пометкой "forced"
  6. database->closeTask(taskId, "forced");
  7. }

Можно ак переписать

  1. for (int taskId : database->getIdListForProject(projectIdList.at(i)))
  2. {
  3. if (!database->isClosed(taskId))
  4. database->closeTask(taskId, "forced");
  5. }

P/S/ Вы можете в статье добавлять рекомендуемые статьи, например, список всех статей по Simple Tracker. Тогда пользователи смогу лучше ориентироваться по всем вашим статьям.

IscanderChe
  • Шілде 30, 2019, 3:19 Т.Қ.

Все enum после Name будут и так увеличиваться на единицу.

Это мне самому нужно было, чтобы при переписываниии с Qt::UserRole + n на enum не запутаться. Сам себе проблему придумал, поскольку сразу не ввёл enum.

Там где у вас QModelIndex берутся, также можно переписать в одну строку, как в предыдущем варианте.

Тоже пишу так для себя, поскольку ещё не до окнца освоился с QModelIndex.

  1. lang-cpp for(int id : projectIdList)

Понял. Да, спасибо.

// rowCount не должен возвращать -1 в принципе, поэтому второе условие просто лишнее

Согласен.

Просто создайте на стеке и тогда по окончанию работы диалог сам уничтожиться, не говоря уже о том, что в предыдущем варианте лишнее создание умного указателя с созданием объекта диалога и его копированием.

Понял.

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз