diff --git a/src/browsers/BrowserBreadcrumbWidget.cpp b/src/browsers/BrowserBreadcrumbWidget.cpp index 6c0499ab48..75910d76d6 100644 --- a/src/browsers/BrowserBreadcrumbWidget.cpp +++ b/src/browsers/BrowserBreadcrumbWidget.cpp @@ -1,243 +1,221 @@ /**************************************************************************************** * Copyright (c) 2009 Nikolaj Hald Nielsen * * * * 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, see . * ****************************************************************************************/ #define DEBUG_PREFIX "BrowserBreadcrumbWidget" #include "BrowserBreadcrumbWidget.h" #include "amarokurls/AmarokUrl.h" #include "BrowserBreadcrumbItem.h" #include "BrowserCategoryList.h" #include "browsers/filebrowser/FileBrowser.h" #include "MainWindow.h" #include "widgets/BreadcrumbItemButton.h" #include #include #include #include #include #include BrowserBreadcrumbWidget::BrowserBreadcrumbWidget( QWidget * parent ) : BoxWidget( false, parent) , m_rootList( nullptr ) - , m_childMenuButton( nullptr ) { setFixedHeight( 28 ); setContentsMargins( 3, 0, 3, 0 ); m_breadcrumbArea = new BoxWidget( false, this ); m_breadcrumbArea->setContentsMargins( 0, 0, 0, 0 ); - static_cast( layout() )->setStretchFactor( m_breadcrumbArea, 10 ); + layout()->setStretchFactor( m_breadcrumbArea, 10 ); new BreadcrumbUrlMenuButton( QStringLiteral("navigate"), this ); - - m_spacer = new QWidget( nullptr ); } BrowserBreadcrumbWidget::~BrowserBreadcrumbWidget() { - clearCrumbs(); } void BrowserBreadcrumbWidget::clearCrumbs() { - foreach( BrowserBreadcrumbItem *item, m_items ) + const QList childCrumbs = m_breadcrumbArea->findChildren(QString(), Qt::FindDirectChildrenOnly); + for( auto item : childCrumbs) { - item->hide(); - item->deleteLater(); + delete item; } - m_items.clear(); - - //if we have a final menu button, also delete it. - delete m_childMenuButton; - m_childMenuButton = 0; } void BrowserBreadcrumbWidget::setRootList( BrowserCategoryList * rootList ) { m_rootList = rootList; //update the breadcrumbs every time the view changes. connect( m_rootList, &BrowserCategoryList::viewChanged, this, &BrowserBreadcrumbWidget::updateBreadcrumbs ); updateBreadcrumbs(); } void BrowserBreadcrumbWidget::updateBreadcrumbs() { if( !m_rootList ) return; clearCrumbs(); - m_spacer->setParent( this ); addLevel( m_rootList ); - m_breadcrumbArea->layout()->addWidget( m_spacer ); + + // spacer is the right-most widget + new QWidget(m_breadcrumbArea); showAsNeeded(); } void BrowserBreadcrumbWidget::addLevel( BrowserCategoryList *list ) { BrowserBreadcrumbItem *item = list->breadcrumb(); addBreadCrumbItem( item ); - m_items.append( item ); BrowserCategory *childCategory = list->activeCategory(); if( childCategory ) { item->setActive( false ); //check if this is also a list BrowserCategoryList *childList = qobject_cast( childCategory ); if( childList ) { addLevel( childList ); } else { BrowserBreadcrumbItem *leaf = childCategory->breadcrumb(); addBreadCrumbItem( leaf ); - m_items.append( leaf ); const QList additionalItems = childCategory->additionalItems(); //no children, but check if there are additional breadcrumb levels (for internal navigation in the category) that should be added anyway. - foreach( BrowserBreadcrumbItem *addItem, additionalItems ) + for( BrowserBreadcrumbItem *addItem : additionalItems ) { //hack to ensure that we have not already added it to the front of the breadcrumb... addBreadCrumbItem( addItem ); } if( !additionalItems.isEmpty() ) additionalItems.last()->setActive( true ); else leaf->setActive( true ); } } else { //if this item has children, add a menu button for selecting these. BrowserCategoryList *childList = qobject_cast( list ); if( childList ) { - m_childMenuButton = new BreadcrumbItemMenuButton( m_breadcrumbArea ); + auto childMenuButton = new BreadcrumbItemMenuButton( m_breadcrumbArea ); - QMenu *menu = new QMenu( item ); + auto menu = new QMenu( item ); menu->hide(); QMap childMap = childList->categories(); - QStringList childNames = childMap.keys(); + const QStringList childNames = childMap.keys(); - foreach( const QString &siblingName, childNames ) + for( const QString &siblingName : childNames ) { //no point in adding ourselves to this menu if ( siblingName == list->name() ) continue; BrowserCategory * siblingCategory = childMap.value( siblingName ); QAction * action = menu->addAction( siblingCategory->icon(), siblingCategory->prettyName() ); connect( action, &QAction::triggered, childMap.value( siblingName ), &BrowserCategory::activate ); } - m_childMenuButton->setMenu( menu ); + childMenuButton->setMenu( menu ); //do a little magic to line up items in the menu with the current item int offset = 6; menu->setContentsMargins( offset, 1, 1, 2 ); } item->setActive( true ); } } void BrowserBreadcrumbWidget::addBreadCrumbItem( BrowserBreadcrumbItem *item ) { - item->hide(); - item->setParent( this ); // may be already shown, we want it to be last, so reparent - m_breadcrumbArea->layout()->addWidget( item ); + item->setParent( m_breadcrumbArea ); } void BrowserBreadcrumbWidget::resizeEvent( QResizeEvent *event ) { Q_UNUSED( event ) - // we need to postpone the call, because hideAsNeeded() itself may trigger resizeEvent + // we need to postpone the call, because showAsNeeded() itself may trigger resizeEvent QTimer::singleShot( 0 , this, &BrowserBreadcrumbWidget::showAsNeeded ); } void BrowserBreadcrumbWidget::showAsNeeded() { /* we need to check if there is enough space for all items, if not, we start hiding * items from the left (excluding the home item) until they fit (we never hide the * rightmost item) we also add the hidden levels to the drop down menu of the last * item so they are accessible. */ //make a temp list that includes both regular items and add items QList allItems; - allItems.append( m_items ); - if( m_rootList->activeCategory() ) - allItems.append( m_rootList->activeCategory()->additionalItems() ); - - // filter-out leftover items not parented to m_breadcrumbArea (bug 285712): - QMutableListIterator it( allItems ); - while( it.hasNext() ) - { - if( it.next()->parent() != m_breadcrumbArea ) - it.remove(); - } + allItems.append( m_breadcrumbArea->findChildren(QString(), Qt::FindDirectChildrenOnly)); if( allItems.isEmpty() ) return; int sizeOfFirst = allItems.first()->nominalWidth(); int sizeOfLast = allItems.last()->nominalWidth(); int spaceLeft = width() - ( sizeOfFirst + sizeOfLast + 28 ); allItems.first()->show(); allItems.last()->show(); int numberOfItems = allItems.count(); for( int i = numberOfItems - 2; i > 0; i-- ) { if( allItems.at( i )->nominalWidth() <= spaceLeft ) { allItems.at( i )->show(); spaceLeft -= allItems.at( i )->nominalWidth(); } else { //set spaceLeft to 0 so no items further to the left are shown spaceLeft = 0; allItems.at( i )->hide(); } } } diff --git a/src/browsers/BrowserBreadcrumbWidget.h b/src/browsers/BrowserBreadcrumbWidget.h index 0884430b38..3e8e47b62b 100644 --- a/src/browsers/BrowserBreadcrumbWidget.h +++ b/src/browsers/BrowserBreadcrumbWidget.h @@ -1,114 +1,110 @@ /**************************************************************************************** * Copyright (c) 2009 Nikolaj Hald Nielsen * * * * 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, see . * ****************************************************************************************/ #ifndef BROWSERBREADCRUMBWIDGET_H #define BROWSERBREADCRUMBWIDGET_H #include "widgets/BoxWidget.h" #include #include #include #include class BreadcrumbItemMenuButton; class BrowserBreadcrumbItem; class BrowserCategoryList; /** * A widget for displaying the current state of and navigating the category dig down interface. * * @author Nikolaj Hald Nielsen */ class BrowserBreadcrumbWidget : public BoxWidget { Q_OBJECT public: /** * Constructor * @param parent the parent widget */ explicit BrowserBreadcrumbWidget( QWidget * parent ); /** * Destructor */ ~BrowserBreadcrumbWidget() override; /** * Set the BrowserCategoryList which acts as the "root" of the breadcrumb widget. * A root breadcrumb item is created that represents the lowest level, and the categories * in the list are added to the items drop-down menu. * @param rootList the BrowserCategoryList representing the lowest level in the navigation hirachy */ void setRootList( BrowserCategoryList *rootList ); Q_SIGNALS: /** * Signal emitted when the root breadcrumb item is clicked. */ void toHome(); public Q_SLOTS: /** * Rebuild the list of breadcrumb items corresponding to the current location in the hierarchy. * This also allows for categories that add additional breadcrumb items (such as the file browser) to update the * breadcrumbs when their internal state changes. */ void updateBreadcrumbs(); protected: void resizeEvent( QResizeEvent * event ) override; private Q_SLOTS: /** * Goes through all breadcrumb items and shows the most relevant ones based on * available size. (always shows home icon and the last item) */ void showAsNeeded(); private: /** * Remove all breadcrumb items */ void clearCrumbs(); /** * Recursive function that traverses the tree of BrowserCategoryList's * and adds each one as a level in the breadcrumb. * @param list the root level BrowserCategoryList. */ void addLevel( BrowserCategoryList *list ); /** * Helper function for addLevel() that first hides BrowserBreadcrumbItem, adds it to * to breadcrumb area. */ void addBreadCrumbItem( BrowserBreadcrumbItem *item ); //QStringList m_currentPath; BrowserCategoryList * m_rootList; - QList m_items; - QWidget *m_spacer; BoxWidget *m_breadcrumbArea; - BreadcrumbItemMenuButton *m_childMenuButton; - }; #endif