PageRenderTime 53ms CodeModel.GetById 16ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 0ms

/src/viewmanager.cpp

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