]> git.lyx.org Git - features.git/blobdiff - src/frontends/qt4/GuiView.cpp
move updateLables to buffer
[features.git] / src / frontends / qt4 / GuiView.cpp
index e944475f5f2ca9fc9cb943987a17197ba612d3cd..be58dc71c066165eefb330cb48ca741d3f2de46a 100644 (file)
@@ -3,10 +3,10 @@
  * This file is part of LyX, the document processor.
  * Licence details can be found in the file COPYING.
  *
- * \author Lars Gullik Bjønnes
+ * \author Lars Gullik Bjønnes
  * \author John Levon
  * \author Abdelrazak Younes
- * \author Peter Kümmel
+ * \author Peter Kümmel
  *
  * Full author contact details are available in file CREDITS.
  */
@@ -142,6 +142,7 @@ private:
        QPixmap splash_;
 };
 
+
 /// Toolbar store providing access to individual toolbars by name.
 typedef std::map<std::string, GuiToolbar *> ToolbarMap;
 
@@ -153,13 +154,14 @@ typedef boost::shared_ptr<Dialog> DialogPtr;
 struct GuiView::GuiViewPrivate
 {
        GuiViewPrivate()
-               : current_work_area_(0), layout_(0), autosave_timeout_(5000),
+               : current_work_area_(0), current_main_work_area_(0),
+               layout_(0), autosave_timeout_(5000),
                in_show_(false)
        {
                // hardcode here the platform specific icon size
-               smallIconSize = 14;     // scaling problems
-               normalIconSize = 20;    // ok, default
-               bigIconSize = 26;               // better for some math icons
+               smallIconSize = 14;  // scaling problems
+               normalIconSize = 20; // ok, default
+               bigIconSize = 26;    // better for some math icons
 
                splitter_ = new QSplitter;
                bg_widget_ = new BackgroundWidget;
@@ -233,7 +235,7 @@ struct GuiView::GuiViewPrivate
 
                for (int i = 0; i != splitter_->count(); ++i) {
                        TabWorkArea * twa = tabWorkArea(i);
-                       if (current_work_area_ == twa->currentWorkArea())
+                       if (current_main_work_area_ == twa->currentWorkArea())
                                return twa;
                }
 
@@ -243,6 +245,7 @@ struct GuiView::GuiViewPrivate
 
 public:
        GuiWorkArea * current_work_area_;
+       GuiWorkArea * current_main_work_area_;
        QSplitter * splitter_;
        QStackedWidget * stack_widget_;
        BackgroundWidget * bg_widget_;
@@ -284,6 +287,7 @@ GuiView::GuiView(int id)
        : d(*new GuiViewPrivate), id_(id), closing_(false)
 {
        // GuiToolbars *must* be initialised before the menu bar.
+       normalSizedIcons(); // at least on Mac the default is 32 otherwise, which is huge
        constructToolbars();
 
        // set ourself as the current view. This is needed for the menu bar
@@ -329,10 +333,11 @@ GuiView::GuiView(int id)
                        return;
        }
 
-       // No session handling, default to a sane size.
+       // no session handling, default to a sane size.
        setGeometry(50, 50, 690, 510);
        initToolbars();
-       // This enables to clear session data if any.
+
+       // clear session data if any.
        QSettings settings;
        settings.remove("views");
 }
@@ -347,15 +352,16 @@ GuiView::~GuiView()
 void GuiView::saveLayout() const
 {
        QSettings settings;
-       QString const key = "views/" + QString::number(id_);
+       settings.beginGroup("views");
+       settings.beginGroup(QString::number(id_));
 #ifdef Q_WS_X11
-       settings.setValue(key + "/pos", pos());
-       settings.setValue(key + "/size", size());
+       settings.setValue("pos", pos());
+       settings.setValue("size", size());
 #else
-       settings.setValue(key + "/geometry", saveGeometry());
+       settings.setValue("geometry", saveGeometry());
 #endif
-       settings.setValue(key + "/layout", saveState(0));
-       settings.setValue(key + "/icon_size", iconSize());
+       settings.setValue("layout", saveState(0));
+       settings.setValue("icon_size", iconSize());
 }
 
 
@@ -382,11 +388,8 @@ bool GuiView::restoreLayout()
        setLayoutDirection(qApp->layoutDirection());
 
        // Allow the toc and view-source dock widget to be restored if needed.
-       Dialog * tmp;
-       if ((tmp = findOrBuild("toc", true)))
-               tmp->showView();
-       if ((tmp = findOrBuild("view-source", true)))
-               tmp->showView();
+       findOrBuild("toc", true);
+       findOrBuild("view-source", true);
 
        if (!restoreState(settings.value("layout").toByteArray(), 0))
                initToolbars();
@@ -481,12 +484,13 @@ TocModels & GuiView::tocModels()
 
 void GuiView::setFocus()
 {
+       LYXERR(Debug::DEBUG, "GuiView::setFocus()" << this);
        // Make sure LyXFunc points to the correct view.
+       guiApp->setCurrentView(this);
        theLyXFunc().setLyXView(this);
+       QMainWindow::setFocus();
        if (d.current_work_area_)
                d.current_work_area_->setFocus();
-       else
-               QWidget::setFocus();
 }
 
 
@@ -510,15 +514,20 @@ void GuiView::showEvent(QShowEvent * e)
 }
 
 
