GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/widgets/tabs/setup_relations.cpp Lines: 68 131 51.9 %
Date: 2021-03-17 Branches: 61 156 39.1 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2008-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2019  The ManaPlus Developers
6
 *  Copyright (C) 2019-2021  Andrei Karas
7
 *
8
 *  This file is part of The ManaPlus Client.
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; either version 2 of the License, or
13
 *  any later version.
14
 *
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
#include "gui/widgets/tabs/setup_relations.h"
25
26
#include "actormanager.h"
27
28
#include "being/localplayer.h"
29
30
#include "gui/models/ignorechoiceslistmodel.h"
31
#include "gui/models/playertablemodel.h"
32
33
#include "gui/widgets/button.h"
34
#include "gui/widgets/checkbox.h"
35
#include "gui/widgets/containerplacer.h"
36
#include "gui/widgets/dropdown.h"
37
#include "gui/widgets/label.h"
38
#include "gui/widgets/layouthelper.h"
39
#include "gui/widgets/scrollarea.h"
40
#include "gui/widgets/guitable.h"
41
42
#include "utils/delete2.h"
43
44
#include "debug.h"
45
46
static const int COLUMNS_NR = 2;  // name plus listbox
47
static const int NAME_COLUMN = 0;
48
static const unsigned int NAME_COLUMN_WIDTH = 230;
49
static const unsigned int RELATION_CHOICE_COLUMN = 1;
50
static const unsigned int RELATION_CHOICE_COLUMN_WIDTH = 80;
51
52
3
static const std::string ACTION_DELETE("delete");
53
3
static const std::string ACTION_TABLE("table");
54
3
static const std::string ACTION_STRATEGY("strategy");
55
56
static const char *const table_titles[COLUMNS_NR] =
57
{
58
    // TRANSLATORS: relations table header
59
    N_("Name"),
60
    // TRANSLATORS: relations table header
61
    N_("Relation")
62
};
63
64
2
Setup_Relations::Setup_Relations(const Widget2 *const widget) :
65
    SetupTab(widget),
66
    PlayerRelationsListener(),
67

2
    mPlayerTableTitleModel(new StaticTableModel(1, COLUMNS_NR)),
68

2
    mPlayerTableModel(new PlayerTableModel(this)),
69

2
    mPlayerTable(new GuiTable(this, mPlayerTableModel, Opaque_true)),
70

2
    mPlayerTitleTable(new GuiTable(this, mPlayerTableTitleModel, Opaque_true)),
71
    mPlayerScrollArea(new ScrollArea(this,
72

4
        mPlayerTable, Opaque_true, std::string())),
73
    // TRANSLATORS: relation dialog button
74
2
    mDefaultTrading(new CheckBox(this, _("Allow trading"),
75
2
        (playerRelations.getDefault() & PlayerRelation::TRADE) != 0U,
76

4
        nullptr, std::string())),
77
    // TRANSLATORS: relation dialog button
78
2
    mDefaultWhisper(new CheckBox(this, _("Allow whispers"),
79
2
        (playerRelations.getDefault() & PlayerRelation::WHISPER) != 0U,
80

4
        nullptr, std::string())),
81
    // TRANSLATORS: relation dialog button
82
2
    mDeleteButton(new Button(this, _("Delete"), ACTION_DELETE,
83

2
        BUTTON_SKIN, this)),
84
4
    mIgnoreActionChoicesModel(new IgnoreChoicesListModel),
85
    mIgnoreActionChoicesBox(new DropDown(widget, mIgnoreActionChoicesModel,
86


46
        false, Modal_false, nullptr, std::string()))
