mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-27 09:30:13 +03:00
[Sharing] First step towards proper group sharing
This commit is contained in:
parent
309be57a12
commit
6fb4e59120
9 changed files with 542 additions and 17 deletions
|
@ -54,6 +54,7 @@ set(client_SRCS
|
|||
networksettings.cpp
|
||||
ocsjob.cpp
|
||||
ocssharejob.cpp
|
||||
ocsshareejob.cpp
|
||||
openfilemanager.cpp
|
||||
owncloudgui.cpp
|
||||
owncloudsetupwizard.cpp
|
||||
|
@ -63,6 +64,7 @@ set(client_SRCS
|
|||
share.cpp
|
||||
sharedialog.cpp
|
||||
shareusergroupdialog.cpp
|
||||
sharee.cpp
|
||||
socketapi.cpp
|
||||
sslbutton.cpp
|
||||
sslerrordialog.cpp
|
||||
|
|
46
src/gui/ocsshareejob.cpp
Normal file
46
src/gui/ocsshareejob.cpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) by Roeland Jago Douma <roeland@owncloud.com>
|
||||
*
|
||||
* 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; version 2 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "ocsshareejob.h"
|
||||
|
||||
namespace OCC {
|
||||
|
||||
OcsShareeJob::OcsShareeJob(AccountPtr account, QObject *parent)
|
||||
: OcsJob(account, parent)
|
||||
{
|
||||
setPath("ocs/v1.php/apps/files_sharing/api/v1/sharees");
|
||||
connect(this, SIGNAL(jobFinished(QVariantMap)), SLOT(jobDone(QVariantMap)));
|
||||
|
||||
}
|
||||
|
||||
void OcsShareeJob::getSharees(const QString search,
|
||||
const QString itemType,
|
||||
int page,
|
||||
int perPage)
|
||||
{
|
||||
setVerb("GET");
|
||||
|
||||
addParam(QString::fromLatin1("search"), search);
|
||||
addParam(QString::fromLatin1("itemType"), itemType);
|
||||
addParam(QString::fromLatin1("page"), QString::number(page));
|
||||
addParam(QString::fromLatin1("perPage"), QString::number(perPage));
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
void OcsShareeJob::jobDone(const QVariantMap &reply)
|
||||
{
|
||||
emit shareeJobFinished(reply);
|
||||
}
|
||||
|
||||
}
|
58
src/gui/ocsshareejob.h
Normal file
58
src/gui/ocsshareejob.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (C) by Roeland Jago Douma <roeland@owncloud.com>
|
||||
*
|
||||
* 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; version 2 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef OCSSHAREEJOB_H
|
||||
#define OCSSHAREEJOB_H
|
||||
|
||||
#include "ocsjob.h"
|
||||
#include <QVariantMap>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
/**
|
||||
* @brief The OcsShareeJob class
|
||||
* @ingroup gui
|
||||
*
|
||||
* Fetching sharees from the OCS Sharee API
|
||||
*/
|
||||
class OcsShareeJob : public OcsJob {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
explicit OcsShareeJob(AccountPtr account, QObject *parent = 0);
|
||||
|
||||
/**
|
||||
* Get a list of sharees
|
||||
*
|
||||
* @param path Path to request shares for (default all shares)
|
||||
*/
|
||||
void getSharees(const QString search,
|
||||
const QString itemType,
|
||||
int page = 1,
|
||||
int perPage = 50);
|
||||
signals:
|
||||
/**
|
||||
* Result of the OCS request
|
||||
*
|
||||
* @param reply The reply
|
||||
*/
|
||||
void shareeJobFinished(const QVariantMap &reply);
|
||||
|
||||
private slots:
|
||||
void jobDone(const QVariantMap &reply);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OCSSHAREEJOB_H
|
77
src/gui/sharedialogshare.ui
Normal file
77
src/gui/sharedialogshare.ui
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>OCC::ShareDialogShare</class>
|
||||
<widget class="QWidget" name="OCC::ShareDialogShare">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="sharedWith">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Permissions</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="permissionUpdate">
|
||||
<property name="text">
|
||||
<string>Update</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="permissionCreate">
|
||||
<property name="text">
|
||||
<string>Create</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="permissionDelete">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="permissionShare">
|
||||
<property name="text">
|
||||
<string>Share</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteShareButton">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
159
src/gui/sharee.cpp
Normal file
159
src/gui/sharee.cpp
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright (C) by Roeland Jago Douma <roeland@owncloud.com>
|
||||
*
|
||||
* 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; version 2 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "sharee.h"
|
||||
#include "ocsshareejob.h"
|
||||
|
||||
namespace OCC {
|
||||
|
||||
Sharee::Sharee(const QString shareWith,
|
||||
const QString displayName,
|
||||
const Type type)
|
||||
: _shareWith(shareWith),
|
||||
_displayName(displayName),
|
||||
_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
QString Sharee::shareWith() const
|
||||
{
|
||||
return _shareWith;
|
||||
}
|
||||
|
||||
QString Sharee::displayName() const
|
||||
{
|
||||
return _displayName;
|
||||
}
|
||||
|
||||
Sharee::Type Sharee::type() const
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
|
||||
|
||||
ShareeModel::ShareeModel(AccountPtr account,
|
||||
const QString search,
|
||||
const QString type,
|
||||
QObject *parent)
|
||||
: QAbstractTableModel(parent),
|
||||
_account(account),
|
||||
_search(search),
|
||||
_type(type)
|
||||
{
|
||||
OcsShareeJob *job = new OcsShareeJob(_account, this);
|
||||
connect(job, SIGNAL(shareeJobFinished(QVariantMap)), SLOT(shareesFetched(QVariantMap)));
|
||||
job->getSharees(_search, _type, 1, 50);
|
||||
}
|
||||
|
||||
void ShareeModel::shareesFetched(const QVariantMap &reply)
|
||||
{
|
||||
auto data = reply.value("ocs").toMap().value("data").toMap();
|
||||
|
||||
QVector<QSharedPointer<Sharee>> newSharees;
|
||||
|
||||
/*
|
||||
* Todo properly loop all of this
|
||||
*/
|
||||
auto exact = data.value("exact").toMap();
|
||||
{
|
||||
auto user = exact.value("user").toMap();
|
||||
if (user.size() > 0) {
|
||||
newSharees.append(parseSharee(user));
|
||||
}
|
||||
auto group = exact.value("group").toMap();
|
||||
if (group.size() > 0) {
|
||||
newSharees.append(parseSharee(group));
|
||||
}
|
||||
auto remote = exact.value("remote").toMap();
|
||||
if (remote.size() > 0) {
|
||||
newSharees.append(parseSharee(remote));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto users = data.value("users").toList();
|
||||
foreach(auto user, users) {
|
||||
newSharees.append(parseSharee(user.toMap()));
|
||||
}
|
||||
}
|
||||
{
|
||||
auto groups = data.value("groups").toList();
|
||||
foreach(auto group, groups) {
|
||||
newSharees.append(parseSharee(group.toMap()));
|
||||
}
|
||||
}
|
||||
{
|
||||
auto remotes = data.value("remotes").toList();
|
||||
foreach(auto remote, remotes) {
|
||||
newSharees.append(parseSharee(remote.toMap()));
|
||||
}
|
||||
}
|
||||
|
||||
beginInsertRows(QModelIndex(), _sharees.size(), newSharees.size());
|
||||
_sharees += newSharees;
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
QSharedPointer<Sharee> ShareeModel::parseSharee(const QVariantMap &data)
|
||||
{
|
||||
const QString displayName = data.value("label").toString();
|
||||
const QString shareWith = data.value("value").toMap().value("shareWith").toString();
|
||||
Sharee::Type type = (Sharee::Type)data.value("value").toMap().value("shareType").toInt();
|
||||
|
||||
return QSharedPointer<Sharee>(new Sharee(shareWith, shareWith, type));
|
||||
}
|
||||
|
||||
int ShareeModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return _sharees.size();
|
||||
}
|
||||
|
||||
int ShareeModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
QVariant ShareeModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
auto sharee = _sharees.at(index.row());
|
||||
|
||||
switch(index.column()) {
|
||||
case 0:
|
||||
return sharee->displayName();
|
||||
case 1:
|
||||
return sharee->type();
|
||||
case 2:
|
||||
return sharee->shareWith();
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant ShareeModel::headerData(int section, Qt::Orientation orientation, int role)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << section << orientation << role;
|
||||
if (orientation == Qt::Horizontal) {
|
||||
switch(section) {
|
||||
case 0:
|
||||
return "Name";
|
||||
case 1:
|
||||
return "Type";
|
||||
case 2:
|
||||
return "Id";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
77
src/gui/sharee.h
Normal file
77
src/gui/sharee.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (C) by Roeland Jago Douma <roeland@owncloud.com>
|
||||
*
|
||||
* 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; version 2 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <QObject>
|
||||
#include <QFlags>
|
||||
#include <QAbstractTableModel>
|
||||
#include <QModelIndex>
|
||||
#include <QVariant>
|
||||
#include <QSharedPointer>
|
||||
#include <QVector>
|
||||
|
||||
#include "accountfwd.h"
|
||||
|
||||
namespace OCC {
|
||||
|
||||
class Sharee : public QObject {
|
||||
public:
|
||||
|
||||
enum Type {
|
||||
User = 0,
|
||||
Group = 1,
|
||||
Federated = 6
|
||||
};
|
||||
Q_DECLARE_FLAGS(Types, Type)
|
||||
|
||||
explicit Sharee(const QString shareWith,
|
||||
const QString displayName,
|
||||
const Type type);
|
||||
|
||||
QString shareWith() const;
|
||||
QString displayName() const;
|
||||
Type type() const;
|
||||
|
||||
|
||||
private:
|
||||
QString _shareWith;
|
||||
QString _displayName;
|
||||
Type _type;
|
||||
};
|
||||
|
||||
class ShareeModel : public QAbstractTableModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ShareeModel(AccountPtr account,
|
||||
const QString search,
|
||||
const QString type,
|
||||
QObject *parent = 0);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole);
|
||||
|
||||
QSharedPointer<Sharee> parseSharee(const QVariantMap &data);
|
||||
|
||||
private slots:
|
||||
void shareesFetched(const QVariantMap &reply);
|
||||
|
||||
private:
|
||||
AccountPtr _account;
|
||||
QString _search;
|
||||
QString _type;
|
||||
|
||||
QVector<QSharedPointer<Sharee>> _sharees;
|
||||
};
|
||||
|
||||
}
|
|
@ -25,12 +25,14 @@
|
|||
|
||||
#include "thumbnailjob.h"
|
||||
#include "share.h"
|
||||
#include "sharee.h"
|
||||
|
||||
#include "QProgressIndicator.h"
|
||||
#include <QBuffer>
|
||||
#include <QFileIconProvider>
|
||||
#include <QClipboard>
|
||||
#include <QFileInfo>
|
||||
#include <QCompleter>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
|
@ -50,8 +52,14 @@ ShareUserGroupDialog::ShareUserGroupDialog(AccountPtr account, const QString &sh
|
|||
//Is this a file or folder?
|
||||
_isFile = QFileInfo(localPath).isFile();
|
||||
|
||||
_ui->searchPushButton->setEnabled(false);
|
||||
_ui->shareeView->hide();
|
||||
_ui->searchMorePushButton->hide();
|
||||
_ui->sharePushButton->hide();
|
||||
|
||||
_manager = new ShareManager(_account, this);
|
||||
connect(_manager, SIGNAL(sharesFetched(QList<QSharedPointer<Share>>)), SLOT(slotSharesFetched(QList<QSharedPointer<Share>>)));
|
||||
connect(_manager, SIGNAL(shareCreated(QSharedPointer<Share>)), SLOT(getShares()));
|
||||
}
|
||||
|
||||
void ShareUserGroupDialog::done( int r ) {
|
||||
|
@ -65,6 +73,54 @@ ShareUserGroupDialog::~ShareUserGroupDialog()
|
|||
delete _ui;
|
||||
}
|
||||
|
||||
void ShareUserGroupDialog::on_shareeLineEdit_textEdited(const QString &text)
|
||||
{
|
||||
if (text == "") {
|
||||
_ui->searchPushButton->setEnabled(false);
|
||||
} else {
|
||||
_ui->searchPushButton->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ShareUserGroupDialog::on_searchPushButton_clicked()
|
||||
{
|
||||
ShareeModel *model = new ShareeModel(_account,
|
||||
_ui->shareeLineEdit->text(),
|
||||
_isFile ? QLatin1String("file") : QLatin1String("folder"),
|
||||
_ui->shareeView);
|
||||
_ui->shareeView->setModel(model);
|
||||
|
||||
_ui->shareeView->show();
|
||||
_ui->searchMorePushButton->show();
|
||||
_ui->sharePushButton->show();
|
||||
_ui->sharePushButton->setEnabled(false);
|
||||
}
|
||||
|
||||
void ShareUserGroupDialog::on_searchMorePushButton_clicked()
|
||||
{
|
||||
//TODO IMPLEMENT
|
||||
}
|
||||
|
||||
void ShareUserGroupDialog::on_shareeView_activated()
|
||||
{
|
||||
_ui->sharePushButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void ShareUserGroupDialog::on_sharePushButton_clicked()
|
||||
{
|
||||
const QModelIndex index = _ui->shareeView->currentIndex();
|
||||
|
||||
auto model = _ui->shareeView->model();
|
||||
|
||||
const QModelIndex shareWithIndex = model->index(index.row(), 2);
|
||||
const QModelIndex typeIndex = model->index(index.row(), 1);
|
||||
|
||||
QString shareWith = model->data(shareWithIndex, Qt::DisplayRole).toString();
|
||||
int type = model->data(typeIndex, Qt::DisplayRole).toInt();
|
||||
|
||||
_manager->createShare(_sharePath, (Share::ShareType)type, shareWith, Share::PermissionRead);
|
||||
}
|
||||
|
||||
void ShareUserGroupDialog::getShares()
|
||||
{
|
||||
_manager->fetchShares(_sharePath);
|
||||
|
|
|
@ -74,12 +74,21 @@ public:
|
|||
bool resharingAllowed,
|
||||
QWidget *parent = 0);
|
||||
~ShareUserGroupDialog();
|
||||
|
||||
public slots:
|
||||
void getShares();
|
||||
|
||||
private slots:
|
||||
void slotSharesFetched(const QList<QSharedPointer<Share>> &shares);
|
||||
void done( int r );
|
||||
|
||||
|
||||
void on_shareeLineEdit_textEdited(const QString &text);
|
||||
void on_searchPushButton_clicked();
|
||||
void on_searchMorePushButton_clicked();
|
||||
void on_sharePushButton_clicked();
|
||||
void on_shareeView_activated();
|
||||
|
||||
private:
|
||||
Ui::ShareUserGroupDialog *_ui;
|
||||
AccountPtr _account;
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="errorLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
|
@ -79,7 +79,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
|
||||
|
@ -92,21 +92,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="newShareLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="newSharePushButton">
|
||||
<property name="text">
|
||||
<string>Share</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="3" column="0">
|
||||
<layout class="QVBoxLayout" name="sharesLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
|
@ -117,6 +103,61 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="shareeLineEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="searchPushButton">
|
||||
<property name="text">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="shareeView">
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragDropOverwriteMode">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="searchMorePushButton">
|
||||
<property name="text">
|
||||
<string>Search more</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="sharePushButton">
|
||||
<property name="text">
|
||||
<string>Share</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
|
|
Loading…
Reference in a new issue