mirror of https://github.com/qTox/qTox.git
24 changed files with 913 additions and 216 deletions
@ -0,0 +1,69 @@ |
|||||||
|
/*
|
||||||
|
Copyright © 2015 by The qTox Project |
||||||
|
|
||||||
|
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||||
|
|
||||||
|
qTox is libre 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 3 of the License, or |
||||||
|
(at your option) any later version. |
||||||
|
|
||||||
|
qTox 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 qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/ |
||||||
|
|
||||||
|
#include "genericnetcamview.h" |
||||||
|
#include <QBoxLayout> |
||||||
|
#include <QPushButton> |
||||||
|
#include <QFrame> |
||||||
|
|
||||||
|
GenericNetCamView::GenericNetCamView(QWidget *parent) |
||||||
|
: QWidget(parent) |
||||||
|
{ |
||||||
|
verLayout = new QVBoxLayout(this); |
||||||
|
setWindowTitle(tr("Tox video")); |
||||||
|
|
||||||
|
int spacing = verLayout->spacing(); |
||||||
|
verLayout->setSpacing(0); |
||||||
|
|
||||||
|
QHBoxLayout* buttonLayout = new QHBoxLayout(); |
||||||
|
buttonLayout->addStretch(); |
||||||
|
button = new QPushButton(); |
||||||
|
buttonLayout->addWidget(button); |
||||||
|
connect(button, &QPushButton::clicked, this, &GenericNetCamView::showMessageClicked); |
||||||
|
|
||||||
|
verLayout->addSpacing(spacing); |
||||||
|
verLayout->addLayout(buttonLayout); |
||||||
|
verLayout->addSpacing(spacing); |
||||||
|
|
||||||
|
QFrame* lineFrame = new QFrame(this); |
||||||
|
lineFrame->setStyleSheet("border: 1px solid #c1c1c1;"); |
||||||
|
lineFrame->setFrameShape(QFrame::HLine); |
||||||
|
lineFrame->setMaximumHeight(1); |
||||||
|
verLayout->addWidget(lineFrame); |
||||||
|
|
||||||
|
setShowMessages(false); |
||||||
|
|
||||||
|
setStyleSheet("NetCamView { background-color: #c1c1c1; }"); |
||||||
|
} |
||||||
|
|
||||||
|
void GenericNetCamView::setShowMessages(bool show, bool notify) |
||||||
|
{ |
||||||
|
if (show) |
||||||
|
{ |
||||||
|
button->setText(tr("Show Messages")); |
||||||
|
|
||||||
|
if (notify) |
||||||
|
button->setIcon(QIcon("://ui/chatArea/info.svg")); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
button->setText(tr("Hide Messages")); |
||||||
|
button->setIcon(QIcon()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
/*
|
||||||
|
Copyright © 2015 by The qTox Project |
||||||
|
|
||||||
|
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||||
|
|
||||||
|
qTox is libre 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 3 of the License, or |
||||||
|
(at your option) any later version. |
||||||
|
|
||||||
|
qTox 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 qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef GENERICNETCAMVIEW_H |
||||||
|
#define GENERICNETCAMVIEW_H |
||||||
|
|
||||||
|
#include <QWidget> |
||||||
|
|
||||||
|
class VideoSurface; |
||||||
|
class QPushButton; |
||||||
|
class QVBoxLayout; |
||||||
|
|
||||||
|
class GenericNetCamView : public QWidget |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
public: |
||||||
|
GenericNetCamView(QWidget* parent); |
||||||
|
|
||||||
|
signals: |
||||||
|
void showMessageClicked(); |
||||||
|
|
||||||
|
public slots: |
||||||
|
void setShowMessages(bool show, bool notify = false); |
||||||
|
|
||||||
|
protected: |
||||||
|
QVBoxLayout* verLayout; |
||||||
|
VideoSurface* videoSurface; |
||||||
|
|
||||||
|
private: |
||||||
|
QPushButton* button; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif // GENERICNETCAMVIEW_H
|
@ -0,0 +1,235 @@ |
|||||||
|
/*
|
||||||
|
Copyright © 2015 by The qTox Project |
||||||
|
|
||||||
|
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||||
|
|
||||||
|
qTox is libre 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 3 of the License, or |
||||||
|
(at your option) any later version. |
||||||
|
|
||||||
|
qTox 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 qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/ |
||||||
|
|
||||||
|
#include "groupnetcamview.h" |
||||||
|
#include "src/widget/tool/croppinglabel.h" |
||||||
|
#include "src/video/videosurface.h" |
||||||
|
#include <QScrollArea> |
||||||
|
#include <QTimer> |
||||||
|
#include <QMap> |
||||||
|
#include "src/audio/audio.h" |
||||||
|
|
||||||
|
#include "src/widget/tool/flowlayout.h" |
||||||
|
|
||||||
|
class LabeledVideo : public QFrame |
||||||
|
{ |
||||||
|
public: |
||||||
|
LabeledVideo(QWidget* parent = 0, bool expanding = true) |
||||||
|
: QFrame(parent) |
||||||
|
{ |
||||||
|
//setFrameStyle(QFrame::Box);
|
||||||
|
videoSurface = new VideoSurface(-1, 0, expanding); |
||||||
|
videoSurface->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
||||||
|
videoSurface->setMinimumHeight(96); |
||||||
|
//videoSurface->setMaximumHeight(96);
|
||||||
|
connect(videoSurface, &VideoSurface::ratioChanged, this, &LabeledVideo::updateSize); |
||||||
|
label = new CroppingLabel(this); |
||||||
|
label->setText("Unknown"); |
||||||
|
label->setTextFormat(Qt::PlainText); |
||||||
|
label->setStyleSheet("color: white"); |
||||||
|
//label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||||
|
//qDebug() << label->sizePolicy();
|
||||||
|
label->setAlignment(Qt::AlignCenter); |
||||||
|
|
||||||
|
QVBoxLayout* layout = new QVBoxLayout(this); |
||||||
|
layout->addWidget(videoSurface, 1); |
||||||
|
layout->addWidget(label); |
||||||
|
|
||||||
|
setMouseTracking(true); |
||||||
|
} |
||||||
|
|
||||||
|
~LabeledVideo() |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
VideoSurface* getVideoSurface() const |
||||||
|
{ |
||||||
|
return videoSurface; |
||||||
|
} |
||||||
|
|
||||||
|
void setText(const QString& text) |
||||||
|
{ |
||||||
|
label->setText(text); |
||||||
|
} |
||||||
|
|
||||||
|
QString getText() const |
||||||
|
{ |
||||||
|
return label->text(); |
||||||
|
} |
||||||
|
|
||||||
|
protected: |
||||||
|
void resizeEvent(QResizeEvent* event) final override |
||||||
|
{ |
||||||
|
QWidget::resizeEvent(event); |
||||||
|
updateSize(); |
||||||
|
} |
||||||
|
|
||||||
|
void mousePressEvent(QMouseEvent* event) final override |
||||||
|
{ |
||||||
|
if (videoSurface->isExpanding()) |
||||||
|
{ |
||||||
|
setStyleSheet("QFrame { background-color: #414141; border-radius: 10px; }"); |
||||||
|
selected = true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private slots: |
||||||
|
void updateSize() |
||||||
|
{ |
||||||
|
if (videoSurface->isExpanding()) |
||||||
|
{ |
||||||
|
int width = videoSurface->height() * videoSurface->getRatio(); |
||||||
|
videoSurface->setFixedWidth(width); |
||||||
|
setMaximumWidth(width + layout()->margin() * 2); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private: |
||||||
|
CroppingLabel* label; |
||||||
|
VideoSurface* videoSurface; |
||||||
|
bool selected = false; |
||||||
|
}; |
||||||
|
|
||||||
|
GroupNetCamView::GroupNetCamView(int group, QWidget *parent) |
||||||
|
: GenericNetCamView(parent) |
||||||
|
, group(group) |
||||||
|
{ |
||||||
|
videoLabelSurface = new LabeledVideo(this, false); |
||||||
|
videoSurface = videoLabelSurface->getVideoSurface(); |
||||||
|
//videoSurface->setExpanding(false);
|
||||||
|
videoSurface->setMinimumHeight(256); |
||||||
|
videoSurface->setContentsMargins(6, 6, 6, 6); |
||||||
|
videoLabelSurface->setContentsMargins(0, 0, 0, 0); |
||||||
|
videoLabelSurface->layout()->setMargin(0); |
||||||
|
videoLabelSurface->setStyleSheet("QFrame { background-color: black; }"); |
||||||
|
|
||||||
|
verLayout->insertWidget(0, videoLabelSurface, 1); |
||||||
|
|
||||||
|
QScrollArea* scrollArea = new QScrollArea(); |
||||||
|
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
||||||
|
scrollArea->setStyleSheet("QScrollArea { background-color: black; }"); |
||||||
|
scrollArea->setFrameStyle(QFrame::NoFrame); |
||||||
|
QWidget* widget = new QWidget(nullptr); |
||||||
|
scrollArea->setWidget(widget); |
||||||
|
scrollArea->setWidgetResizable(true); |
||||||
|
horLayout = new QHBoxLayout(widget); |
||||||
|
//FlowLayout* horLayout = new FlowLayout(widget);
|
||||||
|
horLayout->addStretch(); |
||||||
|
|
||||||
|
LabeledVideo* labeledVideo = new LabeledVideo(this); |
||||||
|
horLayout->addWidget(labeledVideo); |
||||||
|
horLayout->setAlignment(labeledVideo, Qt::AlignCenter | Qt::AlignHCenter); |
||||||
|
|
||||||
|
horLayout->addStretch(); |
||||||
|
verLayout->insertWidget(1, scrollArea); |
||||||
|
scrollArea->setMinimumHeight(labeledVideo->height()); |
||||||
|
|
||||||
|
connect(&Audio::getInstance(), &Audio::groupAudioPlayed, this, &GroupNetCamView::groupAudioPlayed); |
||||||
|
|
||||||
|
QTimer* timer = new QTimer(this); |
||||||
|
timer->setInterval(1000); |
||||||
|
connect(timer, &QTimer::timeout, this, &GroupNetCamView::findActivePeer); |
||||||
|
timer->start(); |
||||||
|
} |
||||||
|
|
||||||
|
void GroupNetCamView::clearPeers() |
||||||
|
{ |
||||||
|
QList<int> keys = videoList.keys(); |
||||||
|
|
||||||
|
for (int &i : keys) |
||||||
|
removePeer(i); |
||||||
|
} |
||||||
|
|
||||||
|
void GroupNetCamView::addPeer(int peer, const QString& name) |
||||||
|
{ |
||||||
|
LabeledVideo* labeledVideo = new LabeledVideo(this); |
||||||
|
labeledVideo->setText(name); |
||||||
|
horLayout->insertWidget(horLayout->count() - 1, labeledVideo); |
||||||
|
horLayout->setAlignment(labeledVideo, Qt::AlignCenter | Qt::AlignHCenter); |
||||||
|
PeerVideo peerVideo; |
||||||
|
peerVideo.video = labeledVideo; |
||||||
|
videoList.insert(peer, peerVideo); |
||||||
|
|
||||||
|
findActivePeer(); |
||||||
|
} |
||||||
|
|
||||||
|
void GroupNetCamView::removePeer(int peer) |
||||||
|
{ |
||||||
|
auto peerVideo = videoList.find(peer); |
||||||
|
|
||||||
|
if (peerVideo != videoList.end()) |
||||||
|
{ |
||||||
|
LabeledVideo* labeledVideo = peerVideo.value().video; |
||||||
|
horLayout->removeWidget(labeledVideo); |
||||||
|
labeledVideo->deleteLater(); |
||||||
|
videoList.remove(peer); |
||||||
|
|
||||||
|
findActivePeer(); |
||||||
|
} |
||||||
|
} |
||||||
|
#include <QDebug> |
||||||
|
void GroupNetCamView::setActive(int peer) |
||||||
|
{ |
||||||
|
qDebug() << "HI: " << peer; |
||||||
|
if (peer == -1) |
||||||
|
{ |
||||||
|
// Show self.
|
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
auto peerVideo = videoList.find(peer); |
||||||
|
qDebug() << "BTW" << (peerVideo == videoList.end()); |
||||||
|
|
||||||
|
if (peerVideo != videoList.end()) |
||||||
|
{ |
||||||
|
// When group video exists:
|
||||||
|
// videoSurface->setSource(peerVideo.value()->getVideoSurface()->source);
|
||||||
|
|
||||||
|
videoLabelSurface->setText(peerVideo.value().video->getText()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void GroupNetCamView::groupAudioPlayed(int Group, int peer, unsigned short volume) |
||||||
|
{ |
||||||
|
if (group != Group) |
||||||
|
return; |
||||||
|
|
||||||
|
auto peerVideo = videoList.find(peer); |
||||||
|
|
||||||
|
if (peerVideo != videoList.end()) |
||||||
|
peerVideo.value().volume = volume; |
||||||
|
} |
||||||
|
|
||||||
|
void GroupNetCamView::findActivePeer() |
||||||
|
{ |
||||||
|
int candidate = -1; |
||||||
|
int maximum = 0; |
||||||
|
|
||||||
|
for (auto peer = videoList.begin(); peer != videoList.end(); ++peer) |
||||||
|
{ |
||||||
|
if (peer.value().volume > maximum) |
||||||
|
{ |
||||||
|
maximum = peer.value().volume; |
||||||
|
candidate = peer.key(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
setActive(candidate); |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
/*
|
||||||
|
Copyright © 2015 by The qTox Project |
||||||
|
|
||||||
|
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||||
|
|
||||||
|
qTox is libre 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 3 of the License, or |
||||||
|
(at your option) any later version. |
||||||
|
|
||||||
|
qTox 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 qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef GROUPNETCAMVIEW_H |
||||||
|
#define GROUPNETCAMVIEW_H |
||||||
|
|
||||||
|
#include "genericnetcamview.h" |
||||||
|
#include <QMap> |
||||||
|
|
||||||
|
class LabeledVideo; |
||||||
|
class QHBoxLayout; |
||||||
|
|
||||||
|
class GroupNetCamView : public GenericNetCamView |
||||||
|
{ |
||||||
|
public: |
||||||
|
GroupNetCamView(int group, QWidget* parent = 0); |
||||||
|
void clearPeers(); |
||||||
|
void addPeer(int peer, const QString &name); |
||||||
|
void removePeer(int peer); |
||||||
|
|
||||||
|
public slots: |
||||||
|
void groupAudioPlayed(int group, int peer, unsigned short volume); |
||||||
|
|
||||||
|
private slots: |
||||||
|
void findActivePeer(); |
||||||
|
|
||||||
|
private: |
||||||
|
struct PeerVideo |
||||||
|
{ |
||||||
|
LabeledVideo* video; |
||||||
|
unsigned short volume = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
void setActive(int peer); |
||||||
|
|
||||||
|
QHBoxLayout* horLayout; |
||||||
|
QMap<int, PeerVideo> videoList; |
||||||
|
LabeledVideo* videoLabelSurface; |
||||||
|
int activePeer; |
||||||
|
int group; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif // GROUPNETCAMVIEW_H
|
@ -0,0 +1,190 @@ |
|||||||
|
/****************************************************************************
|
||||||
|
** |
||||||
|
** Copyright (C) 2015 The Qt Company Ltd. |
||||||
|
** Contact: http://www.qt.io/licensing/
|
||||||
|
** |
||||||
|
** This file is part of the examples of the Qt Toolkit. |
||||||
|
** |
||||||
|
** $QT_BEGIN_LICENSE:BSD$ |
||||||
|
** You may use this file under the terms of the BSD license as follows: |
||||||
|
** |
||||||
|
** "Redistribution and use in source and binary forms, with or without |
||||||
|
** modification, are permitted provided that the following conditions are |
||||||
|
** met: |
||||||
|
** * Redistributions of source code must retain the above copyright |
||||||
|
** notice, this list of conditions and the following disclaimer. |
||||||
|
** * Redistributions in binary form must reproduce the above copyright |
||||||
|
** notice, this list of conditions and the following disclaimer in |
||||||
|
** the documentation and/or other materials provided with the |
||||||
|
** distribution. |
||||||
|
** * Neither the name of The Qt Company Ltd nor the names of its |
||||||
|
** contributors may be used to endorse or promote products derived |
||||||
|
** from this software without specific prior written permission. |
||||||
|
** |
||||||
|
** |
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
||||||
|
** |
||||||
|
** $QT_END_LICENSE$ |
||||||
|
** |
||||||
|
****************************************************************************/ |
||||||
|
|
||||||
|
#include <QtWidgets> |
||||||
|
|
||||||
|
#include "flowlayout.h" |
||||||
|
FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing) |
||||||
|
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing) |
||||||
|
{ |
||||||
|
setContentsMargins(margin, margin, margin, margin); |
||||||
|
} |
||||||
|
|
||||||
|
FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing) |
||||||
|
: m_hSpace(hSpacing), m_vSpace(vSpacing) |
||||||
|
{ |
||||||
|
setContentsMargins(margin, margin, margin, margin); |
||||||
|
} |
||||||
|
|
||||||
|
FlowLayout::~FlowLayout() |
||||||
|
{ |
||||||
|
QLayoutItem *item; |
||||||
|
while ((item = takeAt(0))) |
||||||
|
delete item; |
||||||
|
} |
||||||
|
|
||||||
|
void FlowLayout::addItem(QLayoutItem *item) |
||||||
|
{ |
||||||
|
itemList.append(item); |
||||||
|
} |
||||||
|
|
||||||
|
int FlowLayout::horizontalSpacing() const |
||||||
|
{ |
||||||
|
if (m_hSpace >= 0) { |
||||||
|
return m_hSpace; |
||||||
|
} else { |
||||||
|
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
int FlowLayout::verticalSpacing() const |
||||||
|
{ |
||||||
|
if (m_vSpace >= 0) { |
||||||
|
return m_vSpace; |
||||||
|
} else { |
||||||
|
return smartSpacing(QStyle::PM_LayoutVerticalSpacing); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
int FlowLayout::count() const |
||||||
|
{ |
||||||
|
return itemList.size(); |
||||||
|
} |
||||||
|
|
||||||
|
QLayoutItem *FlowLayout::itemAt(int index) const |
||||||
|
{ |
||||||
|
return itemList.value(index); |
||||||
|
} |
||||||
|
|
||||||
|
QLayoutItem *FlowLayout::takeAt(int index) |
||||||
|
{ |
||||||
|
if (index >= 0 && index < itemList.size()) |
||||||
|
return itemList.takeAt(index); |
||||||
|
else |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
Qt::Orientations FlowLayout::expandingDirections() const |
||||||
|
{ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
bool FlowLayout::hasHeightForWidth() const |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
int FlowLayout::heightForWidth(int width) const |
||||||
|
{ |
||||||
|
int height = doLayout(QRect(0, 0, width, 0), true); |
||||||
|
return height; |
||||||
|
} |
||||||
|
|
||||||
|
void FlowLayout::setGeometry(const QRect &rect) |
||||||
|
{ |
||||||
|
QLayout::setGeometry(rect); |
||||||
|
doLayout(rect, false); |
||||||
|
} |
||||||
|
|
||||||
|
QSize FlowLayout::sizeHint() const |
||||||
|
{ |
||||||
|
return minimumSize(); |
||||||
|
} |
||||||
|
|
||||||
|
QSize FlowLayout::minimumSize() const |
||||||
|
{ |
||||||
|
QSize size; |
||||||
|
QLayoutItem *item; |
||||||
|
foreach (item, itemList) |
||||||
|
size = size.expandedTo(item->minimumSize()); |
||||||
|
|
||||||
|
size += QSize(2*margin(), 2*margin()); |
||||||
|
return size; |
||||||
|
} |
||||||
|
|
||||||
|
int FlowLayout::doLayout(const QRect &rect, bool testOnly) const |
||||||
|
{ |
||||||
|
int left, top, right, bottom; |
||||||
|
getContentsMargins(&left, &top, &right, &bottom); |
||||||
|
QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom); |
||||||
|
int x = effectiveRect.x(); |
||||||
|
int y = effectiveRect.y(); |
||||||
|
int lineHeight = 0; |
||||||
|
|
||||||
|
QLayoutItem *item; |
||||||
|
foreach (item, itemList) { |
||||||
|
QWidget *wid = item->widget(); |
||||||
|
int spaceX = horizontalSpacing(); |
||||||
|
if (spaceX == -1) |
||||||
|
spaceX = wid->style()->layoutSpacing( |
||||||
|
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal); |
||||||
|
int spaceY = verticalSpacing(); |
||||||
|
if (spaceY == -1) |
||||||
|
spaceY = wid->style()->layoutSpacing( |
||||||
|
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical); |
||||||
|
int nextX = x + item->sizeHint().width() + spaceX; |
||||||
|
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) { |
||||||
|
x = effectiveRect.x(); |
||||||
|
y = y + lineHeight + spaceY; |
||||||
|
nextX = x + item->sizeHint().width() + spaceX; |
||||||
|
lineHeight = 0; |
||||||
|
} |
||||||
|
|
||||||
|
if (!testOnly) |
||||||
|
item->setGeometry(QRect(QPoint(x, y), item->sizeHint())); |
||||||
|
|
||||||
|
x = nextX; |
||||||
|
lineHeight = qMax(lineHeight, item->sizeHint().height()); |
||||||
|
} |
||||||
|
return y + lineHeight - rect.y() + bottom; |
||||||
|
} |
||||||
|
|
||||||
|
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const |
||||||
|
{ |
||||||
|
QObject *parent = this->parent(); |
||||||
|
if (!parent) { |
||||||
|
return -1; |
||||||
|
} else if (parent->isWidgetType()) { |
||||||
|
QWidget *pw = static_cast<QWidget *>(parent); |
||||||
|
return pw->style()->pixelMetric(pm, 0, pw); |
||||||
|
} else { |
||||||
|
return static_cast<QLayout *>(parent)->spacing(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,76 @@ |
|||||||
|
/****************************************************************************
|
||||||
|
** |
||||||
|
** Copyright (C) 2015 The Qt Company Ltd. |
||||||
|
** Contact: http://www.qt.io/licensing/
|
||||||
|
** |
||||||
|
** This file is part of the examples of the Qt Toolkit. |
||||||
|
** |
||||||
|
** $QT_BEGIN_LICENSE:BSD$ |
||||||
|
** You may use this file under the terms of the BSD license as follows: |
||||||
|
** |
||||||
|
** "Redistribution and use in source and binary forms, with or without |
||||||
|
** modification, are permitted provided that the following conditions are |
||||||
|
** met: |
||||||
|
** * Redistributions of source code must retain the above copyright |
||||||
|
** notice, this list of conditions and the following disclaimer. |
||||||
|
** * Redistributions in binary form must reproduce the above copyright |
||||||
|
** notice, this list of conditions and the following disclaimer in |
||||||
|
** the documentation and/or other materials provided with the |
||||||
|
** distribution. |
||||||
|
** * Neither the name of The Qt Company Ltd nor the names of its |
||||||
|
** contributors may be used to endorse or promote products derived |
||||||
|
** from this software without specific prior written permission. |
||||||
|
** |
||||||
|
** |
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||||
|
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||||
|
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||||
|
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||||
|
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||||
|
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||||
|
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
||||||
|
** |
||||||
|
** $QT_END_LICENSE$ |
||||||
|
** |
||||||
|
****************************************************************************/ |
||||||
|
|
||||||
|
#ifndef FLOWLAYOUT_H |
||||||
|
#define FLOWLAYOUT_H |
||||||
|
|
||||||
|
#include <QLayout> |
||||||
|
#include <QRect> |
||||||
|
#include <QStyle> |
||||||
|
class FlowLayout : public QLayout |
||||||
|
{ |
||||||
|
public: |
||||||
|
explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1); |
||||||
|
explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1); |
||||||
|
~FlowLayout(); |
||||||
|
|
||||||
|
void addItem(QLayoutItem *item) Q_DECL_OVERRIDE; |
||||||
|
int horizontalSpacing() const; |
||||||
|
int verticalSpacing() const; |
||||||
|
Qt::Orientations expandingDirections() const Q_DECL_OVERRIDE; |
||||||
|
bool hasHeightForWidth() const Q_DECL_OVERRIDE; |
||||||
|
int heightForWidth(int) const Q_DECL_OVERRIDE; |
||||||
|
int count() const Q_DECL_OVERRIDE; |
||||||
|
QLayoutItem *itemAt(int index) const Q_DECL_OVERRIDE; |
||||||
|
QSize minimumSize() const Q_DECL_OVERRIDE; |
||||||
|
void setGeometry(const QRect &rect) Q_DECL_OVERRIDE; |
||||||
|
QSize sizeHint() const Q_DECL_OVERRIDE; |
||||||
|
QLayoutItem *takeAt(int index) Q_DECL_OVERRIDE; |
||||||
|
|
||||||
|
private: |
||||||
|
int doLayout(const QRect &rect, bool testOnly) const; |
||||||
|
int smartSpacing(QStyle::PixelMetric pm) const; |
||||||
|
|
||||||
|
QList<QLayoutItem *> itemList; |
||||||
|
int m_hSpace; |
||||||
|
int m_vSpace; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif // FLOWLAYOUT_H
|
Loading…
Reference in new issue