diff options
Diffstat (limited to 'src/tabwindow')
-rw-r--r-- | src/tabwindow/tabbar.cpp | 242 | ||||
-rw-r--r-- | src/tabwindow/tabbar.h | 61 | ||||
-rw-r--r-- | src/tabwindow/tabwindow.cpp | 436 | ||||
-rw-r--r-- | src/tabwindow/tabwindow.h | 100 |
4 files changed, 839 insertions, 0 deletions
diff --git a/src/tabwindow/tabbar.cpp b/src/tabwindow/tabbar.cpp new file mode 100644 index 00000000..06b90897 --- /dev/null +++ b/src/tabwindow/tabbar.cpp @@ -0,0 +1,242 @@ +/*************************************************************************** + * Copyright (C) 2012 by Andrea Diamantini <adjam7@gmail.com> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * + ***************************************************************************/ + + +#include "tabbar.h" +#include "tabbar.moc" + +#include "tabwindow.h" + +#include <KDebug> +#include <KAcceleratorManager> +#include <KAction> +#include <KLocalizedString> +#include <KMenu> + + +TabBar::TabBar(QWidget *parent) + : KTabBar(parent) +{ + setElideMode(Qt::ElideRight); + + setTabsClosable(true); + setMovable(true); + setAcceptDrops(true); + + // avoid ambiguos shortcuts. See BUG:275858 + KAcceleratorManager::setNoAccel(this); + + // context menu(s) + setContextMenuPolicy(Qt::CustomContextMenu); + + connect(this, SIGNAL(contextMenu(int, QPoint)), this, SLOT(contextMenu(int, QPoint))); + connect(this, SIGNAL(emptyAreaContextMenu(QPoint)), this, SLOT(emptyAreaContextMenu(QPoint))); +} + + +QSize TabBar::tabSizeHint(int index) const +{ + Q_UNUSED(index); + + QWidget* p = qobject_cast<QWidget *>(parent()); + + int maxTabBarWidth = p->size().width(); + + int baseTabWidth = maxTabBarWidth / genericTabNumber; + + int minTabWidth = p->sizeHint().width() / genericTabNumber; + + int w = baseTabWidth; + if (count() >= genericTabNumber) + { + w = minTabWidth; + } + + int h = size().height(); + + QSize ts = QSize(w, h); + return ts; +} + + +void TabBar::cloneTab() +{ + KAction *a = qobject_cast<KAction *>(sender()); + if (a) + { + int index = a->data().toInt(); + emit cloneTab(index); + } +} + + +void TabBar::closeTab() +{ + KAction *a = qobject_cast<KAction *>(sender()); + if (a) + { + int index = a->data().toInt(); + emit closeTab(index); + } +} + + +void TabBar::closeOtherTabs() +{ + KAction *a = qobject_cast<KAction *>(sender()); + if (a) + { + int index = a->data().toInt(); + emit closeOtherTabs(index); + } +} + + +void TabBar::reloadTab() +{ + KAction *a = qobject_cast<KAction *>(sender()); + if (a) + { + int index = a->data().toInt(); + emit reloadTab(index); + } +} + + +void TabBar::detachTab() +{ + KAction *a = qobject_cast<KAction *>(sender()); + if (a) + { + int index = a->data().toInt(); + emit detachTab(index); + } +} + + +void TabBar::reopenLastClosedTab() +{ + KAction *a = qobject_cast<KAction *>(sender()); + if (a) + { + int index = a->data().toInt(); + emit restoreClosedTab(index); + } +} + + +void TabBar::contextMenu(int tab, const QPoint &pos) +{ + TabWindow *w = qobject_cast<TabWindow *>(parent()); + + KAction *a; + + KMenu menu; + + a = new KAction(KIcon("tab-new"), i18n("New &Tab"), this); + connect(a, SIGNAL(triggered(bool)), w, SLOT(newCleanTab())); + menu.addAction(a); + + menu.addSeparator(); // ---------------------------------------------------------------- + + a = new KAction(KIcon("tab-duplicate"), i18n("Clone"), this); + a->setData(tab); + connect(a, SIGNAL(triggered(bool)), this, SLOT(cloneTab())); + menu.addAction(a); + + a = new KAction(KIcon("view-refresh"), i18n("Reload"), this); + connect(a, SIGNAL(triggered(bool)), this, SLOT(reloadTab())); + a->setData(tab); + menu.addAction(a); + + if (count() > 1) + { + a = new KAction(KIcon("tab-detach"), i18n("Detach"), this); + connect(a, SIGNAL(triggered(bool)), this, SLOT(detachTab())); + a->setData(tab); + menu.addAction(a); + } + + menu.addSeparator(); // ---------------------------------------------------------------- + + a = new KAction(KIcon("tab-close"), i18n("&Close"), this); + a->setData(tab); + connect(a, SIGNAL(triggered(bool)), this, SLOT(closeTab())); + menu.addAction(a); + + if (count() > 1) + { + a = new KAction(KIcon("tab-close-other"), i18n("Close &Other Tabs"), this); + connect(a, SIGNAL(triggered(bool)), this, SLOT(closeOtherTabs())); + a->setData(tab); + menu.addAction(a); + } + + menu.addSeparator(); + + + a = new KAction(KIcon("tab-new"), i18n("Open Last Closed Tab"), this); + a->setData(0); // last closed tab has index 0! + connect(a, SIGNAL(triggered(bool)), this, SLOT(reopenLastClosedTab())); + menu.addAction(a); + + if (count() > 1) + { + a = new KAction(KIcon("bookmark-new"), i18n("Bookmarks all tabs"), this); + menu.addAction(a); + } + else + { + a = new KAction(KIcon("bookmark-new"), i18n("Bookmark"), this); + menu.addAction(a); + } + + menu.exec(pos); +} + + +void TabBar::emptyAreaContextMenu(const QPoint &pos) +{ + TabWindow *w = qobject_cast<TabWindow *>(parent()); + + KAction *a; + + KMenu menu; + + a = new KAction(KIcon("tab-new"), i18n("New &Tab"), this); + connect(a, SIGNAL(triggered(bool)), w, SLOT(newCleanTab())); + menu.addAction(a); + + a = new KAction(KIcon("tab-new"), i18n("Open Last Closed Tab"), this); + a->setData(0); // last closed tab has index 0! + menu.addAction(a); + + if (count() > 1) + { + a = new KAction(KIcon("bookmark-new"), i18n("Bookmarks all tabs"), this); + menu.addAction(a); + } + else + { + a = new KAction(KIcon("bookmark-new"), i18n("Bookmark"), this); + menu.addAction(a); + } + + menu.exec(pos); +} diff --git a/src/tabwindow/tabbar.h b/src/tabwindow/tabbar.h new file mode 100644 index 00000000..e3bf6d9a --- /dev/null +++ b/src/tabwindow/tabbar.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (C) 2012 by Andrea Diamantini <adjam7@gmail.com> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * + ***************************************************************************/ + + +#ifndef TAB_BAR +#define TAB_BAR + + +// KDE Includes +#include <KTabBar> + + +class TabBar : public KTabBar +{ + Q_OBJECT + +public: + TabBar(QWidget *parent); + + static const int genericTabNumber = 6; + +protected: + virtual QSize tabSizeHint(int index) const; + +Q_SIGNALS: + void cloneTab(int); + void closeTab(int); + void closeOtherTabs(int); + void reloadTab(int); + void detachTab(int); + void restoreClosedTab(int); + +private Q_SLOTS: + void cloneTab(); + void closeTab(); + void closeOtherTabs(); + void reloadTab(); + void detachTab(); + void reopenLastClosedTab(); + + void contextMenu(int, const QPoint &); + void emptyAreaContextMenu(const QPoint &); +}; + +#endif // TAB_BAR diff --git a/src/tabwindow/tabwindow.cpp b/src/tabwindow/tabwindow.cpp new file mode 100644 index 00000000..4a9a8abf --- /dev/null +++ b/src/tabwindow/tabwindow.cpp @@ -0,0 +1,436 @@ +/*************************************************************************** + * Copyright (C) 2012 by Andrea Diamantini <adjam7@gmail.com> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * + ***************************************************************************/ + + +#include "tabwindow.h" +#include "tabwindow.moc" + +#include "webpage.h" +#include "webwindow.h" +#include "tabbar.h" + +#include "tabhistory.h" + +#include <KAction> +#include <KDebug> +#include <KLocalizedString> +#include <KStandardDirs> +#include <KUrl> + +#include <QApplication> +#include <QDesktopWidget> +#include <QLabel> +#include <QMovie> +#include <QTabBar> +#include <QToolButton> + +#include <QWebHistory> +#include <QWebSettings> + + +TabWindow::TabWindow(QWidget *parent) + : KTabWidget(parent) + , _addTabButton(new QToolButton(this)) + , _openedTabsCounter(0) +{ + // This has to be a window... + setWindowFlags(Qt::Window); + + setContentsMargins(0, 0, 0, 0); + + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + + // set mouse tracking for tab previews + setMouseTracking(true); + + // setting tabbar + TabBar *tabBar = new TabBar(this); + setTabBar(tabBar); + + // connecting tabbar signals + connect(tabBar, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int))); + connect(tabBar, SIGNAL(mouseMiddleClick(int)), this, SLOT(closeTab(int))); + + connect(tabBar, SIGNAL(newTabRequest()), this, SLOT(newCleanTab())); + + connect(tabBar, SIGNAL(cloneTab(int)), this, SLOT(cloneTab(int))); + connect(tabBar, SIGNAL(closeTab(int)), this, SLOT(closeTab(int))); + connect(tabBar, SIGNAL(closeOtherTabs(int)), this, SLOT(closeOtherTabs(int))); + connect(tabBar, SIGNAL(reloadTab(int)), this, SLOT(reloadTab(int))); + connect(tabBar, SIGNAL(detachTab(int)), this, SLOT(detachTab(int))); + connect(tabBar, SIGNAL(restoreClosedTab(int)), this, SLOT(restoreClosedTab(int))); + + // new tab button + KAction* a = new KAction(KIcon("tab-new"), i18n("New &Tab"), this); + _addTabButton->setDefaultAction(a); + _addTabButton->setAutoRaise(true); + _addTabButton->setToolButtonStyle(Qt::ToolButtonIconOnly); + connect(_addTabButton, SIGNAL(triggered(QAction *)), this, SLOT(newCleanTab())); + + connect(this, SIGNAL(currentChanged(int)), this, SLOT(currentChanged(int))); + + // FIXME: Manage sizes... + kDebug() << "SIZE: " << size(); + kDebug() << "SIZE HINT: " << sizeHint(); + + resize(sizeHint()); + +} + + +QSize TabWindow::sizeHint() const +{ + QRect desktopRect = QApplication::desktop()->screenGeometry(); + QSize size = desktopRect.size() * 0.8; + return size; +} + + +TabBar *TabWindow::tabBar() const +{ + TabBar *tabBar = qobject_cast<TabBar *>(QTabWidget::tabBar()); + return tabBar; +} + + +WebWindow *TabWindow::currentWebWindow() const +{ + return webWindow(currentIndex()); +} + + +WebWindow *TabWindow::webWindow(int index) const +{ + WebWindow *tab = qobject_cast<WebWindow *>(this->widget(index)); + if (tab) + { + return tab; + } + + kDebug() << "WebWindow with index " << index << "not found. Returning NULL." ; + return 0; +} + + +WebWindow *TabWindow::prepareNewTab(WebPage *page) +{ + WebWindow *tab; + if (page) + tab = new WebWindow(page, this); + else + tab = new WebWindow(this); + + connect(tab, SIGNAL(titleChanged(QString)), this, SLOT(tabTitleChanged(QString))); + + connect(tab, SIGNAL(loadStarted()), this, SLOT(tabLoadStarted())); + connect(tab, SIGNAL(loadProgress(int)), this, SLOT(tabLoadProgress(int))); + connect(tab, SIGNAL(loadFinished(bool)), this, SLOT(tabLoadFinished(bool))); + + connect(tab, SIGNAL(pageCreated(WebPage *)), this, SLOT(pageCreated(WebPage *))); + + return tab; +} + + +void TabWindow::loadUrlInNewTab(const QUrl &url, TabHistory *history) +{ + WebWindow *tab = prepareNewTab(); + + // Now, the dirty jobs... + addTab(tab, i18n("new tab")); + tab->load(url); + + setCurrentWidget(tab); + + if (history) + { + history->applyHistory(tab->page()->history()); + } + + updateTabBar(); +} + + +void TabWindow::newCleanTab() +{ + QUrl u = QUrl::fromUserInput("/DATI/WEBPAGES/HomePage/index.htm"); + loadUrlInNewTab(u); +} + + +void TabWindow::pageCreated(WebPage *page) +{ + WebWindow *tab = prepareNewTab(page); + + // Now, the dirty jobs... + _openedTabsCounter++; + insertTab(currentIndex() + _openedTabsCounter, tab, i18n("new tab")); + + // Finally, update tab bar... + updateTabBar(); +} + + +void TabWindow::currentChanged(int newIndex) +{ + Q_UNUSED(newIndex); + + _openedTabsCounter = 0; +} + + +void TabWindow::resizeEvent(QResizeEvent *event) +{ + QTabWidget::resizeEvent(event); + updateTabBar(); +} + + +void TabWindow::updateTabBar() +{ + // update tab button position + static bool ButtonInCorner = false; + + int tabWidgetWidth = frameSize().width(); + int tabBarWidth = tabBar()->sizeHint().width(); + + if (tabBarWidth + _addTabButton->width() > tabWidgetWidth) + { + if (ButtonInCorner) + return; + setCornerWidget(_addTabButton); + ButtonInCorner = true; + } + else + { + if (ButtonInCorner) + { + setCornerWidget(0); + ButtonInCorner = false; + } + + _addTabButton->move(tabBarWidth, 0); + _addTabButton->show(); + } +} + + +void TabWindow::tabTitleChanged(const QString &title) +{ + WebWindow *tab = qobject_cast<WebWindow *>(sender()); + if (!tab) + return; + + QString tabTitle = title.isEmpty() ? i18n("(Untitled)") : title; + tabTitle.replace('&', "&&"); + + int index = indexOf(tab); + if (-1 != index) + { + setTabText(index, tabTitle); + } + + // TODO: What about window title? +} + + +void TabWindow::tabLoadStarted() +{ + WebWindow *tab = qobject_cast<WebWindow *>(sender()); + if (!tab) + return; + + int index = indexOf(tab); + if (index != -1) + { + QLabel *label = qobject_cast<QLabel* >(tabBar()->tabButton(index, QTabBar::LeftSide)); + if (!label) + { + label = new QLabel(this); + } + + if (!label->movie()) + { + static QString loadingGitPath = KStandardDirs::locate("appdata" , "pics/loading.mng"); + + QMovie *movie = new QMovie(loadingGitPath, QByteArray(), label); + movie->setSpeed(50); + label->setMovie(movie); + movie->start(); + } + tabBar()->setTabButton(index, QTabBar::LeftSide, 0); + tabBar()->setTabButton(index, QTabBar::LeftSide, label); + } +} + + +void TabWindow::tabLoadProgress(int p) +{ + // FIXME: is this needed? + WebWindow *tab = qobject_cast<WebWindow *>(sender()); + if (!tab) + return; + + int index = indexOf(tab); + kDebug() << "LOADING TAB: " << index << ", PROGRESS: " << p; +} + + +void TabWindow::tabLoadFinished(bool ok) +{ + Q_UNUSED(ok); + + WebWindow *tab = qobject_cast<WebWindow *>(sender()); + if (!tab) + return; + + int index = indexOf(tab); + + if (-1 != index) + { + QLabel *label = qobject_cast<QLabel* >(tabBar()->tabButton(index, QTabBar::LeftSide)); + + QMovie *movie = label->movie(); + movie->stop(); + delete movie; + + label->setMovie(0); + label->setPixmap(tab->icon().pixmap(16, 16)); + } +} + + +void TabWindow::cloneTab(int index) +{ + if (index < 0) + index = currentIndex(); + if (index < 0 || index >= count()) + return; + + QUrl u = webWindow(index)->url(); + QWebHistory* history = webWindow(index)->page()->history(); + TabHistory tHistory(history); + + loadUrlInNewTab(u, &tHistory); +} + + +void TabWindow::closeTab(int index, bool del) +{ + if (index < 0) + index = currentIndex(); + if (index < 0 || index >= count()) + return; + + WebWindow *tabToClose = webWindow(index); + if (!tabToClose) + return; + + // what to do if there is just one tab... + if (count() == 1) + { + kDebug() << "CANNOT CLOSE WINDOW FROM HERE..."; + QUrl u = QUrl::fromUserInput("/DATI/WEBPAGES/HomePage/index.htm"); + currentWebWindow()->load(u); + return; + } + + if (!tabToClose->url().isEmpty() + && tabToClose->url().scheme() != QLatin1String("about") + && !tabToClose->page()->settings()->testAttribute(QWebSettings::PrivateBrowsingEnabled) + ) + { + const int recentlyClosedTabsLimit = 8; + TabHistory history(tabToClose->page()->history()); + history.title = tabToClose->title(); + history.url = tabToClose->url().toString(); + + m_recentlyClosedTabs.removeAll(history); + if (m_recentlyClosedTabs.count() == recentlyClosedTabsLimit) + m_recentlyClosedTabs.removeLast(); + m_recentlyClosedTabs.prepend(history); + } + + removeTab(index); + updateTabBar(); // UI operation: do it ASAP!! + + if (del) + { + tabToClose->deleteLater(); + } +} + + +void TabWindow::closeOtherTabs(int index) +{ + if (index < 0) + index = currentIndex(); + if (index < 0 || index >= count()) + return; + + for (int i = count() - 1; i > index; --i) + { + closeTab(i); + } + + for (int i = index - 1; i >= 0; --i) + { + closeTab(i); + } +} + + +void TabWindow::reloadTab(int index) +{ + // When index is -1 index chooses the current tab + if (index < 0) + index = currentIndex(); + + if (index < 0 || index >= count()) + return; + + WebWindow *reloadingTab = webWindow(index); + QAction *action = reloadingTab->page()->action(QWebPage::Reload); + action->trigger(); +} + + +void TabWindow::reloadAllTabs() +{ + for (int i = 0; i < count(); ++i) + { + reloadTab(i); + } +} + + +void TabWindow::restoreClosedTab(int i) +{ + if (m_recentlyClosedTabs.isEmpty()) + return; + + TabHistory history = m_recentlyClosedTabs.takeAt(i); + + QUrl u = QUrl(history.url); + + loadUrlInNewTab(u, &history); + + // just to get sure... + m_recentlyClosedTabs.removeAll(history); +} diff --git a/src/tabwindow/tabwindow.h b/src/tabwindow/tabwindow.h new file mode 100644 index 00000000..147fac40 --- /dev/null +++ b/src/tabwindow/tabwindow.h @@ -0,0 +1,100 @@ +/*************************************************************************** + * Copyright (C) 2012 by Andrea Diamantini <adjam7@gmail.com> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * + ***************************************************************************/ + + + +#ifndef TAB_WINDOW +#define TAB_WINDOW + + +#include <KTabWidget> + +class QLabel; +class QUrl; +class QToolButton; +class QWebHistory; + +class TabHistory; + +class TabBar; +class WebPage; +class WebWindow; + + +class TabWindow : public KTabWidget +{ + Q_OBJECT + +public: + TabWindow(QWidget *parent = 0); + + virtual QSize sizeHint() const; + + WebWindow* currentWebWindow() const; + WebWindow* webWindow(int index) const; + + TabBar* tabBar() const; + +public Q_SLOTS: + void loadUrlInNewTab(const QUrl &, TabHistory *history = 0); + void newCleanTab(); + +private: + /** + * Updates tabbar and add new tab button position + */ + void updateTabBar(); + + /** + * Prepares the new WebWindow to be open + */ + WebWindow *prepareNewTab(WebPage *page = 0); + +private Q_SLOTS: + void tabTitleChanged(const QString &); + + void tabLoadStarted(); + void tabLoadProgress(int); + void tabLoadFinished(bool); + + void pageCreated(WebPage *); + + void currentChanged(int); + + // Indexed slots + void cloneTab(int index = -1); + void closeTab(int index = -1, bool del = true); + void closeOtherTabs(int index = -1); + void reloadTab(int index = -1); + void reloadAllTabs(); + void restoreClosedTab(int i); + +protected: + virtual void resizeEvent(QResizeEvent *); + +private: + // the new tab button + QToolButton *_addTabButton; + + int _openedTabsCounter; + + QList<TabHistory> m_recentlyClosedTabs; +}; + +#endif // TAB_WINDOW |