]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiToolbar.cpp
If we are in a closeEvent, we don't want to close all buffers, because these may...
[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         setIcon(QIcon(getPixmap("images/math/", toqstr(tbitem_.name_), "png")));
179         if (sticky)
180                 connect(this, SIGNAL(triggered(QAction *)),
181                         this, SLOT(actionTriggered(QAction *)));
182         connect(bar, SIGNAL(iconSizeChanged(QSize)),
183                 this, SLOT(setIconSize(QSize)));
184 }
185
186 void MenuButton::mousePressEvent(QMouseEvent * e)
187 {
188         if (initialized_) {
189                 QToolButton::mousePressEvent(e);
190                 return;
191         }
192
193         initialized_ = true;
194
195         QString const label = qt_(to_ascii(tbitem_.label_));
196         ButtonMenu * m = new ButtonMenu(label, this);
197         m->setWindowTitle(label);
198         m->setTearOffEnabled(true);
199         connect(bar_, SIGNAL(updated()), m, SLOT(updateParent()));
200         ToolbarInfo const * tbinfo = guiApp->toolbars().info(tbitem_.name_);
201         if (!tbinfo) {
202                 LYXERR0("Unknown toolbar " << tbitem_.name_);
203                 return;
204         }
205         ToolbarInfo::item_iterator it = tbinfo->items.begin();
206         ToolbarInfo::item_iterator const end = tbinfo->items.end();
207         for (; it != end; ++it)
208                 if (!getStatus(it->func_).unknown())
209                         m->add(bar_->addItem(*it));
210         setMenu(m);
211
212         QToolButton::mousePressEvent(e);
213 }
214
215
216 void MenuButton::actionTriggered(QAction * action)
217 {
218         QToolButton::setDefaultAction(action);
219         setPopupMode(QToolButton::DelayedPopup);
220 }
221
222
223 void GuiToolbar::add(ToolbarItem const & item)
224 {
225         switch (item.type_) {
226         case ToolbarItem::SEPARATOR:
227                 addSeparator();
228                 break;
229         case ToolbarItem::LAYOUTS: {
230                 LayoutBox * layout = owner_.getLayoutDialog();
231                 QObject::connect(this, SIGNAL(iconSizeChanged(QSize)),
232                         layout, SLOT(setIconSize(QSize)));
233                 QAction * action = addWidget(layout);
234                 action->setVisible(true);
235                 break;
236         }
237         case ToolbarItem::MINIBUFFER:
238                 command_buffer_ = new GuiCommandBuffer(&owner_);
239                 addWidget(command_buffer_);
240                 /// \todo find a Qt4 equivalent to setHorizontalStretchable(true);
241                 //setHorizontalStretchable(true);
242                 break;
243         case ToolbarItem::TABLEINSERT: {
244                 QToolButton * tb = new QToolButton;
245                 tb->setCheckable(true);
246                 tb->setIcon(getIcon(FuncRequest(LFUN_TABULAR_INSERT), true));
247                 QString const label = qt_(to_ascii(item.label_));
248                 tb->setToolTip(label);
249                 tb->setStatusTip(label);
250                 tb->setText(label);
251                 InsertTableWidget * iv = new InsertTableWidget(owner_, tb);
252                 connect(tb, SIGNAL(clicked(bool)), iv, SLOT(show(bool)));
253                 connect(iv, SIGNAL(visible(bool)), tb, SLOT(setChecked(bool)));
254                 connect(this, SIGNAL(updated()), iv, SLOT(updateParent()));
255                 addWidget(tb);
256                 break;
257                 }
258         case ToolbarItem::ICONPALETTE:
259                 addWidget(new PaletteButton(this, item));
260                 break;
261
262         case ToolbarItem::POPUPMENU: {
263                 addWidget(new MenuButton(this, item, false));
264                 break;
265                 }
266         case ToolbarItem::STICKYPOPUPMENU: {
267                 addWidget(new MenuButton(this, item, true));
268                 break;
269                 }
270         case ToolbarItem::COMMAND: {
271                 if (!getStatus(item.func_).unknown())
272                         addAction(addItem(item));
273                 break;
274                 }
275         default:
276                 break;
277         }
278 }
279
280
281 void GuiToolbar::update(bool in_math, bool in_table, bool in_review, 
282         bool in_mathmacrotemplate)
283 {
284         if (visibility_ & Toolbars::AUTO) {
285                 bool show_it = (in_math && (visibility_ & Toolbars::MATH))
286                         || (in_table && (visibility_ & Toolbars::TABLE))
287                         || (in_review && (visibility_ & Toolbars::REVIEW))
288                         || (in_mathmacrotemplate && (visibility_ & Toolbars::MATHMACROTEMPLATE));
289                 setVisible(show_it);
290         }
291
292         // update visible toolbars only
293         if (!isVisible())
294                 return;
295
296         // This is a speed bottleneck because this is called on every keypress
297         // and update calls getStatus, which copies the cursor at least two times
298         for (int i = 0; i < actions_.size(); ++i)
299                 actions_[i]->update();
300
301         LayoutBox * layout = owner_.getLayoutDialog();
302         if (layout)
303                 layout->setEnabled(lyx::getStatus(FuncRequest(LFUN_LAYOUT)).enabled());
304
305         // emit signal
306         updated();
307 }
308
309
310 QString GuiToolbar::sessionKey() const
311 {
312         return "views/" + QString::number(owner_.id()) + "/" + objectName();
313 }
314
315
316 void GuiToolbar::saveSession() const
317 {
318         QSettings settings;
319         settings.setValue(sessionKey() + "/visibility", visibility_);
320 }
321
322
323 void GuiToolbar::restoreSession()
324 {
325         QSettings settings;
326         setVisibility(settings.value(sessionKey() + "/visibility").toInt());
327 }
328
329
330 void GuiToolbar::toggle()
331 {
332         docstring state;
333         if (allowauto_) {
334                 if (!(visibility_ & Toolbars::AUTO)) {
335                         visibility_ |= Toolbars::AUTO;
336                         hide();
337                         state = _("auto");
338                 } else {
339                         visibility_ &= ~Toolbars::AUTO;
340                         if (isVisible()) {
341                                 hide();
342                                 state = _("off");
343                         } else {
344                                 show();
345                                 state = _("on");
346                         }
347                 }
348         } else {
349                 if (isVisible()) {
350                         hide();
351                         state = _("off");
352                 } else {
353                         show();
354                         state = _("on");
355                 }
356         }
357
358         owner_.message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
359                 qstring_to_ucs4(windowTitle()), state));
360 }
361
362 } // namespace frontend
363 } // namespace lyx
364
365 #include "moc_GuiToolbar.cpp"