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