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