]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/QLToolbar.cpp
delete unneeded Menubar virtual interface.
[lyx.git] / src / frontends / qt4 / QLToolbar.cpp
1 /**
2  * \file qt4/QLToolbar.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 Abdelrazak Younes
11  *
12  * Full author contact details are available in file CREDITS.
13  */
14
15 #include <config.h>
16
17 #include "Buffer.h"
18 #include "BufferParams.h"
19 #include "debug.h"
20 #include "FuncRequest.h"
21 #include "FuncStatus.h"
22 #include "gettext.h"
23 #include "LyXFunc.h"
24 #include "IconPalette.h"
25
26 #include "GuiView.h"
27 #include "QLToolbar.h"
28 #include "LyXAction.h"
29 #include "Action.h"
30 #include "qt_helpers.h"
31 #include "InsertTableWidget.h"
32 #include "support/filetools.h"
33 #include "support/lstrings.h"
34 #include "controllers/ControlMath.h"
35 #include "ToolbarBackend.h"
36
37 #include <QComboBox>
38 #include <QToolBar>
39 #include <QToolButton>
40 #include <QAction>
41 #include <QPixmap>
42
43 namespace lyx {
44
45 using std::string;
46 using std::endl;
47 using support::FileName;
48 using support::libFileSearch;
49 using support::subst;
50
51
52 using support::libFileSearch;
53 using support::subst;
54
55 namespace frontend {
56
57 namespace {
58
59 TextClass const & getTextClass(LyXView const & lv)
60 {
61         return lv.buffer()->params().getTextClass();
62 }
63
64
65 } // namespace anon
66
67
68 QLayoutBox::QLayoutBox(QToolBar * toolbar, GuiView & owner)
69         : owner_(owner)
70 {
71         combo_ = new QComboBox;
72         combo_->setSizeAdjustPolicy(QComboBox::AdjustToContents);
73         combo_->setFocusPolicy(Qt::ClickFocus);
74         combo_->setMinimumWidth(combo_->sizeHint().width());
75         combo_->setMaxVisibleItems(100);
76
77         QObject::connect(combo_, SIGNAL(activated(const QString &)),
78                          this, SLOT(selected(const QString &)));
79
80         toolbar->addWidget(combo_);
81 }
82
83
84 void QLayoutBox::set(docstring const & layout)
85 {
86         TextClass const & tc = getTextClass(owner_);
87
88         QString const & name = toqstr(translateIfPossible(tc[layout]->name()));
89
90         int i = 0;
91         for (; i < combo_->count(); ++i) {
92                 if (name == combo_->itemText(i))
93                         break;
94         }
95
96         if (i == combo_->count()) {
97                 lyxerr << "Trying to select non existent layout type "
98                         << fromqstr(name) << endl;
99                 return;
100         }
101
102         combo_->setCurrentIndex(i);
103 }
104
105
106 void QLayoutBox::update()
107 {
108         TextClass const & tc = getTextClass(owner_);
109
110         combo_->setUpdatesEnabled(false);
111
112         combo_->clear();
113
114         TextClass::const_iterator it = tc.begin();
115         TextClass::const_iterator const end = tc.end();
116         for (; it != end; ++it) {
117                 // ignore obsolete entries
118                 if ((*it)->obsoleted_by().empty())
119                         combo_->addItem(toqstr(translateIfPossible((*it)->name())));
120         }
121
122         // needed to recalculate size hint
123         combo_->hide();
124         combo_->setMinimumWidth(combo_->sizeHint().width());
125         combo_->show();
126
127         combo_->setUpdatesEnabled(true);
128         combo_->update();
129 }
130
131
132 void QLayoutBox::clear()
133 {
134         combo_->clear();
135 }
136
137
138 void QLayoutBox::open()
139 {
140         combo_->showPopup();
141 }
142
143
144 void QLayoutBox::setEnabled(bool enable)
145 {
146         // Workaround for Qt bug where setEnabled(true) closes
147         // the popup
148         if (enable != combo_->isEnabled())
149                 combo_->setEnabled(enable);
150 }
151
152
153 void QLayoutBox::selected(const QString & str)
154 {
155         owner_.setFocus();
156
157         layoutSelected(owner_, qstring_to_ucs4(str));
158 }
159
160
161 QLToolbar::QLToolbar(ToolbarInfo const & tbinfo, GuiView & owner)
162         : QToolBar(qt_(tbinfo.gui_name), &owner), owner_(owner)
163 {
164         // give visual separation between adjacent toolbars
165         addSeparator();
166
167         // TODO: save toolbar position
168         setMovable(true);
169
170         ToolbarInfo::item_iterator it = tbinfo.items.begin();
171         ToolbarInfo::item_iterator end = tbinfo.items.end();
172         for (; it != end; ++it)
173                 add(*it);
174 }
175
176
177 void QLToolbar::add(ToolbarItem const & item)
178 {
179         switch (item.type_) {
180         case ToolbarItem::SEPARATOR:
181                 addSeparator();
182                 break;
183         case ToolbarItem::LAYOUTS:
184                 layout_.reset(new QLayoutBox(this, owner_));
185                 break;
186         case ToolbarItem::MINIBUFFER:
187                 owner_.addCommandBuffer(this);
188                 /// \todo find a Qt4 equivalent to setHorizontalStretchable(true);
189                 //setHorizontalStretchable(true);
190                 break;
191         case ToolbarItem::TABLEINSERT: {
192                 QToolButton * tb = new QToolButton;
193                 tb->setCheckable(true);
194                 tb->setIcon(QPixmap(toqstr(getIcon(FuncRequest(LFUN_TABULAR_INSERT)))));
195                 tb->setToolTip(qt_(to_ascii(item.label_)));
196                 tb->setStatusTip(qt_(to_ascii(item.label_)));
197                 tb->setText(qt_(to_ascii(item.label_)));
198                 InsertTableWidget * iv = new InsertTableWidget(owner_, tb);
199                 connect(tb, SIGNAL(clicked(bool)), iv, SLOT(show(bool)));
200                 connect(iv, SIGNAL(visible(bool)), tb, SLOT(setChecked(bool)));
201                 connect(this, SIGNAL(updated()), iv, SLOT(updateParent()));
202                 addWidget(tb);
203                 break;
204                 }
205         case ToolbarItem::ICONPALETTE: {
206                 QToolButton * tb = new QToolButton(this);
207                 tb->setToolTip(qt_(to_ascii(item.label_)));
208                 tb->setStatusTip(qt_(to_ascii(item.label_)));
209                 tb->setText(qt_(to_ascii(item.label_)));
210                 connect(this, SIGNAL(iconSizeChanged(const QSize &)),
211                         tb, SLOT(setIconSize(const QSize &)));
212                 IconPalette * panel = new IconPalette(tb);
213                 panel->setWindowTitle(qt_(to_ascii(item.label_)));
214                 connect(this, SIGNAL(updated()), panel, SLOT(updateParent()));
215                 ToolbarInfo const * tbinfo = toolbarbackend.getDefinedToolbarInfo(item.name_);
216                 if (!tbinfo) {
217                         lyxerr << "Unknown toolbar " << item.name_ << endl;
218                         break;
219                 }
220                 ToolbarInfo::item_iterator it = tbinfo->items.begin();
221                 ToolbarInfo::item_iterator const end = tbinfo->items.end();
222                 for (; it != end; ++it)
223                         if (!getStatus(it->func_).unknown()) {
224                                 Action * action = new Action(owner_,
225                                         getIcon(it->func_),
226                                         it->label_,
227                                         it->func_,
228                                         it->label_);
229                                 panel->addButton(action);
230                                 ActionVector.push_back(action);
231                                 // use the icon of first action for the toolbar button
232                                 if (it == tbinfo->items.begin())
233                                         tb->setIcon(QPixmap(getIcon(it->func_).c_str()));
234                         }
235                 tb->setCheckable(true);
236                 connect(tb, SIGNAL(clicked(bool)), panel, SLOT(setVisible(bool)));
237                 connect(panel, SIGNAL(visible(bool)), tb, SLOT(setChecked(bool)));
238                 addWidget(tb);
239                 break;
240                 }
241         case ToolbarItem::POPUPMENU: {
242                 QToolButton * tb = new QToolButton;
243                 tb->setPopupMode(QToolButton::InstantPopup);
244                 tb->setToolTip(qt_(to_ascii(item.label_)));
245                 tb->setStatusTip(qt_(to_ascii(item.label_)));
246                 tb->setText(qt_(to_ascii(item.label_)));
247                 FileName icon_path = libFileSearch("images/math", item.name_, "xpm");
248                 tb->setIcon(QIcon(toqstr(icon_path.absFilename())));
249                 connect(this, SIGNAL(iconSizeChanged(const QSize &)),
250                         tb, SLOT(setIconSize(const QSize &)));
251
252                 ButtonMenu * m = new ButtonMenu(qt_(to_ascii(item.label_)), tb);
253                 m->setWindowTitle(qt_(to_ascii(item.label_)));
254                 m->setTearOffEnabled(true);
255                 connect(this, SIGNAL(updated()), m, SLOT(updateParent()));
256                 ToolbarInfo const * tbinfo = toolbarbackend.getDefinedToolbarInfo(item.name_);
257                 if (!tbinfo) {
258                         lyxerr << "Unknown toolbar " << item.name_ << endl;
259                         break;
260                 }
261                 ToolbarInfo::item_iterator it = tbinfo->items.begin();
262                 ToolbarInfo::item_iterator const end = tbinfo->items.end();
263                 for (; it != end; ++it)
264                         if (!getStatus(it->func_).unknown()) {
265                                 Action * action = new Action(owner_,
266                                         getIcon(it->func_, false),
267                                         it->label_,
268                                         it->func_,
269                                         it->label_);
270                                 m->add(action);
271                                 ActionVector.push_back(action);
272                         }
273                 tb->setMenu(m);
274                 addWidget(tb);
275                 break;
276                 }
277         case ToolbarItem::COMMAND: {
278                 if (getStatus(item.func_).unknown())
279                         break;
280
281                 Action * action = new Action(owner_,
282                         getIcon(item.func_),
283                         item.label_,
284                         item.func_,
285                         item.label_);
286                 addAction(action);
287                 ActionVector.push_back(action);
288                 break;
289                 }
290         default:
291                 break;
292         }
293 }
294
295
296 void QLToolbar::hide(bool)
297 {
298         QToolBar::hide();
299 }
300
301
302 void QLToolbar::show(bool)
303 {
304         QToolBar::show();
305 }
306
307
308 bool QLToolbar::isVisible() const
309 {
310         return QToolBar::isVisible();
311 }
312
313
314 void QLToolbar::saveInfo(ToolbarSection::ToolbarInfo & tbinfo)
315 {
316         // if tbinfo.state == auto *do not* set on/off
317         if (tbinfo.state != ToolbarSection::ToolbarInfo::AUTO) {
318                 if (QLToolbar::isVisible())
319                         tbinfo.state = ToolbarSection::ToolbarInfo::ON;
320                 else
321                         tbinfo.state = ToolbarSection::ToolbarInfo::OFF;
322         }
323         //
324         // no need to save it here.
325         Qt::ToolBarArea loc = owner_.toolBarArea(this);
326
327         if (loc == Qt::TopToolBarArea)
328                 tbinfo.location = ToolbarSection::ToolbarInfo::TOP;
329         else if (loc == Qt::BottomToolBarArea)
330                 tbinfo.location = ToolbarSection::ToolbarInfo::BOTTOM;
331         else if (loc == Qt::RightToolBarArea)
332                 tbinfo.location = ToolbarSection::ToolbarInfo::RIGHT;
333         else if (loc == Qt::LeftToolBarArea)
334                 tbinfo.location = ToolbarSection::ToolbarInfo::LEFT;
335         else
336                 tbinfo.location = ToolbarSection::ToolbarInfo::NOTSET;
337
338         // save toolbar position. They are not used to restore toolbar position
339         // now because move(x,y) does not work for toolbar.
340         tbinfo.posx = pos().x();
341         tbinfo.posy = pos().y();
342 }
343
344
345 void QLToolbar::update()
346 {
347         // This is a speed bottleneck because this is called on every keypress
348         // and update calls getStatus, which copies the cursor at least two times
349         for (size_t i = 0; i < ActionVector.size(); ++i)
350                 ActionVector[i]->update();
351
352         // emit signal
353         updated();
354 }
355
356
357 string const getIcon(FuncRequest const & f, bool unknown)
358 {
359         using frontend::find_xpm;
360
361         string fullname;
362
363         switch (f.action) {
364         case LFUN_MATH_INSERT:
365                 if (!f.argument().empty())
366                         fullname = find_xpm(to_utf8(f.argument()).substr(1));
367                 break;
368         case LFUN_MATH_DELIM:
369         case LFUN_MATH_BIGDELIM:
370                 fullname = find_xpm(to_utf8(f.argument()));
371                 break;
372         default:
373                 string const name = lyxaction.getActionName(f.action);
374                 string xpm_name(name);
375
376                 if (!f.argument().empty())
377                         xpm_name = subst(name + ' ' + to_utf8(f.argument()), ' ', '_');
378
379                 fullname = libFileSearch("images", xpm_name, "xpm").absFilename();
380
381                 if (fullname.empty()) {
382                         // try without the argument
383                         fullname = libFileSearch("images", name, "xpm").absFilename();
384                 }
385         }
386
387         if (!fullname.empty()) {
388                 LYXERR(Debug::GUI) << "Full icon name is `"
389                                    << fullname << '\'' << endl;
390                 return fullname;
391         }
392
393         LYXERR(Debug::GUI) << "Cannot find icon for command \""
394                            << lyxaction.getActionName(f.action)
395                            << '(' << to_utf8(f.argument()) << ")\"" << endl;
396         if (unknown)
397                 return libFileSearch("images", "unknown", "xpm").absFilename();
398         else
399                 return string();
400 }
401
402
403 } // namespace frontend
404 } // namespace lyx
405
406 #include "QLToolbar_moc.cpp"