+/** Destroy only all tabbed WorkAreas. Destruction of other WorkAreas
+ ** is responsibility of the container (e.g., dialog)
+ **/
 void GuiView::closeEvent(QCloseEvent * close_event)
 {
+       LYXERR(Debug::DEBUG, "GuiView::closeEvent()");
        closing_ = true;
 
        // it can happen that this event arrives without selecting the view,
        // e.g. when clicking the close button on a background window.
-       theLyXFunc().setLyXView(this);
-
-       while (Buffer * b = buffer()) {
+       setFocus();
+       setCurrentWorkArea(currentMainWorkArea());
+       while (GuiWorkArea * wa = currentMainWorkArea()) {
+               Buffer * b = &wa->bufferView().buffer();
                if (b->parent()) {
                        // This is a child document, just close the tab after saving
                        // but keep the file loaded.
@@ -527,7 +536,7 @@ void GuiView::closeEvent(QCloseEvent * close_event)
                                close_event->ignore();
                                return;
                        }
-                       removeWorkArea(d.current_work_area_);
+               removeWorkArea(wa);
                        continue;
                }
 
@@ -543,12 +552,13 @@ void GuiView::closeEvent(QCloseEvent * close_event)
 
                                // This buffer is also opened in another view, so
                                // close the associated work area...
-                               removeWorkArea(d.current_work_area_);
+                               removeWorkArea(wa);
                                // ... but don't close the buffer.
                                b = 0;
                                break;
                        }
                }
+               // closeBuffer() needs buffer workArea still alive and set as currrent one, and destroys it
                if (b && !closeBuffer(*b, true)) {
                        closing_ = false;
                        close_event->ignore();
@@ -597,7 +607,7 @@ void GuiView::dragEnterEvent(QDragEnterEvent * event)
 }
 
 
-void GuiView::dropEvent(QDropEvent* event)
+void GuiView::dropEvent(QDropEvent * event)
 {
        QList<QUrl> files = event->mimeData()->urls();
        if (files.isEmpty())
@@ -607,8 +617,13 @@ void GuiView::dropEvent(QDropEvent* event)
        for (int i = 0; i != files.size(); ++i) {
                string const file = os::internal_path(fromqstr(
                        files.at(i).toLocalFile()));
-               if (!file.empty())
-                       lyx::dispatch(FuncRequest(LFUN_FILE_OPEN, file));
+               if (!file.empty()) {
+                       // Asynchronously post the event. DropEvent usually come
+                       // from the BufferView. But reloading a file might close
+                       // the BufferView from within its own event handler.
+                       guiApp->dispatchDelayed(FuncRequest(LFUN_FILE_OPEN, file));
+                       event->accept();
+               }
        }
 }
 
