]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiToolbar.cpp
Also display the info about BibTeX databases in the TeX info panel.
[lyx.git] / src / frontends / qt4 / GuiToolbar.cpp
1 /**
2  * \file qt4/GuiToolbar.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 John Levon
8  * \author Jean-Marc Lasgouttes
9  * \author Angus Leeming
10  * \author Stefan Schimanski
11  * \author Abdelrazak Younes
12  *
13  * Full author contact details are available in file CREDITS.
14  */
15
16 #include <config.h>
17
18 #include "GuiToolbar.h"
19
20 #include "Action.h"
21 #include "GuiApplication.h"
22 #include "GuiCommandBuffer.h"
23 #include "GuiView.h"
24 #include "IconPalette.h"
25 #include "InsertTableWidget.h"
26 #include "LayoutBox.h"
27 #include "qt_helpers.h"
28 #include "Toolbars.h"
29
30 #include "FuncRequest.h"
31 #include "FuncStatus.h"
32 #include "KeyMap.h"
33 #include "LyX.h"
34 #include "LyXRC.h"
35
36 #include "support/debug.h"
37 #include "support/gettext.h"
38 #include "support/lstrings.h"
39
40 #include <QSettings>
41 #include <QShowEvent>
42 #include <QString>
43 #include <QToolBar>
44 #include <QToolButton>
45
46 #include "support/lassert.h"
47
48 using namespace std;
49 using namespace lyx::support;
50
51 namespace lyx {
52 namespace frontend {
53
54 GuiToolbar::GuiToolbar(ToolbarInfo const & tbinfo, GuiView & owner)
55         : QToolBar(toqstr(tbinfo.gui_name), &owner), visibility_(0),
56           owner_(owner), command_buffer_(0), tbinfo_(tbinfo), filled_(false)
57 {
58         setIconSize(owner.iconSize());
59         connect(&owner, SIGNAL(iconSizeChanged(QSize)), this,
60                 SLOT(setIconSize(QSize)));
61
62         // Toolbar dragging is allowed.
63         setMovable(true);
64         // This is used by QMainWindow::restoreState for proper main window state
65         // restauration.
66         setObjectName(toqstr(tbinfo.name));
67         restoreSession();
68 }
69
70
71 void GuiToolbar::fill()
72 {
73         if (filled_)
74                 return;
75         ToolbarInfo::item_iterator it = tbinfo_.items.begin();
76         ToolbarInfo::item_iterator end = tbinfo_.items.end();
77         for (; it != end; ++it)
78                 add(*it);       
79         filled_ = true;
80 }
81
82
83 void GuiToolbar::showEvent(QShowEvent * ev)
84 {
85         fill();
86         ev->accept();
87 }
88
89
90 void GuiToolbar::setVisibility(int visibility)
91 {
92         visibility_ = visibility;
93 }
94
95
96 Action * GuiToolbar::addItem(ToolbarItem const & item)
97 {
98         QString text = toqstr(item.label_);
99         // Get the keys bound to this action, but keep only the
100         // first one later
101         KeyMap::Bindings bindings = theTopLevelKeymap().findBindings(item.func_);
102         if (bindings.size())
103                 text += " [" + toqstr(bindings.begin()->print(KeySequence::ForGui)) + "]";
104
105         Action * act = new Action(&owner_, getIcon(item.func_, false),
106                 text, item.func_, text, this);
107         actions_.append(act);
108         return act;
109 }
110
111 namespace {
112
113 class PaletteButton : public QToolButton
114 {
115 private:
116         GuiToolbar * bar_;
117         ToolbarItem const & tbitem_;
118         bool initialized_;
119 public:
120         PaletteButton(GuiToolbar * bar, ToolbarItem const & item)
121                 : QToolButton(bar), bar_(bar), tbitem_(item), initialized_(false)
122         {
123                 QString const label = qt_(to_ascii(tbitem_.label_));
124                 setToolTip(label);
125                 setStatusTip(label);
126                 setText(label);
127                 connect(bar_, SIGNAL(iconSizeChanged(QSize)),
128                         this, SLOT(setIconSize(QSize)));
129                 setCheckable(true);
130                 ToolbarInfo const * tbinfo = guiApp->toolbars().info(tbitem_.name_);
131                 if (tbinfo)
132                         // use the icon of first action for the toolbar button
133                         setIcon(getIcon(tbinfo->items.begin()->func_, true));
134         }
135
136         void mousePressEvent(QMouseEvent * e)
137         {
138                 if (initialized_) {
139                         QToolButton::mousePressEvent(e);
140                         return;
141                 }
142
143                 initialized_ = true;
144
145                 ToolbarInfo const * tbinfo = guiApp->toolbars().info(tbitem_.name_);
146                 if (!tbinfo) {
147                         LYXERR0("Unknown toolbar " << tbitem_.name_);
148                         return;
149                 }
150                 IconPalette * panel = new IconPalette(this);
151                 QString const label = qt_(to_ascii(tbitem_.label_));
152                 panel->setWindowTitle(label);
153                 connect(this, SIGNAL(clicked(bool)), panel, SLOT(setVisible(bool)));
154                 connect(panel, SIGNAL(visible(bool)), this, SLOT(setChecked(bool)));
155                 ToolbarInfo::item_iterator it = tbinfo->items.begin();
156                 ToolbarInfo::item_iterator const end = tbinfo->items.end();
157                 for (; it != end; ++it)
158                         if (!getStatus(it->func_).unknown())
159                                 panel->addButton(bar_->addItem(*it));
160
161                 QToolButton::mousePressEvent(e);
162         }
163 };
164
165 }
166
167
168 MenuButton::MenuButton(GuiToolbar * bar, ToolbarItem const & item, bool const sticky)
169         : QToolButton(bar), bar_(bar), tbitem_(item), initialized_(false)
170 {
171         setPopupMode(QToolButton::InstantPopup);
172         QString const label = qt_(to_ascii(tbitem_.label_));
173         setToolTip(label);
174         setStatusTip(label);
175         setText(label);
176         QString const name = toqstr(tbitem_.name_);
177         QString imagedir = "images/math/";
178         FileName const fname = imageLibFileSearch(imagedir, name, "png");
179         if (fname.exists()) {
180                 setIcon(QIcon(getPixmap(imagedir, name, "png")));
181         } else {
182                 imagedir = "images/";
183                 imageLibFileSearch(imagedir, name, "png");
184                 setIcon(QIcon(getPixmap(imagedir, name, "png")));
185         }
186         if (sticky)
187                 connect(this, SIGNAL(triggered(QAction *)),
188                         this, SLOT(actionTriggered(QAction *)));
189         connect(bar, SIGNAL(iconSizeChanged(QSize)),
190                 this, SLOT(setIconSize(QSize)));
191 }
192
193 void MenuButton::mousePressEvent(QMouseEvent * e)
194 {
195         if (initialized_) {
196                 QToolButton::mousePressEvent(e);
197                 return;
198         }
199
200         initialized_ = true;
201
202         QString const label = qt_(to_ascii(tbitem_.label_));
203         ButtonMenu * m = new ButtonMenu(label, this);
204         m->setWindowTitle(label);
205         m->setTearOffEnabled(true);
206         connect(bar_, SIGNAL(updated()), m, SLOT(updateParent()));
207         ToolbarInfo const * tbinfo = guiApp->toolbars().info(tbitem_.name_);
208         if (!tbinfo) {
209                 LYXERR0("Unknown toolbar " << tbitem_.name_);
210                 return;
211         }
212         ToolbarInfo::item_iterator it = tbinfo->items.begin();
213         ToolbarInfo::item_iterator const end = tbinfo->items.end();
214         for (; it != end; ++it)
215                 if (!getStatus(it->func_).unknown())
216                         m->add(bar_->addItem(*it));
217         setMenu(m);
218
219         QToolButton::mousePressEvent(e);
220 }
221
222
223 void MenuButton::actionTriggered(QAction * action)
224 {
225         QToolButton::setDefaultAction(action);
226         setPopupMode(QToolButton::DelayedPopup);
227 }
228
229
230 void GuiToolbar::add(ToolbarItem const & item)
231 {
232         switch (item.type_) {
233         case ToolbarItem::SEPARATOR:
234                 addSeparator();
235                 break;
236         case ToolbarItem::LAYOUTS: {
237                 LayoutBox * layout = owner_.getLayoutDialog();
238                 QObject::connect(this, SIGNAL(iconSizeChanged(QSize)),
239                         layout, SLOT(setIconSize(QSize)));
240                 QAction * action = addWidget(layout);
241                 action->setVisible(true);
242                 break;
243         }
244         case ToolbarItem::MINIBUFFER:
245                 command_buffer_ = new GuiCommandBuffer(&owner_);
246                 addWidget(command_buffer_);
247                 /// \todo find a Qt4 equivalent to setHorizontalStretchable(true);
248                 //setHorizontalStretchable(true);
249                 break;
250         case ToolbarItem::TABLEINSERT: {
251                 QToolButton * tb = new QToolButton;
252                 tb->setCheckable(true);
253                 tb->setIcon(getIcon(FuncRequest(LFUN_TABULAR_INSERT), true));
254                 QString const label = qt_(to_ascii(item.label_));
255                 tb->setToolTip(label);
256                 tb->setStatusTip(label);
257                 tb->setText(label);
258                 InsertTableWidget * iv = new InsertTableWidget(owner_, tb);
259                 connect(tb, SIGNAL(clicked(bool)), iv, SLOT(show(bool)));
260                 connect(iv, SIGNAL(visible(bool)), tb, SLOT(setChecked(bool)));
261                 connect(this, SIGNAL(updated()), iv, SLOT(updateParent()));
262                 addWidget(tb);
263                 break;
264                 }
265         case ToolbarItem::ICONPALETTE:
266                 addWidget(new PaletteButton(this, item));
267                 break;
268
269         case ToolbarItem::POPUPMENU: {
270                 addWidget(new MenuButton(this, item, false));
271                 break;
272                 }
273         case ToolbarItem::STICKYPOPUPMENU: {
274                 addWidget(new MenuButton(this, item, true));
275                 break;
276                 }
277         case ToolbarItem::COMMAND: {
278                 if (!getStatus(item.func_).unknown())
279                         addAction(addItem(item));
280                 break;
281                 }
282         default:
283                 break;
284         }
285 }
286
287
288 void GuiToolbar::update(bool in_math, bool in_table, bool in_review, 
289         bool in_mathmacrotemplate)
290 {
291         if (visibility_ & Toolbars::AUTO) {
292                 bool show_it = (in_math && (visibility_ & Toolbars::MATH))
293                         || (in_table && (visibility_ & Toolbars::TABLE))
294                         || (in_review && (visibility_ & Toolbars::REVIEW))
295                         || (in_mathmacrotemplate && (visibility_ & Toolbars::MATHMACROTEMPLATE));
296                 setVisible(show_it);
297         }
298
299         // update visible toolbars only
300         if (!isVisible())
301                 return;
302
303         // This is a speed bottleneck because this is called on every keypress
304         // and update calls getStatus, which copies the cursor at least two times
305         for (int i = 0; i < actions_.size(); ++i)
306                 actions_[i]->update();
307
308         LayoutBox * layout = owner_.getLayoutDialog();
309         if (layout)
310                 layout->setEnabled(lyx::getStatus(FuncRequest(LFUN_LAYOUT)).enabled());
311
312         // emit signal
313         updated();
314 }
315
316
317 QString GuiToolbar::sessionKey() const
318 {
319         return "views/" + QString::number(owner_.id()) + "/" + objectName();
320 }
321
322
323 void GuiToolbar::saveSession() const
324 {
325         QSettings settings;
326         settings.setValue(sessionKey() + "/visibility", visibility_);
327 }
328
329
330 void GuiToolbar::restoreSession()
331 {
332         QSettings settings;
333         int const error_val = -1;
334         int visibility =
335                 settings.value(sessionKey() + "/visibility", error_val).toInt();
336         if (visibility == error_val || visibility == 0) {
337                 // This should not happen, but in case we use the defaults
338                 LYXERR0("Session settings could not be found! Defaults are used instead.");
339                 visibility = 
340                         guiApp->toolbars().defaultVisibility(fromqstr(objectName()));
341         }
342         setVisibility(visibility);
343 }
344
345
346 void GuiToolbar::toggle()
347 {
348         docstring state;
349         if (visibility_ & Toolbars::ALLOWAUTO) {
350                 if (!(visibility_ & Toolbars::AUTO)) {
351                         visibility_ |= Toolbars::AUTO;
352                         hide();
353                         state = _("auto");
354                 } else {
355                         visibility_ &= ~Toolbars::AUTO;
356                         if (isVisible()) {
357                                 hide();
358                                 state = _("off");
359                         } else {
360                                 show();
361                                 state = _("on");
362                         }
363                 }
364         } else {
365                 if (isVisible()) {
366                         hide();
367                         state = _("off");
368                 } else {
369                         show();
370                         state = _("on");
371                 }
372         }
373
374         owner_.message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
375                 qstring_to_ucs4(windowTitle()), state));
376 }
377
378 } // namespace frontend
379 } // namespace lyx
380
381 #include "moc_GuiToolbar.cpp"