87
{
88
    // TRANSLATORS: relation dialog name
89
10
    setName(_("Relations"));
90
91
4
    mPlayerTable->setOpaque(Opaque_false);
92
93
2
    mPlayerTableTitleModel->fixColumnWidth(NAME_COLUMN, NAME_COLUMN_WIDTH);
94
2
    mPlayerTableTitleModel->fixColumnWidth(RELATION_CHOICE_COLUMN,
95
2
                                           RELATION_CHOICE_COLUMN_WIDTH);
96
4
    mPlayerTitleTable->setBackgroundColor(getThemeColor(
97
4
        ThemeColorId::TABLE_BACKGROUND, 255U));
98
4
    mPlayerTitleTable->setSelectableGui(false);
99
100
6
    for (int i = 0; i < COLUMNS_NR; i++)
101
    {
102
20
        mPlayerTableTitleModel->set(0, i, new Label(
103

12
            this, gettext(table_titles[i])));
104
    }
105
106
4
    mPlayerTitleTable->setLinewiseSelection(true);
107
108
2
    mPlayerScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
109
4
    mPlayerTable->setActionEventId(ACTION_TABLE);
110
4
    mPlayerTable->setLinewiseSelection(true);
111
2
    mPlayerTable->addActionListener(this);
112
113
    // TRANSLATORS: relation dialog label
114

8
    Label *const ignore_action_label = new Label(this, _("When ignoring:"));
115
116
4
    mIgnoreActionChoicesBox->setActionEventId(ACTION_STRATEGY);
117
2
    mIgnoreActionChoicesBox->addActionListener(this);
118
119
2
    int ignore_strategy_index = 0;  // safe default
120
121
2
    if (playerRelations.getPlayerIgnoreStrategy() != nullptr)
122
    {
123
        ignore_strategy_index = playerRelations.getPlayerIgnoreStrategyIndex(
124
            playerRelations.getPlayerIgnoreStrategy()->mShortName);
125
        if (ignore_strategy_index < 0)
126
            ignore_strategy_index = 0;
127
    }
128
2
    mIgnoreActionChoicesBox->setSelected(ignore_strategy_index);
129
2
    mIgnoreActionChoicesBox->adjustHeight();
130
131
2
    reset();
132
133
    // Do the layout
134
4
    LayoutHelper h(this);
135
2
    ContainerPlacer place = h.getPlacer(0, 0);
136
137
2
    place(0, 0, mPlayerTitleTable, 6, 1);
138
4
    place(0, 1, mPlayerScrollArea, 6, 4).setPadding(2);
139
2
    place(0, 5, mDeleteButton, 1, 1);
140
2
    place(3, 5, ignore_action_label, 1, 1);
141

4
    place(4, 5, mIgnoreActionChoicesBox, 2, 1).setPadding(2);
142
2
    place(3, 6, mDefaultTrading, 3, 1);
143
2
    place(3, 7, mDefaultWhisper, 3, 1);
144
145
4
    playerRelations.addListener(this);
146
147
2
    setDimension(Rect(0, 0, 500, 350));
148
2
}
149
150
8
Setup_Relations::~Setup_Relations()
151
{
152
4
    playerRelations.removeListener(this);
153
2
    delete2(mIgnoreActionChoicesModel)
154
4
}
155
156
157
2
void Setup_Relations::reset()
158
{
159
    // We now have to search through the list of ignore choices to find the
160
    // current selection. We could use an index into the table of config
161
    // options in playerRelations instead of strategies to sidestep this.
162
2
    int selection = 0;
163
12
    for (size_t i = 0, sz = playerRelations.getPlayerIgnoreStrategies()
164
4
         ->size(); i < sz; ++ i)
165
    {
166
30
        if ((*playerRelations.getPlayerIgnoreStrategies())[i] ==
167
10
            playerRelations.getPlayerIgnoreStrategy())
168
        {
169
            selection = CAST_S32(i);
170
            break;
171
        }
172
    }
173
2
    mIgnoreActionChoicesBox->setSelected(selection);
174
2
}
175
176
void Setup_Relations::apply()
177
{
178
    playerRelations.store();
179
180
    const unsigned int old_default_relations = playerRelations.getDefault() &
181
        ~(PlayerRelation::TRADE | PlayerRelation::WHISPER);
182
    playerRelations.setDefault(old_default_relations
183
        | (mDefaultTrading->isSelected() ? PlayerRelation::TRADE : 0)
184
        | (mDefaultWhisper->isSelected() ? PlayerRelation::WHISPER : 0));
185
186
    if (actorManager != nullptr)
187
        actorManager->updatePlayerNames();
188
189
    if (localPlayer != nullptr)
190
        localPlayer->setCheckNameSetting(true);
191
}
192
193
void Setup_Relations::cancel()
194
{
195
}
196
197
void Setup_Relations::action(const ActionEvent &event)
198
{
199
    const std::string &eventId = event.getId();
200
    if (eventId == ACTION_TABLE)
201
    {
202
        // temporarily eliminate ourselves: we are fully aware of this change,
203
        // so there is no need for asynchronous updates.  (In fact, thouse
204
        // might destroy the widet that triggered them, which would be rather
205
        // embarrassing.)
206
        playerRelations.removeListener(this);
207
208
        const int row = mPlayerTable->getSelectedRow();
209
        if (row >= 0)
210
            mPlayerTableModel->updateModelInRow(row);
211
212
        playerRelations.addListener(this);
213
    }
214
    else if (eventId == ACTION_DELETE)
215
    {
216
        const int player_index = mPlayerTable->getSelectedRow();
217
218
        if (player_index < 0)
219
            return;
220
221
        playerRelations.removePlayer(mPlayerTableModel->getPlayerAt(
222
            player_index));
223
    }
224
    else if (eventId == ACTION_STRATEGY)
225
    {
226
        const int sel = mIgnoreActionChoicesBox->getSelected();
227
        if (sel < 0)
228
            return;
229
        PlayerIgnoreStrategy *const s =
230
            (*playerRelations.getPlayerIgnoreStrategies())[sel];
231
232
        playerRelations.setPlayerIgnoreStrategy(s);
233
    }
234
}
235
236
void Setup_Relations::updatedPlayer(const std::string &name A_UNUSED)
237
{
238
    mPlayerTableModel->playerRelationsUpdated();
239
    mDefaultTrading->setSelected(
240
            (playerRelations.getDefault() & PlayerRelation::TRADE) != 0U);
241
    mDefaultWhisper->setSelected(
242
            (playerRelations.getDefault() & PlayerRelation::WHISPER) != 0U);
243
    if (localPlayer != nullptr)
244
        localPlayer->updateName();
245
}
246
247
void Setup_Relations::updateAll()
248
{
249
    PlayerTableModel *const model = new PlayerTableModel(this);
250
    mPlayerTable->setModel(model);
251
    delete mPlayerTableModel;
252
    mPlayerTableModel = model;
253
    int ignore_strategy_index = 0;  // safe default
254
255
    if (playerRelations.getPlayerIgnoreStrategy() != nullptr)
256
    {
257
        ignore_strategy_index = playerRelations.getPlayerIgnoreStrategyIndex(
258
                playerRelations.getPlayerIgnoreStrategy()->mShortName);
259
        if (ignore_strategy_index < 0)
260
            ignore_strategy_index = 0;
261
    }
262
    mIgnoreActionChoicesBox->setSelected(ignore_strategy_index);
263
    mIgnoreActionChoicesBox->adjustHeight();
264
    reset();
265
}
266
void Setup_Relations::externalUpdated()
267
{
268
    mDefaultTrading->setSelected(
269
        (playerRelations.getDefault() & PlayerRelation::TRADE) != 0U);
270
    mDefaultWhisper->setSelected(
271
        (playerRelations.getDefault() & PlayerRelation::WHISPER) != 0U);
272

3
}