]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiView.C
Remove unused symbol encoding
[lyx.git] / src / frontends / qt4 / GuiView.C
1 /**
2  * \file GuiView.C
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 Abdelrazak Younes
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "GuiView.h"
16
17 #include "GuiImplementation.h"
18 #include "GuiWorkArea.h"
19 #include "QLMenubar.h"
20 #include "QLToolbar.h"
21 #include "QCommandBuffer.h"
22 #include "qt_helpers.h"
23
24 #include "frontends/Application.h"
25 #include "frontends/Gui.h"
26 #include "frontends/WorkArea.h"
27
28 #include "support/filetools.h"
29 #include "support/convert.h"
30 #include "support/lstrings.h"
31
32 #include "BufferView.h"
33 #include "bufferlist.h"
34 #include "debug.h"
35 #include "funcrequest.h"
36 #include "lyx_cb.h"
37 #include "lyxrc.h"
38 #include "lyx_main.h"
39 #include "session.h"
40 #include "lyxfunc.h"
41 #include "MenuBackend.h"
42 #include "buffer.h"
43 #include "bufferlist.h"
44
45 #include <QAction>
46 #include <QApplication>
47 #include <QCloseEvent>
48 #include <QPixmap>
49 #include <QStatusBar>
50 #include <QToolBar>
51 #include <QTabBar>
52 #include <QDesktopWidget>
53 #include <QVBoxLayout>
54
55 #include <boost/bind.hpp>
56
57 using std::endl;
58 using std::string;
59 using std::vector;
60
61 using lyx::support::onlyFilename;
62
63 namespace lyx {
64
65 using support::subst;
66 using support::libFileSearch;
67
68 namespace frontend {
69
70 namespace {
71
72 int const statusbar_timer_value = 3000;
73
74 } // namespace anon
75
76
77 class WidgetWithTabBar : public QWidget
78 {
79 public:
80         QTabBar* tabbar;
81         WidgetWithTabBar(QWidget* w)
82         {
83                 tabbar = new QTabBar;
84                 QVBoxLayout* l = new QVBoxLayout;
85                 l->addWidget(tabbar);
86                 l->addWidget(w);
87                 l->setMargin(0);
88                 setLayout(l);
89         }
90 };
91
92 struct GuiView::GuiViewPrivate
93 {
94         typedef std::map<int, FuncRequest> FuncMap;
95         typedef std::pair<int, FuncRequest> FuncMapPair;
96         typedef std::map<string, QString> NameMap;
97         typedef std::pair<string, QString> NameMapPair;
98
99         FuncMap funcmap;
100         NameMap namemap;
101         WidgetWithTabBar* wt;
102
103         GuiViewPrivate()
104         {}
105 };
106
107 GuiView::GuiView(int id)
108         : QMainWindow(), LyXView(id), commandbuffer_(0), d(*new GuiViewPrivate)
109 {
110         setAttribute(Qt::WA_DeleteOnClose, true);
111         setAttribute(Qt::WA_QuitOnClose, true);
112
113 //      setToolButtonStyle(Qt::ToolButtonIconOnly);
114 //      setIconSize(QSize(12,12));
115
116 //      bufferview_.reset(new BufferView(this, width, height));
117
118 #ifndef Q_WS_MACX
119         //  assign an icon to main form. We do not do it under Qt/Mac,
120         //  since the icon is provided in the application bundle.
121         string const iconname = libFileSearch("images", "lyx", "xpm");
122         if (!iconname.empty())
123                 setWindowIcon(QPixmap(toqstr(iconname)));
124 #endif
125 }
126
127
128 GuiView::~GuiView()
129 {
130         delete &d;
131 }
132
133
134 void GuiView::close()
135 {
136         QMainWindow::close();
137 }
138
139
140 void GuiView::init()
141 {
142         menubar_.reset(new QLMenubar(this, menubackend));
143         QObject::connect(menuBar(), SIGNAL(triggered(QAction *)),
144                 this, SLOT(updateMenu(QAction *)));
145
146         getToolbars().init();
147
148         statusBar()->setSizeGripEnabled(false);
149
150         QObject::connect(&statusbar_timer_, SIGNAL(timeout()),
151                 this, SLOT(update_view_state_qt()));
152
153         if (!work_area_->bufferView().buffer() && !theBufferList().empty())
154                 setBuffer(theBufferList().first());
155
156         // make sure the buttons are disabled if needed
157         updateToolbars();
158         updateLayoutChoice();
159         updateMenubar();
160 }
161
162
163 void GuiView::saveGeometry()
164 {
165         // FIXME:
166         // change the ifdef to 'geometry = normalGeometry();' only
167         // when Trolltech has fixed the broken normalGeometry on X11:
168         // http://www.trolltech.com/developer/task-tracker/index_html?id=119684+&method=entry
169         // Then also the moveEvent, resizeEvent, and the
170         // code for floatingGeometry_ can be removed;
171         // adjust GuiView::setGeometry()
172 #ifdef Q_OS_WIN32
173         QRect geometry = normalGeometry();
174 #else
175         updateFloatingGeometry();
176         QRect geometry = floatingGeometry_;
177 #endif
178
179         // save windows size and position
180         Session & session = LyX::ref().session();
181         session.sessionInfo().save("WindowWidth", convert<string>(geometry.width()));
182         session.sessionInfo().save("WindowHeight", convert<string>(geometry.height()));
183         session.sessionInfo().save("WindowIsMaximized", (isMaximized() ? "yes" : "no"));
184         if (lyxrc.geometry_xysaved) {
185                 session.sessionInfo().save("WindowPosX", convert<string>(geometry.x()));
186                 session.sessionInfo().save("WindowPosY", convert<string>(geometry.y()));
187         }
188         getToolbars().saveToolbarInfo();
189 }
190                                                   
191 void GuiView::setGeometry(unsigned int width,
192                                                                   unsigned int height,
193                                                                   int posx, int posy,
194                                                                   bool maximize)
195 {
196         // only true when the -geometry option was NOT used
197         if (width != 0 && height != 0) {
198                 if (posx != -1 && posy != -1) {
199                         // if there are ever startup positioning problems 
200                         // on a virtual desktop then check the 6 lines below
201                         // http://doc.trolltech.com/4.2/qdesktopwidget.html 
202                         QDesktopWidget& dw = *qApp->desktop();
203                         QRect desk = dw.availableGeometry(dw.primaryScreen());
204                         (posx >= desk.width() ? posx = 50 : true);
205                         (posy >= desk.height()? posy = 50 : true);
206 #ifdef Q_WS_WIN
207                         // FIXME: use only setGeoemtry when Trolltech has
208                         // fixed the qt4/X11 bug
209                         QMainWindow::setGeometry(posx, posy,width, height);
210 #else
211                         resize(width, height);
212                         move(posx, posy);
213 #endif
214                 } else {
215                         resize(width, height);
216                 }
217
218                 if (maximize)
219                         setWindowState(Qt::WindowMaximized);
220         }
221         
222         show();
223
224         // For an unknown reason, the Window title update is not effective for
225         // the second windows up until it is shown on screen (Qt bug?).
226         updateWindowTitle();
227 }
228
229
230 void GuiView::updateMenu(QAction * /*action*/)
231 {
232         menubar_->update();
233 }
234
235
236 void GuiView::setWindowTitle(docstring const & t, docstring const & it)
237 {
238         QString title = windowTitle();
239         QString new_title = toqstr(t);
240         if (title != new_title) {
241                 QMainWindow::setWindowTitle(new_title);
242                 QMainWindow::setWindowIconText(toqstr(it));
243         }
244 }
245
246
247 void GuiView::addCommandBuffer(QToolBar * toolbar)
248 {
249         commandbuffer_ = new QCommandBuffer(this, *controlcommand_);
250         focus_command_buffer.connect(boost::bind(&GuiView::focus_command_widget, this));
251         toolbar->addWidget(commandbuffer_);
252 }
253
254
255 void GuiView::message(docstring const & str)
256 {
257         statusBar()->showMessage(toqstr(str));
258         statusbar_timer_.stop();
259         statusbar_timer_.start(statusbar_timer_value);
260 }
261
262
263 void GuiView::clearMessage()
264 {
265         update_view_state_qt();
266 }
267
268
269 void GuiView::focus_command_widget()
270 {
271         if (commandbuffer_)
272                 commandbuffer_->focus_command();
273 }
274
275
276 void GuiView::update_view_state_qt()
277 {
278         statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
279         statusbar_timer_.stop();
280 }
281
282 void GuiView::initTab(QWidget* workarea)
283 {
284         d.wt = new WidgetWithTabBar(workarea);
285         setCentralWidget(d.wt);
286         QObject::connect(d.wt->tabbar, SIGNAL(currentChanged(int)),
287                         this, SLOT(currentTabChanged(int)));
288 }
289
290 void GuiView::updateTab()
291 {
292         QTabBar& tb = *d.wt->tabbar;
293
294         // update when all  is done
295         tb.blockSignals(true);
296
297         typedef std::vector<string> Strings;
298         Strings const names = theBufferList().getFileNames();
299         size_t n_size = names.size();
300
301         Strings addtab;
302         // show tabs only when there is more 
303         // than one file opened
304         if (n_size > 1)
305         {
306                 for (size_t i = 0; i != n_size; i++) 
307                         if (d.namemap.find(names[i]) == d.namemap.end())
308                                 addtab.push_back(names.at(i));
309         }
310
311         for(size_t i = 0; i<addtab.size(); i++)
312         {
313                 QString tab_name = lyx::toqstr(onlyFilename(addtab.at(i))); 
314                 d.namemap.insert(GuiViewPrivate::NameMapPair(addtab.at(i), tab_name));
315                 tb.addTab(tab_name);
316         }
317
318         // check if all names showed by the tabs
319         // are also in the current bufferlist
320         Strings removetab;
321         bool notall = true;
322         if (n_size < 2)
323                 notall = false;
324         std::map<string, QString>::iterator tabit = d.namemap.begin();
325         for (;tabit != d.namemap.end(); ++tabit)
326         {
327                 bool found = false;
328                 for (size_t i = 0; i != n_size; i++) 
329                         if (tabit->first == names.at(i) && notall)
330                                 found = true;
331                 if (!found)
332                         removetab.push_back(tabit->first);
333         }
334         
335
336         // remove tabs
337         for(size_t i = 0; i<removetab.size(); i++)
338         {
339                 if (d.namemap.find(removetab.at(i)) != d.namemap.end())
340                 {
341                         tabit = d.namemap.find(removetab.at(i));
342                         for (int i = 0; i < tb.count(); i++)
343                                 if (tb.tabText(i) == tabit->second)
344                                 {
345                                         tb.removeTab(i);
346                                         break;
347                                 }
348                         d.namemap.erase(tabit);
349                 }
350         }
351
352         // rebuild func map
353         if (removetab.size() > 0 || addtab.size() > 0)
354         {
355                 d.funcmap.clear();
356                 tabit = d.namemap.begin();
357                 for (;tabit != d.namemap.end(); ++tabit)
358                 {
359                         QTabBar& tb = *d.wt->tabbar;
360                         for (int i = 0; i < tb.count(); i++)
361                         {
362                                 if (tb.tabText(i) == tabit->second)
363                                 {
364                                         FuncRequest func(LFUN_BUFFER_SWITCH, tabit->first);
365                                         d.funcmap.insert(GuiViewPrivate::FuncMapPair(i, func));
366                                         break;
367                                 }
368                         }
369                 }
370         }
371
372         // set current tab
373         if (view()->buffer()) 
374         {
375                 string cur_title = view()->buffer()->fileName();
376                 if (d.namemap.find(cur_title) != d.namemap.end())
377                 {
378                         QString tabname = d.namemap.find(cur_title)->second;
379                         for (int i = 0; i < tb.count(); i++)
380                                 if (tb.tabText(i) == tabname)
381                                 {
382                                         tb.setCurrentIndex(i);
383                                         break;
384                                 }
385                 }
386         }
387
388         tb.blockSignals(false);
389         d.wt->update();
390 }
391
392 void GuiView::currentTabChanged (int index)
393 {
394         std::map<int, FuncRequest>::const_iterator it = d.funcmap.find(index);
395         if (it != d.funcmap.end())
396                 activated(it->second);
397 }
398
399
400 void GuiView::updateStatusBar()
401 {
402         // let the user see the explicit message
403         if (statusbar_timer_.isActive())
404                 return;
405
406         statusBar()->showMessage(toqstr(theLyXFunc().viewStatusMessage()));
407 }
408
409
410 void GuiView::activated(FuncRequest const & func)
411 {
412         dispatch(func);
413 }
414
415
416 bool GuiView::hasFocus() const
417 {
418         return qApp->activeWindow() == this;
419 }
420
421
422 void  GuiView::updateFloatingGeometry()
423 {
424         if (!isMaximized())
425                 floatingGeometry_ = QRect(x(), y(), width(), height());
426 }
427
428
429 void GuiView::resizeEvent(QResizeEvent *)
430 {
431         updateFloatingGeometry();
432 }
433
434
435 void GuiView::moveEvent(QMoveEvent *)
436 {
437         updateFloatingGeometry();
438 }
439
440
441 void GuiView::closeEvent(QCloseEvent * close_event)
442 {
443         GuiImplementation & gui 
444                 = static_cast<GuiImplementation &>(theApp->gui());
445
446         vector<int> const & view_ids = gui.viewIds();
447
448         if (view_ids.size() == 1 && !theBufferList().quitWriteAll()) {
449                 close_event->ignore();
450                 return;
451         }
452
453         saveGeometry();
454         gui.unregisterView(this);
455 }
456
457
458 void GuiView::show()
459 {
460         QMainWindow::setWindowTitle(qt_("LyX"));
461         QMainWindow::show();
462         updateFloatingGeometry();
463 }
464
465
466 void GuiView::busy(bool yes)
467 {
468         static_cast<GuiWorkArea *>(work_area_)->setUpdatesEnabled(!yes);
469
470         if (yes) {
471                 work_area_->stopBlinkingCursor();
472                 QApplication::setOverrideCursor(Qt::WaitCursor);
473         }
474         else {
475                 work_area_->startBlinkingCursor();
476                 QApplication::restoreOverrideCursor();
477         }
478 }
479
480
481 Toolbars::ToolbarPtr GuiView::makeToolbar(ToolbarBackend::Toolbar const & tbb)
482 {
483         QLToolbar * Tb = new QLToolbar(tbb, *this);
484         //static QLToolbar * lastTb = 0;
485
486         if (tbb.flags & ToolbarBackend::TOP) {
487                         addToolBar(Qt::TopToolBarArea, Tb);
488                         addToolBarBreak(Qt::TopToolBarArea);
489         }
490         if (tbb.flags & ToolbarBackend::BOTTOM) {
491                 addToolBar(Qt::BottomToolBarArea, Tb);
492                 /*
493                 // Qt bug:
494                 // http://www.trolltech.com/developer/task-tracker/index_html?id=137015&method=entry
495                 // Doesn't work because the toolbar will evtl. be hidden.
496                 if (lastTb)
497                         insertToolBarBreak(lastTb);
498                 lastTb = Tb;
499                 */
500         }
501         if (tbb.flags & ToolbarBackend::LEFT) {
502                 addToolBar(Qt::LeftToolBarArea, Tb);
503         }
504         if (tbb.flags & ToolbarBackend::RIGHT) {
505                 addToolBar(Qt::RightToolBarArea, Tb);
506         }
507
508         return Toolbars::ToolbarPtr(Tb);
509 }
510
511 } // namespace frontend
512 } // namespace lyx
513
514 #include "GuiView_moc.cpp"