]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiToolbars.cpp
Crash fix.
[lyx.git] / src / frontends / qt4 / GuiToolbars.cpp
1 /**
2  * \file GuiToolbars.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  * \author Angus Leeming
8  * \author Abdelrazak Younes
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "GuiToolbars.h"
16
17 #include "GuiCommandBuffer.h"
18 #include "GuiToolbar.h"
19 #include "GuiView.h"
20
21 #include "Buffer.h"
22 #include "BufferParams.h"
23 #include "support/debug.h"
24 #include "FuncRequest.h"
25 #include "FuncStatus.h"
26 #include "support/gettext.h"
27 #include "Layout.h"
28 #include "LyX.h"
29 #include "LyXFunc.h"
30 #include "TextClass.h"
31 #include "ToolbarBackend.h"
32
33 using namespace std;
34
35 namespace lyx {
36 namespace frontend {
37
38 #define TurnOnFlag(x)   flags |= ToolbarInfo::x
39 #define TurnOffFlag(x)  flags &= ~ToolbarInfo::x
40
41 GuiToolbars::GuiToolbars(GuiView & owner)
42         : owner_(owner)
43 {
44         init();
45 }
46
47
48 void GuiToolbars::initFlags(ToolbarInfo & tbinfo)
49 {
50         ToolbarSection::ToolbarInfo & info = LyX::ref().session().toolbars().load(tbinfo.name);
51
52         unsigned int flags = static_cast<unsigned int>(tbinfo.flags);
53
54         // Remove default.ui positions. Only when a valid postion is stored
55         // in the session file the default.ui value will be overwritten
56         unsigned int save = flags;
57         TurnOffFlag(TOP);
58         TurnOffFlag(BOTTOM);
59         TurnOffFlag(RIGHT);
60         TurnOffFlag(LEFT);
61
62         bool valid_location = true;
63         // init tbinfo.flags with saved location
64         if (info.location == ToolbarSection::ToolbarInfo::TOP)
65                 TurnOnFlag(TOP);
66         else if (info.location == ToolbarSection::ToolbarInfo::BOTTOM)
67                 TurnOnFlag(BOTTOM);
68         else if (info.location == ToolbarSection::ToolbarInfo::RIGHT)
69                 TurnOnFlag(RIGHT);
70         else if (info.location == ToolbarSection::ToolbarInfo::LEFT)
71                 TurnOnFlag(LEFT);
72         else {
73                 // use setting from default.ui
74                 flags = save;
75                 valid_location = false;
76         }
77
78         // invalid location is for a new toolbar that has no saved information,
79         // so info.visible is not used for this case.
80         if (valid_location) {
81                 // init tbinfo.flags with saved visibility,
82                 TurnOffFlag(ON);
83                 TurnOffFlag(OFF);
84                 TurnOffFlag(AUTO);
85                 if (info.state == ToolbarSection::ToolbarInfo::ON)
86                         TurnOnFlag(ON);
87                 else if (info.state == ToolbarSection::ToolbarInfo::OFF)
88                         TurnOnFlag(OFF);
89                 else
90                         TurnOnFlag(AUTO);
91         }
92         /*
93         cout << "State " << info.state << " FLAGS: " << flags
94                 << " ON:" << (flags & ToolbarBackend::ON)
95                 << " OFF:" << (flags & ToolbarBackend::OFF)
96                 << " L:" << (flags & ToolbarBackend::LEFT)
97                 << " R:" << (flags & ToolbarBackend::RIGHT)
98                 << " T:" << (flags & ToolbarBackend::TOP)
99                 << " B:" << (flags & ToolbarBackend::BOTTOM)
100                 << " MA:" << (flags & ToolbarBackend::MATH)
101                 << " RE:" << (flags & ToolbarBackend::REVIEW)
102                 << " TB:" << (flags & ToolbarBackend::TABLE)
103                 << " AU:" << (flags & ToolbarBackend::AUTO)
104                 << endl;
105         */
106         // now set the flags
107         tbinfo.flags = static_cast<lyx::ToolbarInfo::Flags>(flags);
108 }
109
110
111 void GuiToolbars::init()
112 {
113         ToolbarsMap::const_iterator it = toolbars_.begin();
114         for (; it != toolbars_.end(); ++it)
115                 delete it->second;
116         toolbars_.clear();
117
118         // extracts the toolbars from the backend
119         ToolbarBackend::Toolbars::iterator cit = toolbarbackend.begin();
120         ToolbarBackend::Toolbars::iterator end = toolbarbackend.end();
121
122         // init flags will also add these toolbars to session if they
123         // are not already there (e.g. first run of lyx).
124         for (; cit != end; ++cit)
125                 initFlags(*cit);
126
127         // add toolbars according the order in session
128         ToolbarSection::ToolbarList::const_iterator tb =
129                 LyX::ref().session().toolbars().begin();
130         ToolbarSection::ToolbarList::const_iterator te =
131                 LyX::ref().session().toolbars().end();
132         ToolbarSection::ToolbarInfo::Location last_loc =
133                 ToolbarSection::ToolbarInfo::NOTSET;
134         int last_posx = 0;
135         int last_posy = 0;
136         for (; tb != te; ++tb) {
137                 LYXERR(Debug::INIT, "Adding " << tb->key << " at position "
138                         << tb->info.posx << " " << tb->info.posy);
139                 // add toolbar break if posx or posy changes
140                 bool newline = tb->info.location == last_loc && (
141                         // if two toolbars at the same location, assume uninitialized and add toolbar break
142                         (tb->info.posx == last_posx && tb->info.posy == last_posy) ||
143                         (last_loc == ToolbarSection::ToolbarInfo::TOP && tb->info.posy != last_posy) ||
144                         (last_loc == ToolbarSection::ToolbarInfo::BOTTOM && tb->info.posy != last_posy) ||
145                         (last_loc == ToolbarSection::ToolbarInfo::LEFT && tb->info.posx != last_posx) ||
146                         (last_loc == ToolbarSection::ToolbarInfo::RIGHT && tb->info.posx != last_posx) );
147                 // find the backend item and add
148                 for (cit = toolbarbackend.begin(); cit != end; ++cit)
149                         if (cit->name == tb->key) {
150                                 add(*cit, newline);
151                                 last_loc = tb->info.location;
152                                 last_posx = tb->info.posx;
153                                 last_posy = tb->info.posy;
154                                 break;
155                         }
156         }
157 }
158
159
160 void GuiToolbars::display(string const & name, bool show)
161 {
162         ToolbarBackend::Toolbars::iterator cit = toolbarbackend.begin();
163         ToolbarBackend::Toolbars::iterator end = toolbarbackend.end();
164
165         for (; cit != end; ++cit) {
166                 if (cit->name == name) {
167                         unsigned int flags = cit->flags;
168                         TurnOffFlag(ON);
169                         TurnOffFlag(OFF);
170                         TurnOffFlag(AUTO);
171                         if (show)
172                                 TurnOnFlag(ON);
173                         else
174                                 TurnOnFlag(OFF);
175                         cit->flags = static_cast<lyx::ToolbarInfo::Flags>(flags);
176                         displayToolbar(*cit, show);
177                 }
178         }
179
180         LYXERR(Debug::GUI, "Toolbar::display: no toolbar named " << name);
181 }
182
183
184 ToolbarInfo * GuiToolbars::getToolbarInfo(string const & name)
185 {
186         return toolbarbackend.getUsedToolbarInfo(name);
187 }
188
189
190 void GuiToolbars::toggleToolbarState(string const & name, bool allowauto)
191 {
192         ToolbarInfo * tbi = toolbarbackend.getUsedToolbarInfo(name);
193
194         if (!tbi) {
195                 LYXERR(Debug::GUI, "Toolbar::display: no toolbar named " << name);
196                 return;
197         }
198
199         int flags = tbi->flags;
200         // off -> on
201         if (flags & ToolbarInfo::OFF) {
202                 TurnOffFlag(OFF);
203                 TurnOnFlag(ON);
204         // auto -> off
205         } else if (flags & ToolbarInfo::AUTO) {
206                 TurnOffFlag(AUTO);
207                 TurnOnFlag(OFF);
208         } else if (allowauto 
209                    && ((flags & ToolbarInfo::MATH) 
210                        || (flags & ToolbarInfo::TABLE)
211                        || (flags & ToolbarInfo::REVIEW)
212                        || (flags & ToolbarInfo::MATHMACROTEMPLATE))) {
213                 // for math etc, toggle from on -> auto
214                 TurnOffFlag(ON);
215                 TurnOnFlag(AUTO);
216         } else {
217                 // for others, toggle from on -> off
218                 TurnOffFlag(ON);
219                 TurnOnFlag(OFF);
220         }
221         tbi->flags = static_cast<ToolbarInfo::Flags>(flags);
222 }
223 #undef TurnOnFlag
224 #undef TurnOffFlag
225
226
227 void GuiToolbars::update(bool in_math, bool in_table, bool review, 
228         bool in_mathmacrotemplate)
229 {
230         updateIcons();
231
232         // extracts the toolbars from the backend
233         ToolbarBackend::Toolbars::const_iterator cit = toolbarbackend.begin();
234         ToolbarBackend::Toolbars::const_iterator end = toolbarbackend.end();
235
236         for (; cit != end; ++cit) {
237                 if (cit->flags & ToolbarInfo::ON)
238                         displayToolbar(*cit, true);
239                 else if (cit->flags & ToolbarInfo::OFF)
240                         displayToolbar(*cit, false);
241                 else if ((cit->flags & ToolbarInfo::AUTO) && (cit->flags & ToolbarInfo::MATH))
242                         displayToolbar(*cit, in_math);
243                 else if ((cit->flags & ToolbarInfo::AUTO) && (cit->flags & ToolbarInfo::TABLE))
244                         displayToolbar(*cit, in_table);
245                 else if ((cit->flags & ToolbarInfo::AUTO) && (cit->flags & ToolbarInfo::REVIEW))
246                         displayToolbar(*cit, review);   
247                 else if ((cit->flags & ToolbarInfo::AUTO) && (cit->flags & ToolbarInfo::MATHMACROTEMPLATE))
248                         displayToolbar(*cit, in_mathmacrotemplate);
249         }
250 }
251
252
253 bool GuiToolbars::visible(string const & name) const
254 {
255         map<string, GuiToolbar *>::const_iterator it =
256                 toolbars_.find(name);
257         if (it == toolbars_.end())
258                 return false;
259         return it->second->isVisible();
260 }
261
262
263 void GuiToolbars::saveToolbarInfo()
264 {
265         ToolbarSection & tb = LyX::ref().session().toolbars();
266
267         for (ToolbarBackend::Toolbars::iterator cit = toolbarbackend.begin();
268                 cit != toolbarbackend.end(); ++cit) {
269                 ToolbarsMap::iterator it = toolbars_.find(cit->name);
270                 BOOST_ASSERT(it != toolbars_.end());
271                 // get toolbar info from session.
272                 ToolbarSection::ToolbarInfo & info = tb.load(cit->name);
273                 if (cit->flags & ToolbarInfo::ON)
274                         info.state = ToolbarSection::ToolbarInfo::ON;
275                 else if (cit->flags & ToolbarInfo::OFF)
276                         info.state = ToolbarSection::ToolbarInfo::OFF;
277                 else if (cit->flags & ToolbarInfo::AUTO)
278                         info.state = ToolbarSection::ToolbarInfo::AUTO;
279                 // save other information
280                 // if auto, frontend should *not* set on/off
281                 it->second->saveInfo(info);
282                 // maybe it is useful to update flags with real status. I do not know
283                 /*
284                 if (!(cit->flags & ToolbarInfo::AUTO)) {
285                         unsigned int flags = static_cast<unsigned int>(cit->flags);
286                         flags &= ~(info.state == ToolbarSection::ToolbarInfo::ON ? ToolbarInfo::OFF : ToolbarInfo::ON);
287                         flags |= (info.state == ToolbarSection::ToolbarInfo::ON ? ToolbarInfo::ON : ToolbarInfo::OFF);
288                         if (info.state == ToolbarSection::ToolbarInfo::ON)
289                         cit->flags = static_cast<lyx::ToolbarInfo::Flags>(flags);
290                 }
291                 */
292         }
293 }
294
295
296 void GuiToolbars::add(ToolbarInfo const & tbinfo, bool newline)
297 {
298         GuiToolbar * tb_ptr = owner_.makeToolbar(tbinfo, newline);
299         toolbars_[tbinfo.name] = tb_ptr;
300
301         if (tbinfo.flags & ToolbarInfo::ON)
302                 tb_ptr->show();
303         else
304                 tb_ptr->hide();
305 }
306
307
308 void GuiToolbars::displayToolbar(ToolbarInfo const & tbinfo,
309                               bool show_it)
310 {
311         ToolbarsMap::iterator it = toolbars_.find(tbinfo.name);
312         BOOST_ASSERT(it != toolbars_.end());
313
314         if (show_it) {
315                 if (it->second->isVisible())
316                         return;
317                 it->second->show();
318         }
319         else if (it->second->isVisible())
320                 it->second->hide();
321 }
322
323
324 void GuiToolbars::updateIcons()
325 {
326         ToolbarsMap::const_iterator it = toolbars_.begin();
327         ToolbarsMap::const_iterator const end = toolbars_.end();
328         for (; it != end; ++it)
329                 it->second->updateContents();
330 }
331
332
333 void GuiToolbars::showCommandBuffer(bool show_it)
334 {
335         ToolbarsMap::const_iterator it = toolbars_.begin();
336         ToolbarsMap::const_iterator const end = toolbars_.end();
337         for (; it != end; ++it) {
338                 GuiCommandBuffer * cb = it->second->commandBuffer();
339                 if (!cb)
340                         continue;
341                 if (!show_it) {
342                         // FIXME: this is a hack, "minibuffer" should not be
343                         // hardcoded.
344                         display("minibuffer", false);
345                         return;
346                 }
347                 if (!it->second->isVisible())
348                         display("minibuffer", true);
349                 cb->setFocus();
350                 return;
351         }
352 }
353
354 } // namespace frontend
355 } // namespace lyx