0

I'm trying to create a menu action which will tabify all the docks in my QMainWindow, to reduce clutter. After trying to do some arithmetic with iterators (oops!), I realized I needed to use something like the adjacent_iterator from this question. The problem is, it won't compile in my application because dockPair isn't initialized. I really don't understand the implementation or limitations of the adjacent iterator very well, and am not sure if I'm doing something wrong, or if it isn't actually right for my application.

Also, if there is an easier/better way to tabify all the docks than my approach, I'm fine reimplementing the function.

tabify docks:

void mainWindow::tabifyDocks()
{

    // get a list of all the docks
    QList<QDockWidget*> docks = findChildren<QDockWidget*>();

    // first, un-float all the tabs
    std::for_each(docks.begin(), docks.end(), std::bind(&QDockWidget::setFloating, std::placeholders::_1 /* the dock widget*/, false));

    // sort them into dockWidget areas
    QVector<QDockWidget*> topArea, leftArea, rightArea, bottomArea;
    QVector<QVector<QDockWidget*>*> dockAreas;

    dockAreas.push_back(&topArea);
    dockAreas.push_back(&leftArea);
    dockAreas.push_back(&rightArea);
    dockAreas.push_back(&bottomArea);

    std::for_each(docks.begin(), docks.end(), [&] (QDockWidget* dock) 
    {
        if      (dockWidgetArea(dock) ==  Qt::TopDockWidgetArea     )   {topArea.push_back(dock);       this->removeDockWidget(dock); dock->resize(dock->minimumSizeHint());    this->addDockWidget(Qt::TopDockWidgetArea   , dock); dock->setVisible(true);} 
        else if (dockWidgetArea(dock) ==  Qt::LeftDockWidgetArea    )   {leftArea.push_back(dock);      this->removeDockWidget(dock); dock->resize(dock->minimumSizeHint());    this->addDockWidget(Qt::LeftDockWidgetArea  , dock); dock->setVisible(true);}
        else if (dockWidgetArea(dock) ==  Qt::RightDockWidgetArea   )   {rightArea.push_back(dock);     this->removeDockWidget(dock); dock->resize(dock->minimumSizeHint());    this->addDockWidget(Qt::RightDockWidgetArea , dock); dock->setVisible(true);}
        else if (dockWidgetArea(dock) ==  Qt::BottomDockWidgetArea  )   {bottomArea.push_back(dock);    this->removeDockWidget(dock); dock->resize(dock->minimumSizeHint());    this->addDockWidget(Qt::BottomDockWidgetArea, dock); dock->setVisible(true);}
    });

    // then, tab them all       
    for (auto areasItr = dockAreas.begin(); areasItr != dockAreas.end(); areasItr++)
    {
        // within each area, tab all the docks if there are more than 1
        QVector<QDockWidget*> area = **areasItr;
        for (const auto& dockPair : make_adjacent_range(area)) 
        {
            this->tabifyDockWidget(dockPair.first, dockPair.second);
        }
    }
}

compiler errors:

error C2143: syntax error : missing ',' before ':'
error C2530: 'dockPair' : references must be initialized
error C3531: 'dockPair': a symbol whose type contains 'auto' must have an initializer
error C2143: syntax error : missing ';' before '{'
Community
  • 1
  • 1
Nicolas Holthaus
  • 7,763
  • 4
  • 42
  • 97
  • It doesn't work if you use a vector like QVector, instead of using raw pointers? – dfranca Oct 22 '14 at 15:42
  • @danielfranca I think in the end it was a c++11 compiler support issue (msvc2010). I think the code would compile/run as is on a newer version that supports range-based loops. – Nicolas Holthaus Oct 22 '14 at 17:25

1 Answers1

0

The problem is, I was trying to compile this code with MSVC2010, which does not support range-based for loops.

The working code, using normal for loops is as follows:

void mainWindow::tabifyDocks()
{
    // get a list of all the docks
    QList<QDockWidget*> docks = findChildren<QDockWidget*>();

    // first, un-float all the tabs
    std::for_each(docks.begin(), docks.end(), std::bind(&QDockWidget::setFloating, std::placeholders::_1 /* the dock widget*/, false));

    // sort them into dockWidget areas
    QVector<QDockWidget*> topArea, leftArea, rightArea, bottomArea;
    QVector<QVector<QDockWidget*>*> dockAreas;

    dockAreas.push_back(&topArea);
    dockAreas.push_back(&leftArea);
    dockAreas.push_back(&rightArea);
    dockAreas.push_back(&bottomArea);

    std::for_each(docks.begin(), docks.end(), [&] (QDockWidget* dock) 
    {
        if      (dockWidgetArea(dock) ==  Qt::TopDockWidgetArea     )   {topArea.   push_back(dock);    this->removeDockWidget(dock); dock->resize(dock->minimumSizeHint());    this->addDockWidget(Qt::TopDockWidgetArea   , dock); dock->setVisible(true);}
        else if (dockWidgetArea(dock) ==  Qt::LeftDockWidgetArea    )   {leftArea.  push_back(dock);    this->removeDockWidget(dock); dock->resize(dock->minimumSizeHint());    this->addDockWidget(Qt::LeftDockWidgetArea  , dock); dock->setVisible(true);}
        else if (dockWidgetArea(dock) ==  Qt::RightDockWidgetArea   )   {rightArea. push_back(dock);    this->removeDockWidget(dock); dock->resize(dock->minimumSizeHint());    this->addDockWidget(Qt::RightDockWidgetArea , dock); dock->setVisible(true);}
        else if (dockWidgetArea(dock) ==  Qt::BottomDockWidgetArea  )   {bottomArea.push_back(dock);    this->removeDockWidget(dock); dock->resize(dock->minimumSizeHint());    this->addDockWidget(Qt::BottomDockWidgetArea, dock); dock->setVisible(true);}
    });

    // then, tab them all       
    // definition: areas == top && bottom && etc.. 
    // definition: area == top || bottom || etc...
    for (QVector<QVector<QDockWidget*>*>::iterator areasItr = dockAreas.begin(); areasItr != dockAreas.end(); areasItr++)
    {
        // within each area, tab all the docks if there are more than 1
        QVector<QDockWidget*> area = **areasItr;
        auto areaRange = make_adjacent_range(area);
        for (auto areaItr = areaRange.begin(); areaItr != areaRange.end(); ++areaItr) 
        {
            auto dockPair = *areaItr;
            this->tabifyDockWidget(dockPair.first, dockPair.second);
        }
    }
}
Nicolas Holthaus
  • 7,763
  • 4
  • 42
  • 97