]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiToolbar.cpp
Add a function to translate QStrings
[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.empty())
103                 text += " [" + toqstr(bindings.begin()->print(KeySequence::ForGui)) + "]";
104
105         Action * act = new Action(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)
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         QStringList imagedirs;
178         imagedirs << "images/math/" << "images/";
179         for (int i = 0; i < imagedirs.size(); ++i) { 
180                 QString imagedir = imagedirs.at(i);
181                 FileName const fname = imageLibFileSearch(imagedir, name, "png");
182                 if (fname.exists()) {
183                         setIcon(QIcon(getPixmap(imagedir, name, "png")));
184                         break;
185                 }
186         }
187         if (sticky)
188                 connect(this, SIGNAL(triggered(QAction *)),
189                         this, SLOT(actionTriggered(QAction *)));
190         connect(bar, SIGNAL(iconSizeChanged(QSize)),
191                 this, SLOT(setIconSize(QSize)));
192         initialize();
193 }
194
195
196 void MenuButton::initialize()
197 {
198         QString const label = qt_(to_ascii(tbitem_.label_));
199         ButtonMenu * m = new ButtonMenu(label, this);
200         m->setWindowTitle(label);
201         m->setTearOffEnabled(true);
202         connect(bar_, SIGNAL(updated()), m, SLOT(updateParent()));
203         connect(bar_, SIGNAL(updated()), this, SLOT(updateTriggered()));
204         ToolbarInfo const * tbinfo = guiApp->toolbars().info(tbitem_.name_);
205         if (!tbinfo) {
206                 LYXERR0("Unknown toolbar " << tbitem_.name_);
207                 return;
208         }
209         ToolbarInfo::item_iterator it = tbinfo->items.begin();
210         ToolbarInfo::item_iterator const end = tbinfo->items.end();
211         for (; it != end; ++it)
212                 if (!getStatus(it->func_).unknown())
213                         m->add(bar_->addItem(*it));
214         setMenu(m);
215 }
216
217
218 void MenuButton::actionTriggered(QAction * action)
219 {
220         QToolButton::setDefaultAction(action);
221         setPopupMode(QToolButton::DelayedPopup);
222 }
223
224
225 void MenuButton::updateTriggered()
226 {
227         if (!menu())
228                 return;
229
230         bool enabled = false;
231         QList<QAction *> acts = menu()->actions();
232         for (int i = 0; i < acts.size(); ++i)
233                 if (acts[i]->isEnabled()) {
234                         enabled = true;
235                         break;
236                 }
237         // Enable the MenuButton if at least one menu item is enabled
238         setEnabled(enabled);
239         // If a disabled item is default, switch to InstantPopup
240         // (this can happen if a user selects e.g. DVI and then
241         // turns non-TeX fonts on)
242         if (defaultAction() && !defaultAction()->isEnabled())
243                 setPopupMode(QToolButton::InstantPopup);
244 }
245
246
247 void GuiToolbar::add(ToolbarItem const & item)
248 {
249         switch (item.type_) {
250         case ToolbarItem::SEPARATOR:
251                 addSeparator();
252                 break;
253         case ToolbarItem::LAYOUTS: {
254                 LayoutBox * layout = owner_.getLayoutDialog();
255                 QObject::connect(this, SIGNAL(iconSizeChanged(QSize)),
256                         layout, SLOT(setIconSize(QSize)));
257                 QAction * action = addWidget(layout);
258                 action->setVisible(true);
259                 break;
260         }
261         case ToolbarItem::MINIBUFFER:
262                 command_buffer_ = new GuiCommandBuffer(&owner_);
263                 addWidget(command_buffer_);
264                 /// \todo find a Qt4 equivalent to setHorizontalStretchable(true);
265                 //setHorizontalStretchable(true);
266                 break;
267         case ToolbarItem::TABLEINSERT: {
268                 QToolButton * tb = new QToolButton;
269                 tb->setCheckable(true);
270                 tb->setIcon(getIcon(FuncRequest(LFUN_TABULAR_INSERT), true));
271                 QString const label = qt_(to_ascii(item.label_));
272                 tb->setToolTip(label);
273                 tb->setStatusTip(label);
274                 tb->setText(label);
275                 InsertTableWidget * iv = new InsertTableWidget(tb);
276                 connect(tb, SIGNAL(clicked(bool)), iv, SLOT(show(bool)));
277                 connect(iv, SIGNAL(visible(bool)), tb, SLOT(setChecked(bool)));
278                 connect(this, SIGNAL(updated()), iv, SLOT(updateParent()));
279                 addWidget(tb);
280                 break;
281                 }
282         case ToolbarItem::ICONPALETTE:
283                 addWidget(new PaletteButton(this, item));
284                 break;
285
286         case ToolbarItem::POPUPMENU: {
287                 addWidget(new MenuButton(this, item, false));
288                 break;
289                 }
290         case ToolbarItem::STICKYPOPUPMENU: {
291                 addWidget(new MenuButton(this, item, true));
292                 break;
293                 }
294         case ToolbarItem::COMMAND: {
295                 if (!getStatus(item.func_).unknown())
296                         addAction(addItem(item));
297                 break;
298                 }
299         default:
300                 break;
301         }
302 }
303
304
305 void GuiToolbar::update(bool in_math, bool in_table, bool in_review, 
306         bool in_mathmacrotemplate, bool in_ipa)
307 {
308         if (visibility_ & Toolbars::AUTO) {
309                 bool show_it = (in_math && (visibility_ & Toolbars::MATH))
310                         || (in_table && (visibility_ & Toolbars::TABLE))
311                         || (in_review && (visibility_ & Toolbars::REVIEW))
312                         || (in_mathmacrotemplate && (visibility_ & Toolbars::MATHMACROTEMPLATE))
313                         || (in_ipa && (visibility_ & Toolbars::IPA));
314                 setVisible(show_it);
315         }
316
317         // update visible toolbars only
318         if (!isVisible())
319                 return;
320
321         // This is a speed bottleneck because this is called on every keypress
322         // and update calls getStatus, which copies the cursor at least two times
323         for (int i = 0; i < actions_.size(); ++i)
324                 actions_[i]->update();
325
326         LayoutBox * layout = owner_.getLayoutDialog();
327         if (layout)
328                 layout->setEnabled(lyx::getStatus(FuncRequest(LFUN_LAYOUT)).enabled());
329
330         // emit signal
331         updated();
332 }
333
334
335 QString GuiToolbar::sessionKey() const
336 {
337         return "views/" + QString::number(owner_.id()) + "/" + objectName();
338 }
339
340
341 void GuiToolbar::saveSession() const
342 {
343         QSettings settings;
344         settings.setValue(sessionKey() + "/visibility", visibility_);
345 }
346
347
348 void GuiToolbar::restoreSession()
349 {
350         QSettings settings;
351         int const error_val = -1;
352         int visibility =
353                 settings.value(sessionKey() + "/visibility", error_val).toInt();
354         if (visibility == error_val || visibility == 0) {
355                 // This should not happen, but in case we use the defaults
356                 LYXERR(Debug::GUI, "Session settings could not be found! Defaults are used instead.");
357                 visibility = 
358                         guiApp->toolbars().defaultVisibility(fromqstr(objectName()));
359         }
360         setVisibility(visibility);
361 }
362
363
364 void GuiToolbar::toggle()
365 {
366         docstring state;
367         if (visibility_ & Toolbars::ALLOWAUTO) {
368                 if (!(visibility_ & Toolbars::AUTO)) {
369                         visibility_ |= Toolbars::AUTO;
370                         hide();
371                         state = _("auto");
372                 } else {
373                         visibility_ &= ~Toolbars::AUTO;
374                         if (isVisible()) {
375                                 hide();
376                                 state = _("off");
377                         } else {
378                                 show();
379                                 state = _("on");
380                         }
381                 }
382         } else {
383                 if (isVisible()) {
384                         hide();
385                         state = _("off");
386                 } else {
387                         show();
388                         state = _("on");
389                 }
390         }
391
392         owner_.message(bformat(_("Toolbar \"%1$s\" state set to %2$s"),
393                 qstring_to_ucs4(windowTitle()), state));
394 }
395
396 } // namespace frontend
397 } // namespace lyx
398
399 #include "moc_GuiToolbar.cpp"