@@ -852,6 +867,9 @@ void GuiView::setBusy(bool busy)
 
 GuiWorkArea * GuiView::workArea(Buffer & buffer)
 {
+       if (currentWorkArea()
+           && &currentWorkArea()->bufferView().buffer() == &buffer)
+               return (GuiWorkArea *) currentWorkArea();
        if (TabWorkArea * twa = d.currentTabWorkArea())
                return twa->workArea(buffer);
        return 0;
@@ -887,51 +905,105 @@ GuiWorkArea const * GuiView::currentWorkArea() const
 }
 
 
+GuiWorkArea * GuiView::currentWorkArea()
+{
+       return d.current_work_area_;
+}
+
+
+GuiWorkArea const * GuiView::currentMainWorkArea() const
+{
+       if (d.currentTabWorkArea() == NULL)
+               return NULL;
+       return d.currentTabWorkArea()->currentWorkArea();
+}
+
+
+GuiWorkArea * GuiView::currentMainWorkArea()
+{
+       if (d.currentTabWorkArea() == NULL)
+               return NULL;
+       return d.currentTabWorkArea()->currentWorkArea();
+}
+
+
 void GuiView::setCurrentWorkArea(GuiWorkArea * wa)
 {
-       LASSERT(wa, /**/);
+       LYXERR(Debug::DEBUG, "Setting current wa: " << wa << endl);
+       if (wa == NULL) {
+               d.current_work_area_ = NULL;
+               d.setBackground();
+               return;
+       }
+       GuiWorkArea * old_gwa = theGuiApp()->currentView()->currentWorkArea();
+       if (old_gwa == wa)
+               return;
+
+       theGuiApp()->setCurrentView(this);
        d.current_work_area_ = wa;
        for (int i = 0; i != d.splitter_->count(); ++i) {
-               if (d.tabWorkArea(i)->setCurrentWorkArea(wa))
+               if (d.tabWorkArea(i)->setCurrentWorkArea(wa)) {
+                       //if (d.current_main_work_area_)
+                       //      d.current_main_work_area_->setFrameStyle(QFrame::NoFrame);
+                       d.current_main_work_area_ = wa;
+                       //d.current_main_work_area_->setFrameStyle(QFrame::Box | QFrame::Plain);
+                       //d.current_main_work_area_->setLineWidth(2);
+                       LYXERR(Debug::DEBUG, "Current wa: " << currentWorkArea() << ", Current main wa: " << currentMainWorkArea());
                        return;
+               }
        }
+       LYXERR(Debug::DEBUG, "This is not a tabbed wa");
+       on_currentWorkAreaChanged(wa);
+       BufferView & bv = wa->bufferView();
+       bv.cursor().fixIfBroken();
+       bv.updateMetrics();
+       wa->setUpdatesEnabled(true);
+       LYXERR(Debug::DEBUG, "Current wa: " << currentWorkArea() << ", Current main wa: " << currentMainWorkArea());
 }
 
 
 void GuiView::removeWorkArea(GuiWorkArea * wa)
 {
-       LASSERT(wa, /**/);
+       LASSERT(wa, return);
        if (wa == d.current_work_area_) {
                disconnectBuffer();
                disconnectBufferView();
                d.current_work_area_ = 0;
+               d.current_main_work_area_ = 0;
        }
 
+       bool found_twa = false;
        for (int i = 0; i != d.splitter_->count(); ++i) {
                TabWorkArea * twa = d.tabWorkArea(i);
-               if (!twa->removeWorkArea(wa))
-                       // Not found in this tab group.
-                       continue;
-
-               // We found and removed the GuiWorkArea.
-               if (!twa->count()) {
-                       // No more WorkAreas in this tab group, so delete it.
-                       delete twa;
+               if (twa->removeWorkArea(wa)) {
+                       // Found in this tab group, and deleted the GuiWorkArea.
+                       found_twa = true;
+                       if (twa->count() != 0) {
+                               if (d.current_work_area_ == 0)
+                                       // This means that we are closing the current GuiWorkArea, so
+                                       // switch to the next GuiWorkArea in the found TabWorkArea.
+                                       setCurrentWorkArea(twa->currentWorkArea());
+                       } else {
+                               // No more WorkAreas in this tab group, so delete it.
+                               delete twa;
+                       }
                        break;
                }
+       }
 
-               if (d.current_work_area_)
-                       // This means that we are not closing the current GuiWorkArea;
-                       break;
+       // It is not a tabbed work area (i.e., the search work area), so it
+       // should be deleted by other means.
+       LASSERT(found_twa, /* */);
 
-               // Switch to the next GuiWorkArea in the found TabWorkArea.
-               d.current_work_area_ = twa->currentWorkArea();
-               break;
+       if (d.current_work_area_ == 0) {
+               if (d.splitter_->count() != 0) {
+                       TabWorkArea * twa = d.currentTabWorkArea();
+                       setCurrentWorkArea(twa->currentWorkArea());
+               } else {
+                       // No more work areas, switch to the background widget.
+                       setCurrentWorkArea(0);
+               }
        }
-
-       if (d.splitter_->count() == 0)
-               // No more work area, switch to the background widget.
-               d.setBackground();
 }
 
 
@@ -988,12 +1060,13 @@ Buffer const * GuiView::buffer() const
 
 void GuiView::setBuffer(Buffer * newBuffer)
 {
-       LASSERT(newBuffer, /**/);
+       LYXERR(Debug::DEBUG, "Setting buffer: " << newBuffer << std::endl);
+       LASSERT(newBuffer, return);
        setBusy(true);
 
        GuiWorkArea * wa = workArea(*newBuffer);
        if (wa == 0) {
-               updateLabels(*newBuffer->masterBuffer());
+               newBuffer->masterBuffer()->updateLabels();
                wa = addWorkArea(*newBuffer);
        } else {
                //Disconnect the old buffer...there's no new one.
@@ -1041,6 +1114,12 @@ void GuiView::errors(string const & error_type)
 }
 
 
+void GuiView::updateTocItem(std::string const & type, DocIterator const & dit)
+{
+       d.toc_models_.updateItem(toqstr(type), dit);
+}
+
+
 void GuiView::structureChanged()
 {
        d.toc_models_.reset(view());
@@ -1166,7 +1245,7 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                else if (name == "latexlog")
                        enable = FileName(buf->logName()).isReadableFile();
                else if (name == "spellchecker")
-#if defined (USE_ASPELL) || defined (USE_ISPELL) || defined (USE_PSPELL)
+#if defined (USE_ASPELL)
                        enable = !buf->isReadonly();
 #else
                        enable = false;
@@ -1191,7 +1270,7 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                        FuncStatus fs;
                        if (!inset->getStatus(view()->cursor(), fr, fs)) {
                                // Every inset is supposed to handle this
-                               LASSERT(false, /**/);
+                               LASSERT(false, break);
                        }
                        flag |= fs;
                } else {
@@ -1221,7 +1300,14 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
                break;
 
        case LFUN_COMPLETION_ACCEPT:
-       case LFUN_COMPLETION_CANCEL:
+               if (!d.current_work_area_
+                   || (!d.current_work_area_->completer().popupVisible()
+                       && !d.current_work_area_->completer().inlineVisible()
+                       && !d.current_work_area_->completer().completionAvailable()))
+                       enable = false;
+               break;
+
+               case LFUN_COMPLETION_CANCEL:
                if (!d.current_work_area_
                    || (!d.current_work_area_->completer().popupVisible()
                        && !d.current_work_area_->completer().inlineVisible()))
@@ -1352,8 +1438,7 @@ void GuiView::openDocument(string const & fname)
        docstring str2;
        Buffer * buf = loadDocument(fullname);
        if (buf) {
-               updateLabels(*buf);
-               
+               buf->updateLabels();
                setBuffer(buf);
                buf->errors("Parse");
                str2 = bformat(_("Document %1$s opened."), disp_fn);
@@ -1402,7 +1487,7 @@ static bool import(GuiView * lv, FileName const & filename,
                Buffer * buf = lv->loadDocument(lyxfile);
                if (!buf)
                        return false;
-               updateLabels(*buf);
+               buf->updateLabels();
                lv->setBuffer(buf);
                buf->errors("Parse");
        } else {
@@ -1702,6 +1787,9 @@ bool GuiView::renameBuffer(Buffer & b, docstring const & newname)
 
 bool GuiView::saveBuffer(Buffer & b)
 {
+       if (workArea(b) && workArea(b)->inDialogMode())
+               return true;
+
        if (b.isUnnamed())
                return renameBuffer(b, docstring());
 
@@ -1746,13 +1834,18 @@ bool GuiView::closeBuffer(Buffer & buf, bool tolastopened)
 {
        // goto bookmark to update bookmark pit.
        //FIXME: we should update only the bookmarks related to this buffer!
+       LYXERR(Debug::DEBUG, "GuiView::closeBuffer()");
        for (size_t i = 0; i < theSession().bookmarks().size(); ++i)
                theLyXFunc().gotoBookmark(i+1, false, false);
 
        if (buf.isClean() || buf.paragraphs().empty()) {
                if (buf.masterBuffer() == &buf && tolastopened)
                        theSession().lastOpened().add(buf.fileName());
-               theBufferList().release(&buf);
+               if (buf.parent())
+                       // Don't close child documents.
+                       removeWorkArea(currentMainWorkArea());
+               else
+                       theBufferList().release(&buf);
                return true;
        }
        // Switch to this Buffer.
@@ -1797,7 +1890,7 @@ bool GuiView::closeBuffer(Buffer & buf, bool tolastopened)
 
        if (buf.parent())
                // Don't close child documents.
-               removeWorkArea(d.current_work_area_);
+               removeWorkArea(currentMainWorkArea());
        else
                theBufferList().release(&buf);
 
@@ -1958,6 +2051,11 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                                data = bv->cursor().getEncoding()->name();
                                if (!data.empty())
                                        showDialog("symbols", data);
+                       // bug 5274
+                       } else if (name == "prefs" && isFullScreen()) {
+                               FuncRequest fr(LFUN_INSET_INSERT, "fullscreen");
+                               lfunUiToggle(fr);
+                               showDialog("prefs", data);
                        } else
                                showDialog(name, data);
                        break;
@@ -1969,13 +2067,15 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                        if (inset) {
                                // put cursor in front of inset.
                                if (!view()->setCursorFromInset(inset))
-                                       LASSERT(false, /**/);
+                                       LASSERT(false, break);
                                
+                               // useful if we are called from a dialog.
+                               view()->cursor().beginUndoGroup();
                                view()->cursor().recordUndo();
                                FuncRequest fr(LFUN_INSET_MODIFY, cmd.argument());
                                inset->dispatch(view()->cursor(), fr);
+                               view()->cursor().endUndoGroup();
                        } else {
-                               view()->cursor().recordUndo();
                                FuncRequest fr(LFUN_INSET_INSERT, cmd.argument());
                                lyx::dispatch(fr);
                        }
@@ -2005,15 +2105,11 @@ bool GuiView::dispatch(FuncRequest const & cmd)
                                twa = d.currentTabWorkArea();
                                // Switch to the next GuiWorkArea in the found TabWorkArea.
                                if (twa) {
-                                       d.current_work_area_ = twa->currentWorkArea();
                                        // Make sure the work area is up to date.
-                                       twa->setCurrentWorkArea(d.current_work_area_);
+                                       setCurrentWorkArea(twa->currentWorkArea());
                                } else {
-                                       d.current_work_area_ = 0;
+                                       setCurrentWorkArea(0);
                                }
-                               if (d.splitter_->count() == 0)
-                                       // No more work area, switch to the background widget.
-                                       d.setBackground();
                        }
                        break;
                        
@@ -2124,6 +2220,8 @@ void GuiView::toggleFullScreen()
                menuBar()->show();
                statusBar()->show();
        } else {
+               // bug 5274
+               hideDialogs("prefs", 0);
                for (int i = 0; i != d.splitter_->count(); ++i)
                        d.tabWorkArea(i)->setFullScreen(true);
 #if QT_VERSION >= 0x040300
@@ -2139,6 +2237,9 @@ void GuiView::toggleFullScreen()
                                it->second->hide();
                }
        }
+
+       // give dialogs like the TOC a chance to adapt
+       updateDialogs();
 }
 
 
@@ -2193,7 +2294,7 @@ char const * const dialognames[] = {
 "thesaurus",
 #endif
 
-"texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings" };
+"texinfo", "toc", "href", "view-source", "vspace", "wrap", "listings", "findreplaceadv" };
 
 char const * const * const end_dialognames =
        dialognames + (sizeof(dialognames) / sizeof(char *));
@@ -2225,7 +2326,7 @@ void GuiView::resetDialogs()
        saveLayout();
        menuBar()->clear();
        constructToolbars();
-       guiApp->menus().fillMenuBar(menuBar(), this, true);
+       guiApp->menus().fillMenuBar(menuBar(), this, false);
        if (d.layout_)
                d.layout_->updateContents(true);
        // Now update controls with current buffer.
@@ -2242,8 +2343,11 @@ Dialog * GuiView::findOrBuild(string const & name, bool hide_it)
 
        map<string, DialogPtr>::iterator it = d.dialogs_.find(name);
 
-       if (it != d.dialogs_.end())
+       if (it != d.dialogs_.end()) {
+               if (hide_it)
+                       it->second->hideView();
                return it->second.get();
+       }
 
        Dialog * dialog = build(name);
        d.dialogs_[name].reset(dialog);
@@ -2378,6 +2482,7 @@ Dialog * createGuiPreferences(GuiView & lv);
 Dialog * createGuiPrint(GuiView & lv);
 Dialog * createGuiRef(GuiView & lv);
 Dialog * createGuiSearch(GuiView & lv);
+Dialog * createGuiSearchAdv(GuiView & lv);
 Dialog * createGuiSendTo(GuiView & lv);
 Dialog * createGuiShowFile(GuiView & lv);
 Dialog * createGuiSpellchecker(GuiView & lv);
@@ -2395,7 +2500,7 @@ Dialog * createGuiWrap(GuiView & lv);
 
 Dialog * GuiView::build(string const & name)
 {
-       LASSERT(isValidName(name), /**/);
+       LASSERT(isValidName(name), return 0);
 
        if (name == "aboutlyx")
                return createGuiAbout(*this);
@@ -2425,6 +2530,8 @@ Dialog * GuiView::build(string const & name)
                return createGuiShowFile(*this);
        if (name == "findreplace")
                return createGuiSearch(*this);
+       if (name == "findreplaceadv")
+               return createGuiSearchAdv(*this);
        if (name == "float")
                return createGuiFloat(*this);
        if (name == "graphics")
@@ -2491,4 +2598,4 @@ Dialog * GuiView::build(string const & name)
 } // namespace frontend
 } // namespace lyx
 
-#include "GuiView_moc.cpp"
+#include "moc_GuiView.cpp"