diff --git a/krusader/paneltabbar.cpp b/krusader/paneltabbar.cpp index b600499e..3d22d067 100644 --- a/krusader/paneltabbar.cpp +++ b/krusader/paneltabbar.cpp @@ -1,343 +1,321 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * based on original code from Sebastian Trueg * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "paneltabbar.h" #include "defaults.h" #include "tabactions.h" #include "../krglobal.h" #include "Panel/listpanel.h" // QtCore #include // QtGui #include #include #include // QtWidgets #include #include #include #include #include #include -#define DISPLAY(X) (X.isLocalFile() ? X.path() : X.toDisplayString()) - static const int sDragEnterDelay = 500; // msec PanelTabBar::PanelTabBar(QWidget *parent, TabActions *actions): QTabBar(parent), _maxTabLength(0), _tabClicked(false), _draggingTab(false), _dragTabIndex(-1) { _panelActionMenu = new KActionMenu(i18n("Panel"), this); setAcceptDrops(true); insertAction(actions->actNewTab); insertAction(actions->actLockTab); insertAction(actions->actDupTab); insertAction(actions->actMoveTabToOtherSide); insertAction(actions->actCloseTab); insertAction(actions->actCloseInactiveTabs); insertAction(actions->actCloseDuplicatedTabs); setMovable(true); // enable drag'n'drop _dragTimer = new QTimer(this); _dragTimer->setSingleShot(true); _dragTimer->setInterval(sDragEnterDelay); connect(_dragTimer, &QTimer::timeout, this, [=]() { if (_dragTabIndex != -1 && _dragTabIndex != currentIndex()) { setCurrentIndex(_dragTabIndex); } _dragTabIndex = -1; }); setShape(QTabBar::TriangularSouth); } void PanelTabBar::insertAction(QAction* action) { _panelActionMenu->addAction(action); } int PanelTabBar::addPanel(ListPanel *panel, bool setCurrent, KrPanel *nextTo) { int insertIndex = -1; if (nextTo) { for (int i = 0; i < count(); i++) { if (getPanel(i) == nextTo) { insertIndex = i + 1; break; } } } - const QString text = squeeze(DISPLAY(panel->virtualPath())); + const QString text = squeeze(panel->virtualPath()); const int index = insertIndex != -1 ? insertTab(insertIndex, text) : addTab(text); QVariant v; v.setValue((long long)panel); setTabData(index, v); setIcon(index, panel); // make sure all tabs lengths are correct layoutTabs(); if (setCurrent) setCurrentIndex(index); return index; } ListPanel* PanelTabBar::getPanel(int tabIdx) { QVariant v = tabData(tabIdx); if (v.isNull()) return 0; return (ListPanel*)v.toLongLong(); } void PanelTabBar::changePanel(int tabIdx, ListPanel *panel) { QVariant v; v.setValue((long long)panel); setTabData(tabIdx, v); } ListPanel* PanelTabBar::removePanel(int index, ListPanel* &panelToDelete) { panelToDelete = getPanel(index); // old panel to kill later disconnect(panelToDelete, 0, this, 0); removeTab(index); layoutTabs(); return getPanel(currentIndex()); } ListPanel* PanelTabBar::removeCurrentPanel(ListPanel* &panelToDelete) { return removePanel(currentIndex(), panelToDelete); } void PanelTabBar::updateTab(ListPanel *panel) { // find which is the correct tab for (int i = 0; i < count(); i++) { if ((ListPanel*)tabData(i).toLongLong() == panel) { - setTabText(i, squeeze(DISPLAY(panel->virtualPath()), i)); + setTabText(i, squeeze(panel->virtualPath(), i)); setIcon(i, panel); break; } } } void PanelTabBar::duplicateTab() { int id = currentIndex(); emit newTab(((ListPanel*)tabData(id).toLongLong())->virtualPath()); } void PanelTabBar::setIcon(int index, ListPanel *panel) { setTabIcon(index, panel->isLocked() ? krLoader->loadIcon("lock", KIconLoader::Toolbar, 16) : QIcon()); } -QString PanelTabBar::squeeze(QString text, int index) +QString PanelTabBar::squeeze(const QUrl &url, int tabIndex) { - QString originalText = text; - - KConfigGroup group(krConfig, "Look&Feel"); - bool longNames = group.readEntry("Fullpath Tab Names", _FullPathTabNames); - - if (!longNames) { - while (text.endsWith('/')) - text.truncate(text.length() - 1); - if (text.isEmpty() || text.endsWith(':')) - text += '/'; - else { - QString shortName; - - if (text.contains(":/")) - shortName = text.left(text.indexOf(":/")) + ':'; - - shortName += text.mid(text.lastIndexOf("/") + 1); - text = shortName; - } - - if (index >= 0) - setTabToolTip(index, originalText); - - index = -1; + const QString longText = url.isEmpty() ? i18n("[invalid]") : + url.isLocalFile() ? url.path() : url.toDisplayString(); + if (tabIndex >= 0) + setTabToolTip(tabIndex, longText); + + const KConfigGroup group(krConfig, "Look&Feel"); + const bool showLongNames = group.readEntry("Fullpath Tab Names", _FullPathTabNames); + + QString text; + if (!showLongNames) { + const QString scheme = url.scheme().isEmpty() || url.isLocalFile() ? "" : (url.scheme() + ":"); + const QString host = url.host().isEmpty() ? "" : (url.host() + ":"); + const QString name = url.isLocalFile() && url.fileName().isEmpty() ? "/" : url.fileName(); + text = scheme + host + name; + } else { + text = longText; } - QFontMetrics fm(fontMetrics()); + if (text.isEmpty()) + text = i18nc("invalid URL path", "?"); // set the real max length + QFontMetrics fm(fontMetrics()); _maxTabLength = (static_cast(parent())->width() - (6 * fm.width("W"))) / fm.width("W"); // each tab gets a fair share of the max tab length - int _effectiveTabLength = _maxTabLength / (count() == 0 ? 1 : count()); - - int labelWidth = fm.width("W") * _effectiveTabLength; - int textWidth = fm.width(text); - if (textWidth > labelWidth) { - // start with the dots only - QString squeezedText = "..."; - int squeezedWidth = fm.width(squeezedText); - - // estimate how many letters we can add to the dots on both sides - int letters = text.length() * (labelWidth - squeezedWidth) / textWidth / 2; - if (labelWidth < squeezedWidth) letters = 1; + const int effectiveTabLength = _maxTabLength / (count() == 0 ? 1 : count()); + const int labelWidth = fm.width("W") * effectiveTabLength; + const int textWidth = fm.width(text); + if (textWidth <= labelWidth) + return text; + + // squeeze text - start with the dots only + QString squeezedText = "..."; + int squeezedWidth = fm.width(squeezedText); + + int letters = text.length() * (labelWidth - squeezedWidth) / textWidth / 2; + if (labelWidth < squeezedWidth) + letters = 1; + squeezedText = text.left(letters) + "..." + text.right(letters); + squeezedWidth = fm.width(squeezedText); + + if (squeezedWidth < labelWidth) { + // we estimated too short + // add letters while text < label + do { + letters++; + squeezedText = text.left(letters) + "..." + text.right(letters); + squeezedWidth = fm.width(squeezedText); + } while (squeezedWidth < labelWidth); + letters--; squeezedText = text.left(letters) + "..." + text.right(letters); - squeezedWidth = fm.width(squeezedText); - - if (squeezedWidth < labelWidth) { - // we estimated too short - // add letters while text < label - do { - letters++; - squeezedText = text.left(letters) + "..." + text.right(letters); - squeezedWidth = fm.width(squeezedText); - } while (squeezedWidth < labelWidth); + } else if (squeezedWidth > labelWidth) { + // we estimated too long + // remove letters while text > label + do { letters--; squeezedText = text.left(letters) + "..." + text.right(letters); - } else if (squeezedWidth > labelWidth) { - // we estimated too long - // remove letters while text > label - do { - letters--; - squeezedText = text.left(letters) + "..." + text.right(letters); - squeezedWidth = fm.width(squeezedText); - } while (letters && squeezedWidth > labelWidth); - } - - if (index >= 0) - setTabToolTip(index, originalText); - - if (letters < 5) { - // too few letters added -> we give up squeezing - //return text; - return squeezedText; - } else { - return squeezedText; - } - } else { - //if( index >= 0 ) - // removeTabToolTip( index ); + squeezedWidth = fm.width(squeezedText); + } while (letters && squeezedWidth > labelWidth); + } - return text; - }; + return squeezedText; } void PanelTabBar::resizeEvent(QResizeEvent *e) { QTabBar::resizeEvent(e); layoutTabs(); } void PanelTabBar::mouseMoveEvent(QMouseEvent* e) { QTabBar::mouseMoveEvent(e); if(_tabClicked) { _draggingTab = true; emit draggingTab(e); } } void PanelTabBar::mousePressEvent(QMouseEvent* e) { int clickedTab = tabAt(e->pos()); if (-1 == clickedTab) { // clicked on nothing ... QTabBar::mousePressEvent(e); return; } _tabClicked = true; setCurrentIndex(clickedTab); ListPanel *p = getPanel(clickedTab); if (p) p->slotFocusOnMe(); if (e->button() == Qt::RightButton) { // show the popup menu _panelActionMenu->menu()->popup(e->globalPos()); } else { if (e->button() == Qt::MidButton)// close the current tab emit closeCurrentTab(); } QTabBar::mousePressEvent(e); } void PanelTabBar::mouseReleaseEvent(QMouseEvent* e) { QTabBar::mouseReleaseEvent(e); if(_draggingTab) emit draggingTabFinished(e); _draggingTab = false; _tabClicked = false; } void PanelTabBar::dragEnterEvent(QDragEnterEvent *e) { e->accept(); handleDragEvent(tabAt(e->pos())); QTabBar::dragEnterEvent(e); } void PanelTabBar::dragLeaveEvent(QDragLeaveEvent *) { handleDragEvent(-1); } void PanelTabBar::dragMoveEvent(QDragMoveEvent *e) { e->ignore(); handleDragEvent(tabAt(e->pos())); QTabBar::dragMoveEvent(e); } void PanelTabBar::handleDragEvent(int tabIndex) { if (_dragTabIndex == tabIndex) return; _dragTabIndex = tabIndex; if (_dragTabIndex == -1) { _dragTimer->stop(); } else { _dragTimer->start(); } } void PanelTabBar::layoutTabs() { for (int i = 0; i < count(); i++) { - setTabText(i, squeeze(DISPLAY(((ListPanel*)tabData(i).toLongLong())->virtualPath()), i)); + setTabText(i, squeeze(((ListPanel*)tabData(i).toLongLong())->virtualPath(), i)); } } diff --git a/krusader/paneltabbar.h b/krusader/paneltabbar.h index a2f41510..da35afe2 100644 --- a/krusader/paneltabbar.h +++ b/krusader/paneltabbar.h @@ -1,113 +1,113 @@ /***************************************************************************** * Copyright (C) 2002 Shie Erlich * * Copyright (C) 2002 Rafi Yanai * * based on original code from Sebastian Trueg * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #ifndef PANELTABBAR_H #define PANELTABBAR_H // QtCore #include #include // QtGui #include #include // QtWidgets #include class QMouseEvent; class QAction; class KActionMenu; class KrPanel; class ListPanel; class TabActions; /** * This class extends QTabBar such that right-clicking on a tab pops-up a menu * containing relevant actions for the tab. It also emits signals (caught by PanelManager) * to create a new tab, close the current tab and change a panel when a tab was clicked */ class PanelTabBar : public QTabBar { Q_OBJECT public: PanelTabBar(QWidget *parent, TabActions *actions); public slots: /** * called by PanelManager with an already created panel, and creates the corresponding tab */ int addPanel(ListPanel *panel, bool setCurrent = true, KrPanel *nextTo = 0); ListPanel* getPanel(int tabIdx); void changePanel(int tabIdx, ListPanel *panel); void layoutTabs(); /** * when the user changes the current path in a panel, this method updates the tab accordingly */ void updateTab(ListPanel *panel); /** * actually removes the current tab WITHOUT actually deleting the panel. * returns a pointer to the panel which is going to be displayed next. * panelToDelete returns a reference to the pointer of the soon-to-die panel, to * be used by PanelManager. */ ListPanel* removeCurrentPanel(ListPanel* &panelToDelete); // returns the panel focused after removing the current ListPanel* removePanel(int index, ListPanel* &panelToDelete); signals: /** * emitted when the user right-clicks and selected "close" */ void closeCurrentTab(); /** * emitted when the user right-clicks and selects an action that creates a new tab */ void newTab(const QUrl &path); void draggingTab(QMouseEvent*); void draggingTabFinished(QMouseEvent*); protected: virtual void mouseMoveEvent(QMouseEvent*e) Q_DECL_OVERRIDE; virtual void mousePressEvent(QMouseEvent*) Q_DECL_OVERRIDE; virtual void mouseReleaseEvent(QMouseEvent*) Q_DECL_OVERRIDE; void insertAction(QAction*); - QString squeeze(QString text, int index = -1); + QString squeeze(const QUrl &url, int tabIndex = -1); virtual void dragEnterEvent(QDragEnterEvent *) Q_DECL_OVERRIDE; virtual void dragLeaveEvent(QDragLeaveEvent *) Q_DECL_OVERRIDE; virtual void dragMoveEvent(QDragMoveEvent *) Q_DECL_OVERRIDE; virtual void resizeEvent(QResizeEvent *e) Q_DECL_OVERRIDE; protected slots: void duplicateTab(); private: void setIcon(int index, ListPanel *panel); void handleDragEvent(int tabIndex); KActionMenu *_panelActionMenu; bool _left; int _maxTabLength; bool _tabClicked, _draggingTab; QTimer *_dragTimer; int _dragTabIndex; }; #endif