summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominik Haumann <dhaumann@kde.org>2014-01-23 16:50:28 (GMT)
committerDominik Haumann <dhaumann@kde.org>2014-01-23 16:50:28 (GMT)
commitab6b678d4d12c0369c37f13becc8b053a92711a3 (patch)
tree41e3243f90b6f29d1e97e33e99d185737f1f4b32
parent5e5ff0574a8bd82c02167cd9442412ac3d77b0a9 (diff)
implement correct document switching
-rw-r--r--kate/app/katetabbar.cpp232
-rw-r--r--kate/app/katetabbar.h38
-rw-r--r--kate/app/kateviewspace.cpp240
-rw-r--r--kate/app/kateviewspace.h54
4 files changed, 276 insertions, 288 deletions
diff --git a/kate/app/katetabbar.cpp b/kate/app/katetabbar.cpp
index c3811fb..4ed6e7b 100644
--- a/kate/app/katetabbar.cpp
+++ b/kate/app/katetabbar.cpp
@@ -29,62 +29,8 @@
#include <QToolButton>
#include <QApplication> // QApplication::sendEvent
-#include <QtAlgorithms> // qSort
#include <QDebug>
-KateTabBar::SortType global_sortType;
-
-// public operator < for two tab buttons
-bool tabLessThan(const KateTabButton *a, const KateTabButton *b)
-{
- switch (global_sortType) {
- case KateTabBar::OpeningOrder: {
- return a->buttonID() < b->buttonID();
- }
-
- case KateTabBar::Name: {
- // fall back to ID
- if (a->text().toLower() == b->text().toLower()) {
- return a->buttonID() < b->buttonID();
- }
-
- return a->text() < b->text();
-// return KStringHandler::naturalCompare(a->text(), b->text(), Qt::CaseInsensitive) < 0; // FIXME KF5
- }
-
- case KateTabBar::Extension: {
- // sort by extension, but check whether the files have an
- // extension first
- const int apos = a->text().lastIndexOf(QLatin1Char('.'));
- const int bpos = b->text().lastIndexOf(QLatin1Char('.'));
-
- if (apos == -1 && bpos == -1) {
- return a->text().toLower() < b->text().toLower();
- } else if (apos == -1) {
- return true;
- } else if (bpos == -1) {
- return false;
- } else {
- const int aright = a->text().size() - apos;
- const int bright = b->text().size() - bpos;
- QString aExt = a->text().right(aright).toLower();
- QString bExt = b->text().right(bright).toLower();
- QString aFile = a->text().left(apos).toLower();
- QString bFile = b->text().left(bpos).toLower();
-
- if (aExt == bExt)
- return (aFile == bFile) ? a->buttonID() < b->buttonID()
- : aFile < bFile;
- else {
- return aExt < bExt;
- }
- }
- }
- }
-
- return true;
-}
-
/**
* Creates a new tab bar with the given \a parent and \a name.
* .
@@ -95,9 +41,9 @@ KateTabBar::KateTabBar(QWidget *parent)
m_minimumTabWidth = 150;
m_maximumTabWidth = 350;
- m_tabHeight = 22;
+ // FIXME: better additional size
+ setFixedHeight(QFontMetrics(font()).height() + 10);
- m_sortType = OpeningOrder;
m_nextID = 0;
m_activeButton = 0L;
@@ -134,8 +80,6 @@ void KateTabBar::load(KConfigBase *config, const QString &group)
// tabbar properties
setMinimumTabWidth(cg.readEntry("minimum width", m_minimumTabWidth));
setMaximumTabWidth(cg.readEntry("maximum width", m_maximumTabWidth));
- setTabHeight(cg.readEntry("fixed height", m_tabHeight));
- setTabSortType((SortType) cg.readEntry("sort type", (int)OpeningOrder));
// highlighted entries
QStringList documents = cg.readEntry("highlighted documents", QStringList());
@@ -162,8 +106,6 @@ void KateTabBar::save(KConfigBase *config, const QString &group) const
// tabbar properties
cg.writeEntry("minimum width", minimumTabWidth());
cg.writeEntry("maximum width", maximumTabWidth());
- cg.writeEntry("fixed height", tabHeight());
- cg.writeEntry("sort type", (int)tabSortType());
// highlighted entries
cg.writeEntry("highlighted documents", m_highlightedTabs.keys());
@@ -180,7 +122,7 @@ void KateTabBar::setMinimumTabWidth(int min_pixel)
}
m_minimumTabWidth = min_pixel;
- triggerResizeEvent();
+ updateButtonPositions();
}
/**
@@ -193,7 +135,7 @@ void KateTabBar::setMaximumTabWidth(int max_pixel)
}
m_maximumTabWidth = max_pixel;
- triggerResizeEvent();
+ updateButtonPositions();
}
/**
@@ -213,52 +155,31 @@ int KateTabBar::maximumTabWidth() const
}
/**
- * Set the fixed height in pixels all tabs have.
- * \note If you also show icons use a height of iconheight + 2.
- * E.g. for 16x16 pixel icons, a tab height of 18 pixel looks best.
- * For 22x22 pixel icons a height of 24 pixel is best etc.
+ * This is an overloaded member function, provided for convenience.
+ * It behaves essentially like the above function.
+ *
+ * Adds a new tab with \a text. Returns the new tab's id.
*/
-void KateTabBar::setTabHeight(int height_pixel)
+int KateTabBar::addTab(const QString &text)
{
- if (m_tabHeight == height_pixel) {
- return;
- }
-
- m_tabHeight = height_pixel;
- updateFixedHeight();
+ return insertTab(m_tabButtons.size(), text);
}
-/**
- * Get the fixed tab height in pixels.
- */
-int KateTabBar::tabHeight() const
+int KateTabBar::insertTab(int position, const QString & text)
{
- return m_tabHeight;
-}
+ Q_ASSERT(position <= m_tabButtons.size());
-/**
- * Adds a new tab with text \a text. Returns the new tab's ID.
- */
-int KateTabBar::addTab(const QString &text)
-{
- return addTab(QIcon(), text);
-}
+ // -1 is append
+ if (position < 0) {
+ position = m_tabButtons.size();
+ }
-/**
- * This is an overloaded member function, provided for convenience.
- * It behaves essentially like the above function.
- *
- * Adds a new tab with \a icon and \a text. Returns the new tab's index.
- */
-int KateTabBar::addTab(const QIcon &icon, const QString &text)
-{
KateTabButton *tabButton = new KateTabButton(text, m_nextID, this);
- tabButton->setIcon(icon);
if (m_highlightedTabs.contains(text)) {
tabButton->setHighlightColor(QColor(m_highlightedTabs[text]));
}
- m_tabButtons.append(tabButton);
+ m_tabButtons.insert(position, tabButton);
m_IDToTabButton[m_nextID] = tabButton;
connect(tabButton, SIGNAL(activated(KateTabButton*)),
this, SLOT(tabButtonActivated(KateTabButton*)));
@@ -271,28 +192,11 @@ int KateTabBar::addTab(const QIcon &icon, const QString &text)
connect(tabButton, SIGNAL(closeAllTabsRequest()),
this, SLOT(tabButtonCloseAllRequest()));
- if (!isVisible()) {
- show();
- }
-
- updateSort();
+ updateButtonPositions();
return m_nextID++;
}
-void KateTabBar::raiseTab(int buttonId)
-{
- Q_ASSERT(m_IDToTabButton.contains(buttonId));
-
- KateTabButton *button = m_IDToTabButton[buttonId];
- int tabIndex = m_tabButtons.indexOf(button);
- Q_ASSERT(tabIndex > -1);
-
- m_tabButtons.move(tabIndex, 0);
-
- triggerResizeEvent();
-}
-
/**
* Get the ID of the tab bar's activated tab. Returns -1 if no tab is activated.
*/
@@ -328,22 +232,26 @@ void KateTabBar::setCurrentTab(int index)
}
/**
- * Removes the tab with ID \a index.
+ * Removes the tab with ID \a id.
+ * @return the position where the tab was
*/
-void KateTabBar::removeTab(int index)
+int KateTabBar::removeTab(int id)
{
- if (!m_IDToTabButton.contains(index)) {
- return;
+ if (!m_IDToTabButton.contains(id)) {
+ Q_ASSERT(false);
+ return -1;
}
- KateTabButton *tabButton = m_IDToTabButton[index];
+ KateTabButton *tabButton = m_IDToTabButton[id];
if (tabButton == m_activeButton) {
m_activeButton = 0L;
}
- m_IDToTabButton.remove(index);
- m_tabButtons.removeAll(tabButton);
+ const int position = m_tabButtons.indexOf(tabButton);
+
+ m_IDToTabButton.remove(id);
+ m_tabButtons.removeAt(position);
// delete the button with deleteLater() because the button itself might
// have send a close-request. So the app-execution is still in the
// button, a delete tabButton; would lead to a crash.
@@ -354,7 +262,9 @@ void KateTabBar::removeTab(int index)
hide();
}
- triggerResizeEvent();
+ updateButtonPositions();
+
+ return position;
}
/**
@@ -387,10 +297,6 @@ void KateTabBar::setTabText(int index, const QString &text)
}
m_IDToTabButton[index]->setText(text);
-
- if (tabSortType() == Name || tabSortType() == Extension) {
- updateSort();
- }
}
/**
@@ -464,27 +370,6 @@ int KateTabBar::count() const
return m_tabButtons.count();
}
-/**
- * Set the sort tye to @p sort.
- */
-void KateTabBar::setTabSortType(SortType sort)
-{
- if (m_sortType == sort) {
- return;
- }
-
- m_sortType = sort;
- updateSort();
-}
-
-/**
- * Get the sort type.
- */
-KateTabBar::SortType KateTabBar::tabSortType() const
-{
- return m_sortType;
-}
-
void KateTabBar::setTabModified(int index, bool modified)
{
if (m_IDToTabButton.contains(index)) {
@@ -620,12 +505,27 @@ void KateTabBar::tabButtonCloseAllRequest()
*/
void KateTabBar::resizeEvent(QResizeEvent *event)
{
+ Q_UNUSED(event)
+
+ // fix button positions
+ updateButtonPositions();
+
+ const int tabDiff = maxTabCount() - m_tabButtons.size();
+ if (tabDiff > 0) {
+ emit moreTabsRequested(tabDiff);
+ } else if (tabDiff < 0) {
+ emit lessTabsRequested(-tabDiff);
+ }
+}
+
+void KateTabBar::updateButtonPositions()
+{
// if there are no tabs there is nothing to do
if (m_tabButtons.count() == 0) {
return;
}
- int barWidth = event->size().width();
+ const int barWidth = width();
const int maxCount = maxTabCount();
// how many tabs do we show?
@@ -643,12 +543,10 @@ void KateTabBar::resizeEvent(QResizeEvent *event)
tabButton->hide();
} else {
const int w = ceil(tabWidth);
- tabButton->setGeometry(i * w, 0, w, tabHeight());
+ tabButton->setGeometry(i * w, 0, w, m_tabHeight);
tabButton->show();
}
}
-
-// if (visibleTabCount
}
/**
@@ -659,35 +557,3 @@ int KateTabBar::maxTabCount() const
{
return qMax(1, width() / minimumTabWidth());
}
-
-/**
- * Updates the fixed height. Called when the tab height or the number of rows
- * changed.
- */
-void KateTabBar::updateFixedHeight()
-{
- setFixedHeight(tabHeight());
- triggerResizeEvent();
-}
-
-void KateTabBar::updateSort()
-{
- global_sortType = tabSortType();
- qSort(m_tabButtons.begin(), m_tabButtons.end(), tabLessThan);
- triggerResizeEvent();
-}
-
-/**
- * Triggers a resizeEvent. This is used whenever the tab buttons need
- * a rearrange. By using \p QApplication::sendEvent() multiple calls are
- * combined into only one call.
- *
- * \see addTab(), removeTab(), setMinimumWidth(), setMaximumWidth(),
- * setFixedHeight()
- */
-void KateTabBar::triggerResizeEvent()
-{
- QResizeEvent ev(size(), size());
- QApplication::sendEvent(this, &ev);
-}
-
diff --git a/kate/app/katetabbar.h b/kate/app/katetabbar.h
index 6577b2c..6d6a745 100644
--- a/kate/app/katetabbar.h
+++ b/kate/app/katetabbar.h
@@ -44,17 +44,6 @@ class KateTabBar : public QWidget
Q_OBJECT
public:
- /**
- * Sort types.
- */
- enum SortType {
- OpeningOrder = 0, ///< opening order
- Name, ///< alphabetically
- Extension ///< by file extension (suffix)
- };
- Q_DECLARE_FLAGS(SortTypes, SortType)
-
-public:
// NOTE: as the API here is very self-explaining the docs are in the cpp
// file, more clean imho.
@@ -74,8 +63,8 @@ public:
int tabHeight() const;
int addTab(const QString &text);
- int addTab(const QIcon &pixmap, const QString &text);
- void removeTab(int index);
+ int insertTab(int position, const QString & text);
+ int removeTab(int index);
int currentTab() const;
// corresponding SLOT: void setCurrentTab( int index );
@@ -96,9 +85,6 @@ public:
int count() const;
- void setTabSortType(SortType sort);
- SortType tabSortType() const;
-
void setHighlightMarks(const QMap<QString, QString> &marks);
QMap<QString, QString> highlightMarks() const;
@@ -107,7 +93,6 @@ public:
public Q_SLOTS:
void setCurrentTab(int index); // does not emit signal
void removeHighlightMarks();
- void raiseTab(int index);
Q_SIGNALS:
/**
@@ -126,6 +111,20 @@ Q_SIGNALS:
*/
void highlightMarksChanged(KateTabBar *tabbar);
+ /**
+ * This signal is emitted whenever the tab bar's width allows to
+ * show more tabs than currently available. In other words,
+ * you can safely add @p count tabs which are guaranteed to be visible.
+ */
+ void moreTabsRequested(int count);
+
+ /**
+ * This signal is emitted whenever the tab bar's width is too small,
+ * such that not all tabs can be shown.
+ * Therefore, @p count tabs should be removed.
+ */
+ void lessTabsRequested(int count);
+
protected Q_SLOTS:
void tabButtonActivated(KateTabButton *tabButton);
void tabButtonHighlightChanged(KateTabButton *tabButton);
@@ -138,8 +137,7 @@ protected:
protected:
void updateFixedHeight();
- void triggerResizeEvent();
- void updateSort();
+ void updateButtonPositions();
private:
int m_minimumTabWidth;
@@ -155,8 +153,6 @@ private:
// map of highlighted tabs and colors
QMap< QString, QString > m_highlightedTabs;
- SortType m_sortType;
};
#endif // KATE_TAB_BAR_H
-
diff --git a/kate/app/kateviewspace.cpp b/kate/app/kateviewspace.cpp
index da2d91d..e92f2f7 100644
--- a/kate/app/kateviewspace.cpp
+++ b/kate/app/kateviewspace.cpp
@@ -58,6 +58,8 @@ KateViewSpace::KateViewSpace(KateViewManager *viewManager,
// add tab bar
m_tabBar = new KateTabBar(this);
connect(m_tabBar, &KateTabBar::currentChanged, this, &KateViewSpace::changeView);
+ connect(m_tabBar, &KateTabBar::moreTabsRequested, this, &KateViewSpace::addTabs);
+ connect(m_tabBar, &KateTabBar::lessTabsRequested, this, &KateViewSpace::removeTabs);
hLayout->addWidget(m_tabBar);
// add vertical split view space
@@ -98,9 +100,6 @@ KateViewSpace::KateViewSpace(KateViewManager *viewManager,
statusBarToggled();
}
-KateViewSpace::~KateViewSpace()
-{}
-
bool KateViewSpace::eventFilter(QObject *obj, QEvent *event)
{
QToolButton *button = qobject_cast<QToolButton *>(obj);
@@ -125,13 +124,18 @@ bool KateViewSpace::eventFilter(QObject *obj, QEvent *event)
void KateViewSpace::statusBarToggled()
{
- Q_FOREACH(auto view, mViewList) {
- view->setStatusBarEnabled(m_viewManager->mainWindow()->showStatusBar());
+ Q_FOREACH(KTextEditor::Document * doc, m_lruDocList) {
+ if (m_docToView.contains(doc)) {
+ m_docToView[doc]->setStatusBarEnabled(m_viewManager->mainWindow()->showStatusBar());
+ }
}
}
KTextEditor::View *KateViewSpace::createView(KTextEditor::Document *doc)
{
+ // should only be called if a view does not yet exist
+ Q_ASSERT(! m_docToView.contains(doc));
+
/**
* Create a fresh view
*/
@@ -157,15 +161,15 @@ KTextEditor::View *KateViewSpace::createView(KTextEditor::Document *doc)
}
}
- // just register document, it is shown below through showView() then
- if (! m_docToTabId.contains(doc)) {
+ // register document, it is shown below through showView() then
+ if (! m_lruDocList.contains(doc)) {
registerDocument(doc);
- Q_ASSERT(m_docToTabId.contains(doc));
+ Q_ASSERT(m_lruDocList.contains(doc));
}
// insert View into stack
stack->addWidget(v);
- mViewList.append(v);
+ m_docToView[doc] = v;
showView(v);
return v;
@@ -173,71 +177,62 @@ KTextEditor::View *KateViewSpace::createView(KTextEditor::Document *doc)
void KateViewSpace::removeView(KTextEditor::View *v)
{
- // remove from tab bar
+ // remove view mappings
+ Q_ASSERT(m_docToView.contains(v->document()));
+ m_docToView.remove(v->document());
Q_ASSERT(m_docToTabId.contains(v->document()));
documentDestroyed(v->document());
// remove from view space
bool active = (v == currentView());
- mViewList.removeAt(mViewList.indexOf(v));
stack->removeWidget(v);
if (! active) {
return;
}
- // the last recently used viewspace is always at the end of the list
- if (!mViewList.isEmpty()) {
- showView(mViewList.last());
- }
- // if we still have tabs, use these
- else if (! m_docToTabId.isEmpty()) {
- QList<KTextEditor::Document *> keys = m_docToTabId.keys();
- m_viewManager->createView(keys.first());
- }
-}
-
-KTextEditor::View *KateViewSpace::viewForDocument(KTextEditor::Document *doc) const
-{
- QList<KTextEditor::View *>::const_iterator it = mViewList.constEnd();
- while (it != mViewList.constBegin()) {
- --it;
- if ((*it)->document() == doc) {
- return *it;
+ // the last recently used view/document is always at the end of the list
+ if (! m_lruDocList.isEmpty()) {
+ KTextEditor::Document * doc = m_lruDocList.last();
+ if (m_docToView.contains(doc)) {
+ showView(doc);
+ } else {
+ m_viewManager->createView(doc, this);
}
}
- return 0;
}
bool KateViewSpace::showView(KTextEditor::Document *document)
{
- QList<KTextEditor::View *>::const_iterator it = mViewList.constEnd();
- while (it != mViewList.constBegin()) {
- --it;
- if ((*it)->document() == document) {
- KTextEditor::View *kv = *it;
-
- // move view to end of list
- mViewList.removeAt(mViewList.indexOf(kv));
- mViewList.append(kv);
- stack->setCurrentWidget(kv);
- kv->show();
-
- // raise tab in tab bar
- Q_ASSERT(m_docToTabId.contains(document));
-// m_tabBar->raiseTab(m_docToTabId[document]);
- m_tabBar->setCurrentTab(m_docToTabId[document]);
+ const int index = m_lruDocList.lastIndexOf(document);
- return true;
- }
+ if (index < 0) {
+ return false;
}
- return false;
+
+ if (! m_docToView.contains(document)) {
+ return false;
+ }
+
+ KTextEditor::View *kv = m_docToView[document];
+
+ // move view to end of list
+ m_lruDocList.removeAt(index);
+ m_lruDocList.append(document);
+ stack->setCurrentWidget(kv);
+ kv->show();
+
+ // raise tab in view space tab bar
+ Q_ASSERT(m_docToTabId.contains(document));
+ m_tabBar->setCurrentTab(m_docToTabId[document]);
+
+ return true;
}
-void KateViewSpace::changeView(int buttonId)
+void KateViewSpace::changeView(int id)
{
- KTextEditor::Document *doc = m_docToTabId.key(buttonId);
+ KTextEditor::Document *doc = m_docToTabId.key(id);
Q_ASSERT(doc);
// make sure we open the view in this view space
@@ -251,8 +246,7 @@ void KateViewSpace::changeView(int buttonId)
KTextEditor::View *KateViewSpace::currentView()
{
- // stack->currentWidget() returns NULL, if stack.count() == 0,
- // i.e. if mViewList.isEmpty()
+ // might be 0 if the stack contains no view
return (KTextEditor::View *)stack->currentWidget();
}
@@ -264,31 +258,127 @@ bool KateViewSpace::isActiveSpace()
void KateViewSpace::setActive(bool active, bool)
{
mIsActiveSpace = active;
-
- // change the statusbar palette according to the activation state
- // FIXME KF5 mStatusBar->setEnabled(active);
}
-void KateViewSpace::registerDocument(KTextEditor::Document *doc)
+void KateViewSpace::insertTab(int index, KTextEditor::Document * doc)
{
+ // doc should be in the lru list
+ Q_ASSERT(m_lruDocList.contains(doc));
+
+ // doc should not have a id
Q_ASSERT(! m_docToTabId.contains(doc));
- // add to tab bar
- const int index = m_tabBar->addTab(doc->documentName());
- m_tabBar->setTabToolTip(index, doc->url().toString());
- m_docToTabId[doc] = index;
+
+ const int id = m_tabBar->insertTab(index, doc->documentName());
+ m_tabBar->setTabToolTip(id, doc->url().toDisplayString());
+ m_docToTabId[doc] = id;
connect(doc, SIGNAL(documentNameChanged(KTextEditor::Document*)),
this, SLOT(updateDocumentName(KTextEditor::Document*)));
+}
+
+int KateViewSpace::removeTab(KTextEditor::Document * doc)
+{
+ //
+ // WARNING: removeTab() is also called from documentDestroyed().
+ // Therefore, is may be that doc is half destroyed already.
+ // Therefore, do not access any KTextEditor::Document functions here!
+ // Only access QObject functions!
+ //
+ Q_ASSERT(m_docToTabId.contains(doc));
+
+ const int id = m_docToTabId[doc];
+ const int removeIndex = m_tabBar->removeTab(id);
+ m_docToTabId.remove(doc);
+
+ disconnect(doc, SIGNAL(documentNameChanged(KTextEditor::Document*)),
+ this, SLOT(updateDocumentName(KTextEditor::Document*)));
+
+ return removeIndex;
+}
+
+void KateViewSpace::removeTabs(int count)
+{
+ qDebug() << "________the tab bar wants LESS tabs:" << count;
+
+ while (count > 0) {
+ const int tabCount = m_tabBar->count();
+ KTextEditor::Document * removeDoc = m_lruDocList[m_lruDocList.size() - tabCount];
+ removeTab(removeDoc);
+ Q_ASSERT(! m_docToTabId.contains(removeDoc));
+ --count;
+ }
+}
+
+void KateViewSpace::addTabs(int count)
+{
+ qDebug() << "________the tab bar wants MORE tabs:" << count;
+
+ while (count > 0) {
+ const int tabCount = m_tabBar->count();
+ if (m_lruDocList.size() <= tabCount) {
+ break;
+ }
+ insertTab(tabCount, m_lruDocList[m_lruDocList.size() - tabCount - 1]);
+ --count;
+ }
+}
+
+void KateViewSpace::registerDocument(KTextEditor::Document *doc)
+{
+ // at this point, the doc should be completely unknown
+ Q_ASSERT(! m_lruDocList.contains(doc));
+ Q_ASSERT(! m_docToView.contains(doc));
+ Q_ASSERT(! m_docToTabId.contains(doc));
+
+ m_lruDocList.append(doc);
connect(doc, SIGNAL(destroyed(QObject*)), this, SLOT(documentDestroyed(QObject*)));
+
+ // if space is available, add button
+ if (m_tabBar->count() < m_tabBar->maxTabCount()) {
+ insertTab(m_tabBar->count(), doc);
+ } else {
+ // remove "oldest" button and replace with new one
+ Q_ASSERT(m_lruDocList.size() > m_tabBar->count());
+
+ KTextEditor::Document * docToHide = m_lruDocList[m_tabBar->count() - 1];
+ Q_ASSERT(m_docToTabId.contains(docToHide));
+ const int insertIndex = removeTab(docToHide);
+
+ // add new one at removed position
+ insertTab(insertIndex, doc);
+ }
}
void KateViewSpace::documentDestroyed(QObject *doc)
{
- Q_ASSERT(m_docToTabId.contains(static_cast<KTextEditor::Document *>(doc)));
- const int index = m_docToTabId[static_cast<KTextEditor::Document *>(doc)];
- m_tabBar->removeTab(index);
- m_docToTabId.remove(static_cast<KTextEditor::Document *>(doc));
+ // WARNING: this pointer is half destroyed
+ KTextEditor::Document *invalidDoc = static_cast<KTextEditor::Document *>(doc);
+
+ Q_ASSERT(m_lruDocList.contains(invalidDoc));
+ m_lruDocList.remove(m_lruDocList.indexOf(invalidDoc));
+
+ // case: there was no view created yet, but still a button was added
+ if (m_docToTabId.contains(invalidDoc)) {
+ const int insertIndex = removeTab(invalidDoc);
+ // maybe show another tab button in its stead
+ if (m_lruDocList.size() >= m_tabBar->maxTabCount()
+ && m_tabBar->count() < m_tabBar->maxTabCount()
+ ) {
+ KTextEditor::Document * docToShow = m_lruDocList[m_tabBar->count() - 1];
+ Q_ASSERT(! m_docToTabId.contains(docToShow));
+
+ // add tab that now fits into the bar
+ insertTab(insertIndex, docToShow);
+ }
+ }
+
+ // disconnect entirely
disconnect(doc, 0, this, 0);
+
+ // at this point, the doc should be completely unknown
+ Q_ASSERT(! m_lruDocList.contains(invalidDoc));
+ Q_ASSERT(! m_docToView.contains(invalidDoc));
+ Q_ASSERT(! m_docToTabId.contains(invalidDoc));
}
void KateViewSpace::updateDocumentName(KTextEditor::Document *doc)
@@ -304,8 +394,16 @@ void KateViewSpace::saveConfig(KConfigBase *config, int myIndex , const QString
// qCDebug(LOG_KATE)<<"KateViewSpace::saveConfig("<<myIndex<<", "<<viewConfGrp<<") - currentView: "<<currentView()<<")";
QString groupname = QString(viewConfGrp + QStringLiteral("-ViewSpace %1")).arg(myIndex);
+ // aggregate all views in view space (LRU ordered)
+ QVector<KTextEditor::View*> views;
+ Q_FOREACH(KTextEditor::Document* doc, m_lruDocList) {
+ if (m_docToView.contains(doc)) {
+ views.append(m_docToView[doc]);
+ }
+ }
+
KConfigGroup group(config, groupname);
- group.writeEntry("Count", mViewList.count());
+ group.writeEntry("Count", views.count());
if (currentView()) {
group.writeEntry("Active View", currentView()->document()->url().toString());
@@ -313,8 +411,7 @@ void KateViewSpace::saveConfig(KConfigBase *config, int myIndex , const QString
// Save file list, including cursor position in this instance.
int idx = 0;
- for (QList<KTextEditor::View *>::iterator it = mViewList.begin();
- it != mViewList.end(); ++it) {
+ for (QVector<KTextEditor::View *>::iterator it = views.begin(); it != views.end(); ++it) {
if (!(*it)->document()->url().isEmpty()) {
group.writeEntry(QString::fromLatin1("View %1").arg(idx), (*it)->document()->url().toString());
@@ -344,7 +441,7 @@ void KateViewSpace::restoreConfig(KateViewManager *viewMan, const KConfigBase *c
QString vgroup = QString::fromLatin1("%1 %2").arg(groupname).arg(fn);
KConfigGroup configGroup(config, vgroup);
- viewMan->createView(doc);
+ viewMan->createView(doc, this);
KTextEditor::View *v = viewMan->activeView();
@@ -354,8 +451,9 @@ void KateViewSpace::restoreConfig(KateViewManager *viewMan, const KConfigBase *c
}
}
- if (mViewList.isEmpty()) {
- viewMan->createView(KateDocManager::self()->document(0));
+ // avoid empty view space
+ if (m_docToView.isEmpty()) {
+ viewMan->createView(KateDocManager::self()->document(0), this);
}
m_group = groupname; // used for restroing view configs later
diff --git a/kate/app/kateviewspace.h b/kate/app/kateviewspace.h
index a1298a8..32e09f1 100644
--- a/kate/app/kateviewspace.h
+++ b/kate/app/kateviewspace.h
@@ -42,7 +42,6 @@ class KateViewSpace : public QWidget
public:
explicit KateViewSpace(KateViewManager *, QWidget *parent = 0, const char *name = 0);
- ~KateViewSpace();
bool isActiveSpace();
void setActive(bool b, bool showled = false);
@@ -60,12 +59,7 @@ public:
}
bool showView(KTextEditor::Document *document);
- KTextEditor::View *viewForDocument(KTextEditor::Document *document) const;
-
KTextEditor::View *currentView();
- int viewCount() const {
- return mViewList.count();
- }
void saveConfig(KConfigBase *config, int myIndex, const QString &viewConfGrp);
void restoreConfig(KateViewManager *viewMan, const KConfigBase *config, const QString &group);
@@ -89,19 +83,53 @@ private Q_SLOTS:
void statusBarToggled();
void changeView(int buttonId);
+ /**
+ * Add a tab for @p doc at position @p index.
+ */
+ void insertTab(int index, KTextEditor::Document * doc);
+
+ /**
+ * Remove tab for @p doc, and return the index (position)
+ * of the removed tab.
+ */
+ int removeTab(KTextEditor::Document * doc);
+
+ /**
+ * Remove @p count tabs, since the tab bar shrinked.
+ */
+ void removeTabs(int count);
+
+ /**
+ * Add @p count tabs, since the tab bar grew.
+ */
+ void addTabs(int count);
+
private:
- QStackedWidget *stack;
- bool mIsActiveSpace;
- /// This list is necessary to only save the order of the accessed views.
- /// The order is important. The least recently viewed view is always the
- /// last entry in the list, i.e. mViewList.last()
- /// mViewList.count() == stack.count() is always true!
- QList<KTextEditor::View *> mViewList;
+ // Kate's view manager
KateViewManager *m_viewManager;
+
+ // config group string, used for restoring View session configuration
QString m_group;
+ // flag that indicates whether this view space is the active one.
+ // correct setter: m_viewManager->setActiveSpace(this);
+ bool mIsActiveSpace;
+
+ // widget stack that contains all KTE::Views
+ QStackedWidget *stack;
+
+ // document's in the view space, sorted in LRU mode:
+ // the least recently used Document is at the end of the list
+ QVector<KTextEditor::Document *> m_lruDocList;
+
+ // the list of views that are contained in this view space,
+ // mapped through a hash from Document to View.
+ // note: the number of entries match stack->count();
+ QHash<KTextEditor::Document*, KTextEditor::View*> m_docToView;
+
// tab bar that contains viewspace tabs
KateTabBar *m_tabBar;
+
// map from Document to button id
QHash<KTextEditor::Document *, int> m_docToTabId;
};