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