/src/viewmanager.cpp

https://code.google.com/p/dwarftherapist/ · C++ · 398 lines · 332 code · 36 blank · 30 comment · 54 complexity · e6c91ad002c9202a3de7d85bb58c79ed MD5 · raw file

  1. /*
  2. Dwarf Therapist
  3. Copyright (c) 2009 Trey Stout (chmod)
  4. Permission is hereby granted, free of charge, to any person obtaining a copy
  5. of this software and associated documentation files (the "Software"), to deal
  6. in the Software without restriction, including without limitation the rights
  7. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. copies of the Software, and to permit persons to whom the Software is
  9. furnished to do so, subject to the following conditions:
  10. The above copyright notice and this permission notice shall be included in
  11. all copies or substantial portions of the Software.
  12. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  18. THE SOFTWARE.
  19. */
  20. #include "viewmanager.h"
  21. #include "statetableview.h"
  22. #include "dwarfmodel.h"
  23. #include "dwarfmodelproxy.h"
  24. #include "gridview.h"
  25. #include "defines.h"
  26. #include "truncatingfilelogger.h"
  27. #include "dwarftherapist.h"
  28. #include "viewcolumnset.h"
  29. #include "viewcolumn.h"
  30. #include "utils.h"
  31. ViewManager::ViewManager(DwarfModel *dm, DwarfModelProxy *proxy,
  32. QWidget *parent)
  33. : QTabWidget(parent)
  34. , m_model(dm)
  35. , m_proxy(proxy)
  36. , m_add_tab_button(new QToolButton(this))
  37. {
  38. m_proxy->setSourceModel(m_model);
  39. setTabsClosable(true);
  40. setMovable(true);
  41. #ifdef Q_WS_MAC
  42. setStyleSheet("QTabWidget::tab-bar { alignment: left; left: -4px; }");
  43. #endif
  44. reload_views();
  45. m_add_tab_button->setIcon(QIcon(":img/tab_add.png"));
  46. m_add_tab_button->setPopupMode(QToolButton::InstantPopup);
  47. m_add_tab_button->setToolButtonStyle(Qt::ToolButtonIconOnly);
  48. draw_add_tab_button();
  49. setCornerWidget(m_add_tab_button, Qt::TopLeftCorner);
  50. connect(tabBar(), SIGNAL(tabMoved(int, int)), SLOT(write_views()));
  51. connect(tabBar(), SIGNAL(currentChanged(int)), SLOT(setCurrentIndex(int)));
  52. connect(this, SIGNAL(tabCloseRequested(int)),
  53. SLOT(remove_tab_for_gridview(int)));
  54. connect(m_model, SIGNAL(need_redraw()), SLOT(redraw_current_tab()));
  55. draw_views();
  56. }
  57. void ViewManager::draw_add_tab_button() {
  58. QIcon icn(":img/tab_add.png");
  59. QMenu *m = new QMenu(this);
  60. foreach(GridView *v, m_views) {
  61. QAction *a = m->addAction(icn, "Add " + v->name(), this,
  62. SLOT(add_tab_from_action()));
  63. a->setData((qulonglong)v);
  64. }
  65. m_add_tab_button->setMenu(m);
  66. }
  67. void ViewManager::reload_views() {
  68. m_views.clear();
  69. QSettings *s = new QSettings(
  70. ":config/default_gridviews", QSettings::IniFormat);
  71. int total_views = s->beginReadArray("gridviews");
  72. QList<GridView*> built_in_views;
  73. for (int i = 0; i < total_views; ++i) {
  74. s->setArrayIndex(i);
  75. GridView *gv = GridView::read_from_ini(*s, this);
  76. gv->set_is_custom(false); // this is a default view
  77. m_views << gv;
  78. built_in_views << gv;
  79. }
  80. s->endArray();
  81. // now read any gridviews out of the user's settings
  82. s = DT->user_settings();
  83. total_views = s->beginReadArray("gridviews");
  84. for (int i = 0; i < total_views; ++i) {
  85. s->setArrayIndex(i);
  86. GridView *gv = GridView::read_from_ini(*s, this);
  87. bool name_taken = true;
  88. do {
  89. name_taken = false;
  90. foreach(GridView *built_in, built_in_views) {
  91. if (gv->name() == built_in->name()) {
  92. name_taken = true;
  93. break;
  94. }
  95. }
  96. if (name_taken) {
  97. QMessageBox::information(this, tr("Name in Use!"),
  98. tr("A custom view was found in your settings called '%1.' "
  99. "However, this name is already taken by a built-in view, "
  100. "you must rename the custom view.").arg(gv->name()));
  101. QString new_name;
  102. while (new_name.isEmpty() || new_name == gv->name()) {
  103. new_name = QInputDialog::getText(this, tr("Rename View"),
  104. tr("New name for '%1'").arg(gv->name()));
  105. }
  106. gv->set_name(new_name);
  107. }
  108. } while(name_taken);
  109. gv->set_is_custom(true); // this came from a user's settings
  110. m_views << gv;
  111. }
  112. s->endArray();
  113. LOGI << "Loaded" << m_views.size() << "views from disk";
  114. draw_add_tab_button();
  115. }
  116. void ViewManager::draw_views() {
  117. // see if we have a saved tab order...
  118. QTime start = QTime::currentTime();
  119. int idx = currentIndex();
  120. while (count()) {
  121. QWidget *w = widget(0);
  122. w->deleteLater();
  123. removeTab(0);
  124. }
  125. QStringList tab_order = DT->user_settings()->value(
  126. "gui_options/tab_order").toStringList();
  127. if (tab_order.size() == 0) {
  128. tab_order << "Labors" << "Military" << "Social";
  129. }
  130. if (tab_order.size() > 0) {
  131. foreach(QString name, tab_order) {
  132. foreach(GridView *v, m_views) {
  133. if (v->name() == name)
  134. add_tab_for_gridview(v);
  135. }
  136. }
  137. }
  138. if (idx >= 0 && idx <= count() - 1) {
  139. setCurrentIndex(idx);
  140. } else {
  141. setCurrentIndex(0);
  142. }
  143. QTime stop = QTime::currentTime();
  144. LOGD << QString("redrew views in %L1ms").arg(start.msecsTo(stop));
  145. }
  146. void ViewManager::write_tab_order() {
  147. QStringList tab_order;
  148. for (int i = 0; i < count(); ++i) {
  149. tab_order << tabText(i);
  150. }
  151. DT->user_settings()->setValue("gui_options/tab_order", tab_order);
  152. }
  153. void ViewManager::write_views() {
  154. QSettings *s = DT->user_settings();
  155. s->remove("gridviews"); // look at us, taking chances like this!
  156. // find all custom gridviews...
  157. QList<GridView*> custom_views;
  158. foreach(GridView *gv, m_views) {
  159. if (gv->is_custom())
  160. custom_views << gv;
  161. }
  162. s->beginWriteArray("gridviews", custom_views.size());
  163. int i = 0;
  164. foreach(GridView *gv, custom_views) {
  165. s->setArrayIndex(i++);
  166. gv->write_to_ini(*s);
  167. }
  168. s->endArray();
  169. write_tab_order();
  170. }
  171. void ViewManager::add_view(GridView *view) {
  172. view->re_parent(this);
  173. m_views << view;
  174. write_views();
  175. draw_add_tab_button();
  176. add_tab_for_gridview(view);
  177. }
  178. GridView *ViewManager::get_view(const QString &name) {
  179. GridView *retval = 0;
  180. foreach(GridView *view, m_views) {
  181. if (name == view->name()) {
  182. retval = view;
  183. break;
  184. }
  185. }
  186. return retval;
  187. }
  188. GridView *ViewManager::get_active_view() {
  189. GridView *retval = 0;
  190. foreach(GridView *view, m_views) {
  191. if (view->name() == tabText(currentIndex())) {
  192. retval = view;
  193. break;
  194. }
  195. }
  196. return retval;
  197. }
  198. void ViewManager::remove_view(GridView *view) {
  199. m_views.removeAll(view);
  200. for (int i = 0; i < count(); ++i) {
  201. if (tabText(i) == view->name())
  202. removeTab(i);
  203. }
  204. write_views();
  205. draw_add_tab_button();
  206. view->deleteLater();
  207. }
  208. void ViewManager::replace_view(GridView *old_view, GridView *new_view) {
  209. // if the current tab was updated, we need to redraw it
  210. bool update_current_index = false;
  211. for (int i = 0; i < count(); ++i) {
  212. if (tabText(i) == old_view->name()) {
  213. // update tab titles that were showing the old view
  214. setTabText(i, new_view->name());
  215. // going to have to redraw the active tab as its view was just
  216. // updated
  217. if (i == currentIndex())
  218. update_current_index = true;
  219. }
  220. }
  221. m_views.removeAll(old_view);
  222. m_views.append(new_view);
  223. write_views();
  224. draw_add_tab_button();
  225. if (update_current_index) {
  226. setCurrentIndex(currentIndex());
  227. }
  228. }
  229. StateTableView *ViewManager::get_stv(int idx) {
  230. if (idx == -1)
  231. idx = currentIndex();
  232. QWidget *w = widget(idx);
  233. if (w) {
  234. return qobject_cast<StateTableView*>(w);
  235. }
  236. return 0;
  237. }
  238. void ViewManager::setCurrentIndex(int idx) {
  239. if (idx < 0 || idx > count()-1) {
  240. LOGW << "tab switch to index" << idx << "requested but there are " <<
  241. "only" << count() << "tabs";
  242. return;
  243. }
  244. StateTableView *stv = get_stv(idx);
  245. foreach(GridView *v, m_views) {
  246. if (v->name() == tabText(idx)) {
  247. m_model->set_grid_view(v);
  248. m_model->build_rows();
  249. stv->header()->setResizeMode(QHeaderView::Fixed);
  250. stv->header()->setResizeMode(0, QHeaderView::ResizeToContents);
  251. stv->sortByColumn(0, Qt::AscendingOrder);
  252. QList<Dwarf*> tmp_list;
  253. foreach(Dwarf *d, m_selected_dwarfs) {
  254. tmp_list << d;
  255. }
  256. foreach(Dwarf *d, tmp_list) {
  257. stv->select_dwarf(d);
  258. }
  259. break;
  260. }
  261. }
  262. tabBar()->setCurrentIndex(idx);
  263. stv->restore_expanded_items();
  264. write_tab_order();
  265. }
  266. void ViewManager::dwarf_selection_changed(const QItemSelection &selected,
  267. const QItemSelection &deselected) {
  268. Q_UNUSED(selected);
  269. Q_UNUSED(deselected);
  270. QItemSelectionModel *selection = qobject_cast<QItemSelectionModel*>
  271. (QObject::sender());
  272. m_selected_dwarfs.clear();
  273. foreach(QModelIndex idx, selection->selectedRows(0)) {
  274. int dwarf_id = idx.data(DwarfModel::DR_ID).toInt();
  275. Dwarf *d = DT->get_dwarf_by_id(dwarf_id);
  276. if (d)
  277. m_selected_dwarfs << d;
  278. }
  279. }
  280. int ViewManager::add_tab_from_action() {
  281. QAction *a = qobject_cast<QAction*>(QObject::sender());
  282. if (!a)
  283. return -1;
  284. GridView *v = (GridView*)(a->data().toULongLong());
  285. int idx = add_tab_for_gridview(v);
  286. setCurrentIndex(idx);
  287. return idx;
  288. }
  289. int ViewManager::add_tab_for_gridview(GridView *v) {
  290. v->set_active(true);
  291. StateTableView *stv = new StateTableView(this);
  292. stv->setSortingEnabled(false);
  293. stv->set_model(m_model, m_proxy);
  294. stv->setSortingEnabled(true);
  295. connect(stv, SIGNAL(dwarf_focus_changed(Dwarf*)),
  296. SIGNAL(dwarf_focus_changed(Dwarf*))); // pass-thru
  297. connect(stv->selectionModel(),
  298. SIGNAL(selectionChanged(const QItemSelection &,
  299. const QItemSelection &)),
  300. SLOT(dwarf_selection_changed(const QItemSelection &,
  301. const QItemSelection &)));
  302. stv->show();
  303. int new_idx = addTab(stv, v->name());
  304. write_tab_order();
  305. return new_idx;
  306. }
  307. void ViewManager::remove_tab_for_gridview(int idx) {
  308. if (count() < 2) {
  309. QMessageBox::warning(this, tr("Can't Remove Tab"),
  310. tr("Cannot remove the last tab!"));
  311. return;
  312. }
  313. foreach(GridView *v, m_views) {
  314. if (v->name() == tabText(idx)) {
  315. // find out if there are other dupes of this view still active...
  316. int active = 0;
  317. for(int i = 0; i < count(); ++i) {
  318. if (tabText(i) == v->name()) {
  319. active++;
  320. }
  321. }
  322. if (active < 2)
  323. v->set_active(false);
  324. }
  325. }
  326. widget(idx)->deleteLater();
  327. removeTab(idx);
  328. write_tab_order();
  329. }
  330. void ViewManager::expand_all() {
  331. StateTableView *stv = get_stv();
  332. if (stv)
  333. stv->expandAll();
  334. }
  335. void ViewManager::collapse_all() {
  336. StateTableView *stv = get_stv();
  337. if (stv)
  338. stv->collapseAll();
  339. }
  340. void ViewManager::jump_to_dwarf(QTreeWidgetItem *current,
  341. QTreeWidgetItem *previous) {
  342. StateTableView *stv = get_stv();
  343. if (stv)
  344. stv->jump_to_dwarf(current, previous);
  345. }
  346. void ViewManager::jump_to_profession(QListWidgetItem *current,
  347. QListWidgetItem *previous) {
  348. StateTableView *stv = get_stv();
  349. if (stv)
  350. stv->jump_to_profession(current, previous);
  351. }
  352. void ViewManager::set_group_by(int group_by) {
  353. if (m_model)
  354. m_model->set_group_by(group_by);
  355. redraw_current_tab();
  356. }
  357. void ViewManager::redraw_current_tab() {
  358. setCurrentIndex(currentIndex());
  359. }