Add icons of selected desktop to Desktop TabBox

To support this feature the DesktopModel is turned into a tree model with
the desktops on the root level and the Client's at the next level.

In the view a VisualDataModel is used which kind of supports a tree model
by setting the root index. A list view is added underneath all the
desktops showing the icons of the windows on the desktop one switches to.

BUG: 306187
FIXED-IN: 4.11
REVIEW: 108445
icc-effect-5.14.5
Martin Gräßlin 2013-01-17 08:53:09 +01:00
parent c3423b15e7
commit 54b263e7b6
4 changed files with 125 additions and 23 deletions

View File

@ -62,7 +62,7 @@ QVariant ClientModel::data(const QModelIndex& index, int role) const
return QVariant();
}
int clientIndex = index.row() * columnCount() + index.column();
int clientIndex = index.row();
if (clientIndex >= m_clientList.count())
return QVariant();
QSharedPointer<TabBoxClient> client = m_clientList[ clientIndex ].toStrongRef();

View File

@ -64,15 +64,24 @@ QPixmap ImageProvider::requestPixmap(const QString &id, QSize *size, const QSize
QStringList parts = id.split('/');
const int row = parts.first().toInt(&ok);
if (!ok) {
return QDeclarativeImageProvider::requestPixmap(id, size, requestedSize);
return QPixmap();
}
const QModelIndex index = m_model->index(row, 0);
QModelIndex parentIndex;
const int parentRow = parts.at(1).toInt(&ok);
if (ok) {
// we have parent index
parentIndex = m_model->index(parentRow, 0);
if (!parentIndex.isValid()) {
return QPixmap();
}
}
const QModelIndex index = m_model->index(row, 0, parentIndex);
if (!index.isValid()) {
return QDeclarativeImageProvider::requestPixmap(id, size, requestedSize);
return QPixmap();
}
TabBoxClient* client = static_cast< TabBoxClient* >(index.model()->data(index, ClientModel::ClientRole).value<void *>());
if (!client) {
return QDeclarativeImageProvider::requestPixmap(id, size, requestedSize);
return QPixmap();
}
QSize s(32, 32);
@ -92,9 +101,9 @@ QPixmap ImageProvider::requestPixmap(const QString &id, QSize *size, const QSize
if (parts.size() > 2) {
KIconEffect *effect = KIconLoader::global()->iconEffect();
KIconLoader::States state = KIconLoader::DefaultState;
if (parts.at(2) == QLatin1String("selected")) {
if (parts.last() == QLatin1String("selected")) {
state = KIconLoader::ActiveState;
} else if (parts.at(2) == QLatin1String("disabled")) {
} else if (parts.last() == QLatin1String("disabled")) {
state = KIconLoader::DisabledState;
}
icon = effect->apply(icon, KIconLoader::Desktop, state);

View File

@ -42,10 +42,16 @@ DesktopModel::~DesktopModel()
QVariant DesktopModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid())
if (!index.isValid() || index.column() != 0)
return QVariant();
int desktopIndex = index.row() * columnCount() + index.column();
if (index.parent().isValid()) {
// parent is valid -> access to Client
ClientModel *model = m_clientModels[ m_desktopList[ index.internalId() - 1] ];
return model->data(model->index(index.row(), 0), role);
}
const int desktopIndex = index.row();
if (desktopIndex >= m_desktopList.count())
return QVariant();
switch(role) {
@ -69,21 +75,49 @@ int DesktopModel::columnCount(const QModelIndex& parent) const
int DesktopModel::rowCount(const QModelIndex& parent) const
{
Q_UNUSED(parent)
if (parent.isValid()) {
if (parent.internalId() != 0 || parent.row() >= m_desktopList.count()) {
return 0;
}
const int desktop = m_desktopList.at(parent.row());
const ClientModel *model = m_clientModels.value(desktop);
return model->rowCount();
}
return m_desktopList.count();
}
QModelIndex DesktopModel::parent(const QModelIndex& child) const
{
Q_UNUSED(child)
return QModelIndex();
if (!child.isValid() || child.internalId() == 0) {
return QModelIndex();
}
const int row = child.internalId() -1;
if (row >= m_desktopList.count()) {
return QModelIndex();
}
return createIndex(row, 0);
}
QModelIndex DesktopModel::index(int row, int column, const QModelIndex& parent) const
{
Q_UNUSED(parent)
int index = row * columnCount() + column;
if (index > m_desktopList.count() || m_desktopList.isEmpty())
if (column != 0) {
return QModelIndex();
}
if (row < 0) {
return QModelIndex();
}
if (parent.isValid()) {
if (parent.row() < 0 || parent.row() >= m_desktopList.count() || parent.internalId() != 0) {
return QModelIndex();
}
const int desktop = m_desktopList.at(parent.row());
const ClientModel *model = m_clientModels.value(desktop);
if (row >= model->rowCount()) {
return QModelIndex();
}
return createIndex(row, column, parent.row() + 1);
}
if (row > m_desktopList.count() || m_desktopList.isEmpty())
return QModelIndex();
return createIndex(row, column);
}
@ -92,14 +126,12 @@ QModelIndex DesktopModel::desktopIndex(int desktop) const
{
if (desktop > m_desktopList.count())
return QModelIndex();
int index = m_desktopList.indexOf(desktop);
int row = index / columnCount();
int column = index % columnCount();
return createIndex(row, column);
return createIndex(m_desktopList.indexOf(desktop), 0);
}
void DesktopModel::createDesktopList()
{
beginResetModel();
m_desktopList.clear();
qDeleteAll(m_clientModels);
m_clientModels.clear();
@ -126,7 +158,7 @@ void DesktopModel::createDesktopList()
break;
}
}
reset();
endResetModel();
}
} // namespace Tabbox

View File

@ -28,7 +28,7 @@ Item {
property bool allDesktops: true
property string longestCaption: ""
property int optimalWidth: listView.maxRowWidth
property int optimalHeight: listView.rowHeight * listView.count + background.topMargin + background.bottomMargin
property int optimalHeight: listView.rowHeight * listView.count + clientArea.height + 4 + background.topMargin + background.bottomMargin
property bool canStretchX: true
property bool canStretchY: false
property string maskImagePath: background.maskImagePath
@ -47,9 +47,16 @@ Item {
function setModel(model) {
listView.model = model;
desktopClientModel.model = model;
desktopClientModel.imageId++;
listView.maxRowWidth = listView.calculateMaxRowWidth();
}
function modelChanged() {
listView.currentIndex = -1;
desktopClientModel.imageId++;
}
PlasmaCore.Theme {
id: theme
}
@ -153,11 +160,14 @@ Item {
// used for image provider URL to trick Qt into reloading icons when the model changes
property int imageId: 0
anchors {
fill: parent
top: parent.top
left: parent.left
right: parent.right
bottom: clientArea.top
topMargin: background.topMargin
leftMargin: background.leftMargin
rightMargin: background.rightMargin
bottomMargin: background.bottomMargin
bottomMargin: clientArea.top
}
clip: true
delegate: listDelegate
@ -170,4 +180,55 @@ Item {
highlightMoveDuration: 250
boundsBehavior: Flickable.StopAtBounds
}
Component {
id: clientIconDelegate
Image {
sourceSize {
width: 16
height: 16
}
width: 16
height: 16
Component.onCompleted: {
source = "image://client/" + index + "/" + listView.currentIndex + "/" + desktopClientModel.imagePathPrefix + "-" + desktopClientModel.imageId;
}
}
}
Item {
id: clientArea
VisualDataModel {
property alias desktopIndex: listView.currentIndex
property int imagePathPrefix: (new Date()).getTime()
property int imageId: 0
id: desktopClientModel
model: clientModel
delegate: clientIconDelegate
onDesktopIndexChanged: {
desktopClientModel.imageId++;
desktopClientModel.rootIndex = desktopClientModel.parentModelIndex();
desktopClientModel.rootIndex = desktopClientModel.modelIndex(desktopClientModel.desktopIndex);
}
}
ListView {
id: iconsListView
model: desktopClientModel
clip: true
orientation: ListView.Horizontal
spacing: 4
anchors {
fill: parent
leftMargin: 34
}
}
height: 18
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
topMargin: 2
leftMargin: background.leftMargin
rightMargin: background.rightMargin
bottomMargin: background.bottomMargin
}
}
}