1 /*********
2 *
3 * This file is part of BibleTime's source code, http://www.bibletime.info/.
4 *
5 * Copyright 1999-2016 by the BibleTime developers.
6 * The BibleTime source code is licensed under the GNU General Public License version 2.0.
7 *
8 **********/
9
10 #include "frontend/displaywindow/bttextwindowheaderwidget.h"
11
12 #include <QHBoxLayout>
13 #include <QLabel>
14 #include <QMenu>
15 #include <QToolButton>
16 #include <QToolTip>
17 #include <QSizePolicy>
18 #include <QString>
19 #include "backend/config/btconfig.h"
20 #include "backend/managers/cswordbackend.h"
21 #include "bibletimeapp.h"
22 #include "frontend/displaywindow/bttextwindowheader.h"
23 #include "util/btconnect.h"
24 #include "util/cresmgr.h"
25
26
27 namespace {
28 const QString BookshelfShowHiddenKey = "GUI/bookshelfShowHidden";
29 } // anonymous namespace
30
31 const char* ActionType = "ActionType";
32 const char * ModuleName = "ModuleName";
33
BtTextWindowHeaderWidget(BtTextWindowHeader * parent,CSwordModuleInfo::ModuleType mtype)34 BtTextWindowHeaderWidget::BtTextWindowHeaderWidget(BtTextWindowHeader *parent, CSwordModuleInfo::ModuleType mtype)
35 : QWidget(parent),
36 m_moduleType(mtype),
37 m_popup(nullptr) {
38 QHBoxLayout* layout = new QHBoxLayout(this);
39 layout->setContentsMargins(0, 0, 0, 0);
40
41 m_label = new QLabel("", this);
42 QSizePolicy sizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
43 m_label->setSizePolicy(sizePolicy);
44 m_label->setStyleSheet("QLabel{font-weight:bold}");
45 layout->addWidget(m_label, 0, Qt::AlignRight);
46
47 m_button = new QToolButton( this );
48 m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
49 m_button->setPopupMode( QToolButton::InstantPopup );
50 m_button->setArrowType(Qt::NoArrow);
51 m_button->setStyleSheet("QToolButton{margin:0px;}QToolButton::menu-indicator{subcontrol-position: center center;}");
52 m_button->setToolTip( tr("Add/remove/replace") );
53
54 layout->addWidget(m_button, 0, Qt::AlignLeft);
55
56 m_separator = new QFrame(this);
57 m_separator->setFrameShape(QFrame::VLine);
58 layout->addWidget(m_separator);
59 }
60
recreateWidget(QStringList newModulesToUse,QString thisModule,int newIndex,int lefLikeModules)61 void BtTextWindowHeaderWidget::recreateWidget(QStringList newModulesToUse, QString thisModule, int newIndex, int lefLikeModules) {
62 populateMenu();
63 updateWidget(newModulesToUse, thisModule, newIndex, lefLikeModules);
64 }
65
66 // don't remove yet, maybe we'll add icons to buttons...
67 // const QString BtTextWindowHeaderWidget::iconName() {
68 // switch (m_moduleType) {
69 // case CSwordModuleInfo::Bible:
70 // return (m_hasModule) ? CResMgr::modules::bible::icon_unlocked : CResMgr::modules::bible::icon_add;
71 // case CSwordModuleInfo::Commentary:
72 // return (m_hasModule) ? CResMgr::modules::commentary::icon_unlocked : CResMgr::modules::commentary::icon_add;
73 // case CSwordModuleInfo::Lexicon:
74 // return m_hasModule ? CResMgr::modules::lexicon::icon_unlocked : CResMgr::modules::lexicon::icon_add;
75 // case CSwordModuleInfo::GenericBook:
76 // return m_hasModule ? CResMgr::modules::book::icon_unlocked : CResMgr::modules::book::icon_add;
77 // default: //return as default the bible icon
78 // return CResMgr::modules::bible::icon_unlocked;
79 // }
80 // }
81
updateWidget(QStringList newModulesToUse,QString thisModule,int newIndex,int leftLikeModules)82 void BtTextWindowHeaderWidget::updateWidget(QStringList newModulesToUse, QString thisModule, int newIndex, int leftLikeModules) {
83 m_label->setText(thisModule);
84 m_id = newIndex;
85 // create the menu if it doesn't exist
86 if (!m_popup)
87 populateMenu();
88
89 m_module = thisModule;
90
91 //All items are iterated and the state is changed properly
92 QListIterator<QMenu*> it(m_submenus);
93 while (it.hasNext()) {
94 QMenu* popup = it.next();
95 Q_FOREACH(QAction * const a, popup->actions()) {
96 a->setChecked(a->property(ModuleName).toString() == thisModule);
97 a->setDisabled(
98 newModulesToUse.contains(
99 a->property(ModuleName).toString()));
100 }
101 }
102
103 bool disableRemove = false;
104 if (newModulesToUse.count() == 1 ||
105 (newIndex == 0 && leftLikeModules == 1))
106 disableRemove = true;
107 m_removeAction->setDisabled(disableRemove);
108
109 // Disable non-Bible categories on left replace menu
110 if (m_moduleType == CSwordModuleInfo::Bible && m_id == 0) {
111 QList<QAction*> actionsType = m_popup->actions();
112 for (int t=0; t<actionsType.count(); t++) {
113 QAction* actionType = actionsType.at(t);
114 QString typeText = actionType->text();
115 if (typeText != QObject::tr("Replace"))
116 continue;
117 QMenu* menuType = actionType->menu();
118 if (menuType == nullptr)
119 continue;
120 QList<QAction*> actions = menuType->actions();
121 for (int i=0; i<actions.count(); i++) {
122 QAction* action = actions.at(i);
123 QString text = action->text();
124 if (text != QObject::tr("Bibles")) {
125 action->setDisabled(true);
126 }
127 }
128 }
129 }
130 }
131
132 /** Is called after a module was selected in the popup */
moduleChosen(QAction * action)133 void BtTextWindowHeaderWidget::moduleChosen( QAction* action ) {
134 if (action->property(ActionType).toInt() == RemoveAction) { // note: this is for m_popup, the toplevel!
135 emit sigModuleRemove(m_id);
136 return;
137 }
138 if (action->property(ActionType).toInt() == AddAction) {
139 emit sigModuleAdd(m_id + 1, action->property(ModuleName).toString());
140 return;
141 }
142 if (action->property(ActionType).toInt() == ReplaceAction) {
143 emit sigModuleReplace(m_id, action->property(ModuleName).toString());
144 }
145 }
146
147
populateMenu()148 void BtTextWindowHeaderWidget::populateMenu() {
149 delete m_popup;
150 m_popup = new QMenu(m_button);
151
152 BT_CONNECT(m_popup, SIGNAL(triggered(QAction *)),
153 this, SLOT(moduleChosen(QAction *)));
154 m_button->setMenu(m_popup);
155
156 m_removeAction = new QAction(tr("Remove"), m_popup);
157 m_removeAction->setProperty(ActionType, RemoveAction);
158 m_removeAction->setIcon(CResMgr::displaywindows::general::icon_removeModule());
159 m_popup->addAction(m_removeAction);
160
161 // Add Replace and Add menus, both have all modules in them
162 QMenu* replaceItem = new QMenu(tr("Replace"), m_popup);
163 replaceItem->setIcon(CResMgr::displaywindows::general::icon_replaceModule());
164 replaceItem->setProperty(ActionType, ReplaceAction);
165 m_popup->addMenu(replaceItem);
166
167 QMenu* addItem = new QMenu(tr("Add"), m_popup);
168 addItem->setProperty(ActionType, AddAction);
169 addItem->setIcon(CResMgr::displaywindows::general::icon_addModule());
170 m_popup->addMenu(addItem);
171
172 QList<QMenu*> toplevelMenus;
173 toplevelMenus.append(replaceItem);
174 toplevelMenus.append(addItem);
175
176 Q_FOREACH(QMenu * const menu, toplevelMenus) {
177 // ******* Add categories, languages and modules ********
178 // Filters: add only non-hidden, non-locked and correct type
179 BTModuleTreeItem::HiddenOff hiddenFilter;
180 QList<BTModuleTreeItem::Filter*> filters;
181 if (!btConfig().value<bool>(BookshelfShowHiddenKey, false)) {
182 filters.append(&hiddenFilter);
183 }
184 TypeFilter typeFilter(m_moduleType);
185 filters.append(&typeFilter);
186
187 TypeOfAction const typeOfAction =
188 static_cast<TypeOfAction>(menu->property(ActionType).toInt());
189 if (m_moduleType == CSwordModuleInfo::Bible) {
190 BTModuleTreeItem root(filters, BTModuleTreeItem::CatLangMod);
191 QList<BTModuleTreeItem::Filter*> filters2;
192 if (!btConfig().value<bool>(BookshelfShowHiddenKey, false)) {
193 filters2.append(&hiddenFilter);
194 }
195 if (menu == addItem || menu == replaceItem) {
196 TypeFilter typeFilter2(CSwordModuleInfo::Commentary);
197 filters2.append(&typeFilter2);
198 root.add_items(filters2);
199 }
200 addItemToMenu(&root, menu, typeOfAction);
201 }
202 else {
203 BTModuleTreeItem root(filters, BTModuleTreeItem::LangMod);
204 addItemToMenu(&root, menu, typeOfAction);
205 }
206 }
207 }
208
addItemToMenu(BTModuleTreeItem * item,QMenu * menu,TypeOfAction actionType)209 void BtTextWindowHeaderWidget::addItemToMenu(BTModuleTreeItem* item, QMenu* menu, TypeOfAction actionType) {
210 Q_FOREACH(BTModuleTreeItem * const i, item->children()) {
211 if (i->type() == BTModuleTreeItem::Language ||
212 i->type() == BTModuleTreeItem::Category) {
213 // argument menu was m_popup, create and add a new lang menu to it
214 QMenu* langMenu = new QMenu(i->text(), this);
215 menu->addMenu(langMenu);
216 m_submenus.append(langMenu);
217 // add the module items to the lang menu
218 addItemToMenu(i, langMenu, actionType);
219 }
220 else {
221 // item must be module, create and add it to the lang menu
222 QString name(i->text());
223 QAction* modItem = new QAction(name, menu);
224 modItem->setCheckable(true);
225 modItem->setProperty(ActionType, actionType);
226 modItem->setProperty(ModuleName, name);
227 menu->addAction(modItem);
228 }
229 }
230 }
231