Commit f952657a authored by Dominik Haumann's avatar Dominik Haumann

start adding a tabbar to the view space

todo:
- somehow show what view space is active
- icons on buttons: modified state, close button
- implement button "..." (quick open, ...)
- fix which buttons are visible
- width & height
parent cc573ab3
......@@ -32,6 +32,9 @@ set (KATE_APPLICATION_SRCS
app/katesavemodifieddialog.cpp
app/katemwmodonhddialog.cpp
app/katetabbutton.cpp
app/katetabbar.cpp
# session
session/katesessionchooser.cpp
session/katesessionsaction.cpp
......@@ -45,7 +48,8 @@ set (KATE_APPLICATION_SRCS
app/kateappcommands.cpp
app/katequickopen.cpp
app/katewaiter.h
app/main.cpp)
app/main.cpp
)
# create kde init executable
kf5_add_kdeinit_executable(kate ${KATE_APPLICATION_SRCS})
......
This diff is collapsed.
/* This file is part of the KDE project
*
* Copyright (C) 2014 Dominik Haumann <dhauumann@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KATE_TAB_BAR_H
#define KATE_TAB_BAR_H
#include <QWidget>
#include <QList>
#include <QMap>
#include <QIcon>
#include <QResizeEvent>
class KateTabButton;
class KConfigBase;
/**
* The \p KateTabBar class provides a tab bar, e.g. for tabbed documents and
* supports multiple rows. The tab bar hides itself if there are no tabs.
*
* It implements the API from TrollTech's \p QTabBar with some minor changes
* and additions.
*
* @author Dominik Haumann
*/
class KateTabBar : public QWidget
{
Q_OBJECT
public:
/**
* Sort types.
*/
enum SortType {
OpeningOrder = 0, ///< opening order
Name, ///< alphabetically
URL, ///< alphabetically URL based
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.
KateTabBar(QWidget *parent = 0);
virtual ~KateTabBar();
void load(KConfigBase *config, const QString &group);
void save(KConfigBase *config, const QString &group) const;
void setMinimumTabWidth(int min_pixel);
void setMaximumTabWidth(int max_pixel);
int minimumTabWidth() const;
int maximumTabWidth() const;
void setTabHeight(int height_pixel);
int tabHeight() const;
int addTab(const QString &docurl, const QString &text);
int addTab(const QString &docurl, const QIcon &pixmap, const QString &text);
void removeTab(int button_id);
int currentTab() const;
// corresponding SLOT: void setCurrentTab( int button_id );
bool containsTab(int button_id) const;
void setTabURL(int button_id, const QString &docurl);
QString tabURL(int button_id) const;
void setTabText(int button_id, const QString &text);
QString tabText(int button_id) const;
void setTabIcon(int button_id, const QIcon &pixmap);
QIcon tabIcon(int button_id) const;
void setTabModified(int button_id, bool modified);
bool isTabModified(int button_id) const;
int count() const;
void setTabSortType(SortType sort);
SortType tabSortType() const;
void setHighlightMarks(const QMap<QString, QString> &marks);
QMap<QString, QString> highlightMarks() const;
public Q_SLOTS:
void setCurrentTab(int button_id); // does not emit signal
void removeHighlightMarks();
void raiseTab(int buttonId);
Q_SIGNALS:
/**
* This signal is emitted whenever the current activated tab changes.
*/
void currentChanged(int button_id);
/**
* This signal is emitted whenever a tab should be closed.
*/
void closeRequest(int button_id);
/**
* This signal is emitted whenever a setting entry changes.
*/
void settingsChanged(KateTabBar *tabbar);
/**
* This signal is emitted whenever a highlight mark changes.
* Usually this is used to synchronice several tabbars.
*/
void highlightMarksChanged(KateTabBar *tabbar);
protected Q_SLOTS:
void tabButtonActivated(KateTabButton *tabButton);
void tabButtonHighlightChanged(KateTabButton *tabButton);
void tabButtonCloseAllRequest();
void tabButtonCloseRequest(KateTabButton *tabButton);
void tabButtonCloseOtherRequest(KateTabButton *tabButton);
protected:
virtual void resizeEvent(QResizeEvent *event);
protected:
void updateFixedHeight();
void triggerResizeEvent();
void updateSort();
void updateHelperButtons(QSize new_size);
private:
int m_minimumTabWidth;
int m_maximumTabWidth;
int m_tabHeight;
QList< KateTabButton * > m_tabButtons;
QMap< int, KateTabButton * > m_IDToTabButton;
KateTabButton *m_activeButton;
// buttons on the right to navigate and configure
KateTabButton *m_configureButton;
int m_navigateSize;
int m_nextID;
// map of highlighted tabs and colors
QMap< QString, QString > m_highlightedTabs;
SortType m_sortType;
};
#endif // KATE_TAB_BAR_H
// kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on; eol unix;
/* This file is part of the KDE project
*
* Copyright (C) 2014 Dominik Haumann <dhauumann@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "katetabbutton.h"
#include <klocalizedstring.h>
#include <QApplication>
#include <QColorDialog>
#include <QContextMenuEvent>
#include <QFontDatabase>
#include <QIcon>
#include <QMenu>
#include <QPainter>
QColor KateTabButton::s_predefinedColors[] = { Qt::red, Qt::yellow, Qt::green, Qt::cyan, Qt::blue, Qt::magenta };
const int KateTabButton::s_colorCount = 6;
int KateTabButton::s_currentColor = 0;
KateTabButton::KateTabButton(const QString &docurl, const QString &caption,
int button_id, QWidget *parent)
: QPushButton(parent)
{
setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
setCheckable(true);
setFocusPolicy(Qt::NoFocus);
setMinimumWidth(1);
setFlat(true);
// setAutoFillBackground(true);
m_buttonId = button_id;
m_modified = false;
setIcon(QIcon());
setText(caption);
setURL(docurl);
connect(this, SIGNAL(clicked()), this, SLOT(buttonClicked()));
}
KateTabButton::~KateTabButton()
{
}
void KateTabButton::setURL(const QString &docurl)
{
m_url = docurl;
if (!m_url.isEmpty()) {
setToolTip(m_url);
} else {
setToolTip(text());
}
}
QString KateTabButton::url() const
{
return m_url;
}
void KateTabButton::buttonClicked()
{
// once down, stay down until another tab is activated
if (isChecked()) {
emit activated(this);
} else {
setChecked(true);
}
}
void KateTabButton::setActivated(bool active)
{
if (isChecked() == active) {
return;
}
setChecked(active);
update();
}
bool KateTabButton::isActivated() const
{
return isChecked();
}
void KateTabButton::paintEvent(QPaintEvent *ev)
{
const int opac = 30;
const int comp = 100 - opac;
QPalette pal = QApplication::palette();
if (m_highlightColor.isValid()) {
QColor col(pal.button().color());
col.setRed((col.red()*comp + m_highlightColor.red()*opac) / 100);
col.setGreen((col.green()*comp + m_highlightColor.green()*opac) / 100);
col.setBlue((col.blue()*comp + m_highlightColor.blue()*opac) / 100);
pal.setColor(QPalette::Button, col);
pal.setColor(QPalette::Background, col);
}
setPalette(pal);
QPushButton::paintEvent(ev);
}
void KateTabButton::contextMenuEvent(QContextMenuEvent *ev)
{
QPixmap colorIcon(22, 22);
QMenu menu(/*text(),*/ this);
QMenu *colorMenu = menu.addMenu(i18n("&Highlight Tab"));
QAction *aNone = colorMenu->addAction(i18n("&None"));
colorMenu->addSeparator();
colorIcon.fill(Qt::red);
QAction *aRed = colorMenu->addAction(colorIcon, i18n("&Red"));
colorIcon.fill(Qt::yellow);
QAction *aYellow = colorMenu->addAction(colorIcon, i18n("&Yellow"));
colorIcon.fill(Qt::green);
QAction *aGreen = colorMenu->addAction(colorIcon, i18n("&Green"));
colorIcon.fill(Qt::cyan);
QAction *aCyan = colorMenu->addAction(colorIcon, i18n("&Cyan"));
colorIcon.fill(Qt::blue);
QAction *aBlue = colorMenu->addAction(colorIcon, i18n("&Blue"));
colorIcon.fill(Qt::magenta);
QAction *aMagenta = colorMenu->addAction(colorIcon, i18n("&Magenta"));
colorMenu->addSeparator();
QAction *aCustomColor = colorMenu->addAction(
QIcon::fromTheme(QStringLiteral("colors")), i18n("C&ustom Color..."));
menu.addSeparator();
QAction *aCloseTab = menu.addAction(i18n("&Close Tab"));
QAction *aCloseOtherTabs = menu.addAction(i18n("Close &Other Tabs"));
QAction *aCloseAllTabs = menu.addAction(i18n("Close &All Tabs"));
QAction *choice = menu.exec(ev->globalPos());
// process the result
if (choice == aNone) {
if (m_highlightColor.isValid()) {
setHighlightColor(QColor());
emit highlightChanged(this);
}
} else if (choice == aRed) {
setHighlightColor(Qt::red);
emit highlightChanged(this);
} else if (choice == aYellow) {
setHighlightColor(Qt::yellow);
emit highlightChanged(this);
} else if (choice == aGreen) {
setHighlightColor(Qt::green);
emit highlightChanged(this);
} else if (choice == aCyan) {
setHighlightColor(Qt::cyan);
emit highlightChanged(this);
} else if (choice == aBlue) {
setHighlightColor(Qt::blue);
emit highlightChanged(this);
} else if (choice == aMagenta) {
setHighlightColor(Qt::magenta);
emit highlightChanged(this);
} else if (choice == aCustomColor) {
QColor newColor = QColorDialog::getColor(m_highlightColor, this);
if (newColor.isValid()) {
setHighlightColor(newColor);
emit highlightChanged(this);
}
} else if (choice == aCloseTab) {
emit closeRequest(this);
} else if (choice == aCloseOtherTabs) {
emit closeOtherTabsRequest(this);
} else if (choice == aCloseAllTabs) {
emit closeAllTabsRequest();
}
}
void KateTabButton::mousePressEvent(QMouseEvent *ev)
{
if (ev->button() == Qt::MidButton) {
if (ev->modifiers() & Qt::ControlModifier) {
// clear tab highlight
setHighlightColor(QColor());
} else {
setHighlightColor(s_predefinedColors[s_currentColor]);
if (++s_currentColor >= s_colorCount) {
s_currentColor = 0;
}
}
ev->accept();
} else {
QPushButton::mousePressEvent(ev);
}
}
void KateTabButton::setButtonID(int button_id)
{
m_buttonId = button_id;
}
int KateTabButton::buttonID() const
{
return m_buttonId;
}
void KateTabButton::setHighlightColor(const QColor &color)
{
if (color.isValid()) {
m_highlightColor = color;
update();
} else if (m_highlightColor.isValid()) {
m_highlightColor = QColor();
update();
}
}
QColor KateTabButton::highlightColor() const
{
return m_highlightColor;
}
void KateTabButton::setModified(bool modified)
{
m_modified = modified;
update();
}
bool KateTabButton::isModified() const
{
return m_modified;
}
// kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on; eol unix;
/* This file is part of the KDE project
*
* Copyright (C) 2014 Dominik Haumann <dhauumann@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KATE_TAB_BUTTON
#define KATE_TAB_BUTTON
#include <QPushButton>
#include "katetabbar.h"
/**
* A \p KateTabButton represents a button on the tab bar. It can either be
* \e activated or \e deactivated. If the state is \e deactivated it will
* be @e activated when the mouse is pressed. It then emits the signal
* @p activated(). The \p KateTabButton's caption can be set with \p setText()
* and an additional pixmap can be shown with \p setPixmap().
*
* @author Dominik Haumann
*/
class KateTabButton : public QPushButton
{
Q_OBJECT
public:
/**
* Constructs a new tab bar button with \a caption and \a parent.
* If the @p docurl is unknown, pass QString().
*/
KateTabButton(const QString &docurl, const QString &caption, int button_id,
QWidget *parent = 0);
virtual ~KateTabButton();
/**
* Activate or deactivate the button. If the button is already down
* and \a active is \e true nothing happens, otherwise the state toggles.
* \note The signal \p activated is \e not emitted.
*/
void setActivated(bool active);
/**
* Check the button status. The return value is \e true, if the button is
* down.
*/
bool isActivated() const;
/**
* Set a unique button id number.
*/
void setButtonID(int button_id);
/**
* Get the unique id number.
*/
int buttonID() const;
/**
* Set the document's url to @p docurl. If unknown, pass QString().
*/
void setURL(const QString &docurl);
/**
* Get the document's url.
*/
QString url() const;
/**
* Set the highlighted state. If @p color.isValid() is \e false the
* button is not highlighted. This does \e not emit the signal
* @p highlightChanged().
* @param color the color
*/
void setHighlightColor(const QColor &color);
/**
* Get the highlight color. If the button is not highlighted then the color
* is invalid, i.e. \p QColor::isValid() returns \e flase.
*/
QColor highlightColor() const;
void setModified(bool modified);
bool isModified() const;
Q_SIGNALS:
/**
* Emitted whenever the button changes state from deactivated to activated.
* @param tabbutton the pressed button (this)
*/
void activated(KateTabButton *tabbutton);
/**
* Emitted whenever the user changes the highlighted state. This can be
* done only via the context menu.
* @param tabbutton the changed button (this)
*/
void highlightChanged(KateTabButton *tabbutton);
/**
* Emitted whenever the user wants to close the tab button.
* @param tabbutton the button that emitted this signal
*/
void closeRequest(KateTabButton *tabbutton);
/**
* Emitted whenever the user wants to close all the tab button except the
* selected one.
* @param tabbutton the button that emitted this signal
*/
void closeOtherTabsRequest(KateTabButton *tabbutton);
/**
* Emitted whenever the user wants to close all the tabs.
*/
void closeAllTabsRequest();
protected Q_SLOTS:
void buttonClicked();
protected:
/** paint eyecandy rectangles around the button */
virtual void paintEvent(QPaintEvent *ev);
/** support for context menu */
virtual void contextMenuEvent(QContextMenuEvent *ev);
/** middle mouse button changes color */
virtual void mousePressEvent(QMouseEvent *ev);
private:
QString m_url;
int m_buttonId;
bool m_modified;
QColor m_highlightColor;
static QColor s_predefinedColors[6];
static const int s_colorCount;
static int s_currentColor;
};
#endif
// kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on; eol unix;
......@@ -27,6 +27,7 @@
#include "kateapp.h"
#include "katesessionmanager.h"
#include "katedebug.h"
#include "katetabbar.h"
#include <KSqueezedTextLabel>
#include <KStringHandler>
......@@ -53,6 +54,10 @@ KateViewSpace::KateViewSpace( KateViewManager *viewManager,
layout->setSpacing(0);
layout->setMargin(0);
m_tabBar = new KateTabBar(this);
layout->addWidget(m_tabBar);
connect(m_tabBar, &KateTabBar::currentChanged, this, &KateViewSpace::changeView);
stack = new QStackedWidget( this );
stack->setFocus();
stack->setSizePolicy (QSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding));
......@@ -108,14 +113,27 @@ KTextEditor::View *KateViewSpace::createView (KTextEditor::Document *doc)
}
}
// add to tab bar
const int index = m_tabBar->addTab(doc->url().toString(), doc->documentName());
Q_ASSERT(index >= 0);
m_viewToTabId[v] = index;
// insert into stack
stack->addWidget(v);
mViewList.append(v);
showView( v );
return v;
}
void KateViewSpace::removeView(KTextEditor::View* v)
{
// remove from tab bar
Q_ASSERT(m_viewToTabId.contains(v));
m_tabBar->removeTab(m_viewToTabId[v]);
m_viewToTabId.remove(v);
// remove from view space
bool active = ( v == currentView() );
mViewList.removeAt ( mViewList.indexOf ( v ) );
......@@ -145,12 +163,26 @@ bool KateViewSpace::showView(KTextEditor::Document *document)
stack->setCurrentWidget( kv );
kv->show();
// raise tab in tab bar
Q_ASSERT(m_viewToTabId.contains(kv));
// m_tabBar->raiseTab(m_viewToTabId[kv]);
m_tabBar->setCurrentTab(m_viewToTabId[kv]);
return true;
}
}
return false;
}