Add Ability to undock a chat lobby to a window.

This commit is contained in:
Phenom 2020-04-18 14:49:24 +02:00
parent 27bbd50f1f
commit b529de29e6
11 changed files with 362 additions and 62 deletions

View File

@ -418,9 +418,7 @@ void ChatLobbyWidget::addChatPage(ChatLobbyDialog *d)
if(_lobby_infos.find(d->id()) == _lobby_infos.end())
{
ui.stackedWidget->addWidget(d) ;
connect(d,SIGNAL(lobbyLeave(ChatLobbyId)),this,SLOT(unsubscribeChatLobby(ChatLobbyId))) ;
connect(d,SIGNAL(dialogClose(ChatDialog*)),this,SLOT(dialogClose(ChatDialog*)));
connect(d,SIGNAL(typingEventReceived(ChatLobbyId)),this,SLOT(updateTypingStatus(ChatLobbyId))) ;
connect(d,SIGNAL(messageReceived(bool,ChatLobbyId,QDateTime,QString,QString)),this,SLOT(updateMessageChanged(bool,ChatLobbyId,QDateTime,QString,QString))) ;
connect(d,SIGNAL(peerJoined(ChatLobbyId)),this,SLOT(updatePeerEntering(ChatLobbyId))) ;
@ -429,14 +427,33 @@ void ChatLobbyWidget::addChatPage(ChatLobbyDialog *d)
ChatLobbyId id = d->id();
_lobby_infos[id].dialog = d ;
_lobby_infos[id].default_icon = QIcon() ;
_lobby_infos[id].last_typing_event = time(NULL) ;
_lobby_infos[id].last_typing_event = time(nullptr) ;
ChatLobbyInfo linfo ;
if(rsMsgs->getChatLobbyInfo(id,linfo))
_lobby_infos[id].default_icon = (linfo.lobby_flags & RS_CHAT_LOBBY_FLAGS_PUBLIC) ? QIcon(IMAGE_PUBLIC):QIcon(IMAGE_PRIVATE) ;
else
std::cerr << "(EE) cannot find info for room " << std::hex << id << std::dec << std::endl;
ChatLobbyInfo linfo ;
if(rsMsgs->getChatLobbyInfo(id,linfo))
_lobby_infos[id].default_icon = (linfo.lobby_flags & RS_CHAT_LOBBY_FLAGS_PUBLIC) ? QIcon(IMAGE_PUBLIC):QIcon(IMAGE_PRIVATE) ;
else
std::cerr << "(EE) cannot find info for room " << std::hex << id << std::dec << std::endl;
}
ui.stackedWidget->addWidget(d) ;
}
void ChatLobbyWidget::removeChatPage(ChatLobbyDialog *d)
{
// check that the page already exist.
if(_lobby_infos.find(d->id()) != _lobby_infos.end())
{
ui.stackedWidget->removeWidget(d) ;
}
}
void ChatLobbyWidget::dialogClose(ChatDialog* cd)
{
ChatLobbyDialog* d = dynamic_cast<ChatLobbyDialog*>(cd);
if(_lobby_infos.find(d->id()) != _lobby_infos.end())
unsubscribeChatLobby(d->id());
}
void ChatLobbyWidget::setCurrentChatPage(ChatLobbyDialog *d)
@ -708,7 +725,7 @@ void ChatLobbyWidget::createChatLobby()
void ChatLobbyWidget::showLobby(QTreeWidgetItem *item)
{
if (item == NULL || item->type() != TYPE_LOBBY) {
if (item == nullptr || item->type() != TYPE_LOBBY) {
showBlankPage(0) ;
return;
}
@ -718,7 +735,11 @@ void ChatLobbyWidget::showLobby(QTreeWidgetItem *item)
if(_lobby_infos.find(id) == _lobby_infos.end())
showBlankPage(id) ;
else
ui.stackedWidget->setCurrentWidget(_lobby_infos[id].dialog) ;
{
_lobby_infos[id].dialog->showDialog(RS_CHAT_FOCUS);
if (_lobby_infos[id].dialog->isWindowed())
showBlankPage(id, true);
}
}
// this function is for the case where we don't have any identity yet
@ -772,17 +793,17 @@ bool ChatLobbyWidget::showLobbyAnchor(ChatLobbyId id, QString anchor)
{
QTreeWidgetItem *item = getTreeWidgetItem(id) ;
if(item != NULL) {
if(item != nullptr) {
if(item->type() == TYPE_LOBBY) {
if(_lobby_infos.find(id) == _lobby_infos.end()) {
showBlankPage(id) ;
} else {
//ChatLobbyDialog cldChatLobby =_lobby_infos[id].dialog;
ui.stackedWidget->setCurrentWidget(_lobby_infos[id].dialog) ;
ChatLobbyDialog *cldCW=NULL ;
if (NULL != (cldCW = dynamic_cast<ChatLobbyDialog *>(ui.stackedWidget->currentWidget())))
cldCW->getChatWidget()->scrollToAnchor(anchor);
_lobby_infos[id].dialog->showDialog(RS_CHAT_FOCUS);
if (_lobby_infos[id].dialog->isWindowed())
showBlankPage(id, true);
_lobby_infos[id].dialog->getChatWidget()->scrollToAnchor(anchor);
}
ui.lobbyTreeWidget->setCurrentItem(item);
@ -857,20 +878,20 @@ void ChatLobbyWidget::autoSubscribeLobby(QTreeWidgetItem *item)
subscribeChatLobbyAtItem(item);
}
void ChatLobbyWidget::showBlankPage(ChatLobbyId id)
void ChatLobbyWidget::showBlankPage(ChatLobbyId id, bool subscribed /*= false*/)
{
// show the default blank page.
ui.stackedWidget->setCurrentWidget(ui._lobby_blank_page) ;
// Update information
std::vector<VisibleChatLobbyRecord> lobbies;
rsMsgs->getListOfNearbyChatLobbies(lobbies);
rsMsgs->getListOfNearbyChatLobbies(lobbies);
std::list<RsGxsId> my_ids ;
rsIdentity->getOwnIds(my_ids) ;
std::list<RsGxsId> my_ids ;
rsIdentity->getOwnIds(my_ids) ;
trimAnonIds(my_ids) ;
trimAnonIds(my_ids) ;
for(std::vector<VisibleChatLobbyRecord>::const_iterator it(lobbies.begin());it!=lobbies.end();++it)
if( (*it).lobby_id == id)
{
@ -881,8 +902,10 @@ void ChatLobbyWidget::showBlankPage(ChatLobbyId id)
ui.lobbysec_lineEdit->setText( (( (*it).lobby_flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED)?tr("No anonymous IDs"):tr("Anonymous IDs accepted")) );
ui.lobbypeers_lineEdit->setText( QString::number((*it).total_number_of_peers) );
QString text = tr("You're not subscribed to this chat room; Double click-it to enter and chat.") ;
QString text = tr("You're subscribed to this chat room; Double click to show window and chat.") ;
if (!subscribed)
{
text = tr("You're not subscribed to this chat room; Double click-it to enter and chat.") ;
if(my_ids.empty())
{
if( (*it).lobby_flags & RS_CHAT_LOBBY_FLAGS_PGP_SIGNED)
@ -890,8 +913,9 @@ void ChatLobbyWidget::showBlankPage(ChatLobbyId id)
else
text += "\n\n"+tr("You will need to create an identity in order to join chat rooms.") ;
}
}
ui.lobbyInfoLabel->setText(text);
ui.lobbyInfoLabel->setText(text);
return ;
}
@ -1037,6 +1061,8 @@ void ChatLobbyWidget::unsubscribeChatLobby(ChatLobbyId id)
}
ui.stackedWidget->removeWidget(it->second.dialog) ;
disconnect(it->second.dialog,SIGNAL(dialogClose(ChatDialog*)),this,SLOT(dialogClose(ChatDialog*)));
it->second.dialog->leaveLobby();
_lobby_infos.erase(it) ;
}

View File

@ -38,6 +38,7 @@
class RSTreeWidgetItemCompareRole;
class ChatTabWidget ;
class ChatDialog ;
class ChatLobbyDialog ;
class QTextBrowser ;
@ -69,6 +70,7 @@ public:
void setCurrentChatPage(ChatLobbyDialog *) ; // used by ChatLobbyDialog to raise.
void addChatPage(ChatLobbyDialog *) ;
void removeChatPage(ChatLobbyDialog *) ;
bool showLobbyAnchor(ChatLobbyId id, QString anchor) ;
uint unreadCount();
@ -77,6 +79,7 @@ signals:
void unreadCountChanged(uint unreadCount);
protected slots:
void dialogClose(ChatDialog*);
void lobbyChanged();
void lobbyTreeWidgetCustomPopupMenu(QPoint);
void createChatLobby();
@ -87,7 +90,7 @@ protected slots:
void displayChatLobbyEvent(qulonglong lobby_id, int event_type, const RsGxsId& gxs_id, const QString& str);
void readChatLobbyInvites();
void showLobby(QTreeWidgetItem *lobby_item) ;
void showBlankPage(ChatLobbyId id) ;
void showBlankPage(ChatLobbyId id, bool subscribed = false) ;
void unsubscribeChatLobby(ChatLobbyId id) ;
void createIdentityAndSubscribe();
void subscribeChatLobbyAs() ;

View File

@ -62,7 +62,7 @@ const static uint32_t timeToInactivity = 60 * 10; // in seconds
/** Default constructor */
ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::WindowFlags flags)
: ChatDialog(parent, flags), lobbyId(lid),
: ChatDialog(parent, flags), lobbyId(lid), mWindowedSetted(false), mPCWindow(nullptr),
bullet_red_128(":/icons/bullet_red_128.png"), bullet_grey_128(":/icons/bullet_grey_128.png"),
bullet_green_128(":/icons/bullet_green_128.png"), bullet_yellow_128(":/icons/bullet_yellow_128.png")
{
@ -129,6 +129,15 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::Wi
double scaler_factor = S > 25 ? 2.4 : 1.8;
QSize icon_size(scaler_factor * S, scaler_factor * S);
// Add a button to undock dialog.
//
undockButton = new QToolButton;
undockButton->setText(QString());
undockButton->setAutoRaise(true);
connect(undockButton, SIGNAL(clicked()), this , SLOT(toggleWindowed()));
getChatWidget()->addTitleBarWidget(undockButton) ;
// Add a button to invite friends.
//
inviteFriendsButton = new QToolButton ;
@ -201,8 +210,12 @@ ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::Wi
void ChatLobbyDialog::leaveLobby()
{
emit lobbyLeave(id()) ;
emit dialogClose(this);
if (mPCWindow)
mPCWindow = nullptr;// Windows deleted by events just before.
}
void ChatLobbyDialog::inviteFriends()
{
std::cerr << "Inviting friends" << std::endl;
@ -404,12 +417,8 @@ void ChatLobbyDialog::init(const ChatId &/*id*/, const QString &/*title*/)
lastUpdateListTime = 0;
// add to window
ChatLobbyWidget *chatLobbyPage = dynamic_cast<ChatLobbyWidget*>(MainWindow::getPage(MainWindow::ChatLobby));
if (chatLobbyPage) {
chatLobbyPage->addChatPage(this) ;
}
// add to stacked lobby list
setWindowed(false);
/** List of muted Participants */
mutedParticipants.clear() ;
@ -421,11 +430,15 @@ void ChatLobbyDialog::init(const ChatId &/*id*/, const QString &/*title*/)
/** Destructor. */
ChatLobbyDialog::~ChatLobbyDialog()
{
// announce leaving of lobby
if (mPCWindow)
{
mPCWindow->removeDialog(this);
mPCWindow = nullptr;
}
// check that the lobby still exists.
if (mChatId.isLobbyId())
rsMsgs->sendLobbyStatusPeerLeaving(mChatId.toLobbyId());
// announce leaving of lobby
if (mChatId.isLobbyId())
rsMsgs->sendLobbyStatusPeerLeaving(mChatId.toLobbyId());
// save settings
processSettings(false);
@ -910,11 +923,17 @@ void ChatLobbyDialog::showDialog(uint chatflags)
{
if (chatflags & RS_CHAT_FOCUS)
{
MainWindow::showWindow(MainWindow::ChatLobby);
MainPage *p = MainWindow::getPage(MainWindow::ChatLobby);
if (isWindowed() && mPCWindow) {
mPCWindow->showDialog(this, chatflags);
}
else
{
MainWindow::showWindow(MainWindow::ChatLobby);
MainPage *p = MainWindow::getPage(MainWindow::ChatLobby);
if(p != NULL)
dynamic_cast<ChatLobbyWidget*>(p)->setCurrentChatPage(this) ;
if(p)
dynamic_cast<ChatLobbyWidget*>(p)->setCurrentChatPage(this) ;
}
}
}
@ -941,3 +960,54 @@ void ChatLobbyDialog::filterIds()
ui.participantsList->filterItems(filterColumn, text);
}
void ChatLobbyDialog::setWindowed(bool windowed)
{
if (mWindowedSetted && (windowed == isWindowed()) )
{
RsErr() << __PRETTY_FUNCTION__ << " Attempt to set windowed same as last state." << std::endl;
return;
}
mWindowedSetted = true;
// just empiric values
qreal S = QFontMetricsF(font()).height();
int size = static_cast<int>(S > 25.0 ? 2.4 * S : 1.8 * S);
QSize icon_size(size, size);
QIcon icon ;
// chatLobbyPage could be NULL for first autosubscribe lobby as Dialog is created before main widget
ChatLobbyWidget *chatLobbyPage = dynamic_cast<ChatLobbyWidget*>(MainWindow::getPage(MainWindow::ChatLobby));
if (!mPCWindow)
mPCWindow = PopupChatWindow::getWindow(true);
if (windowed)
{
if (chatLobbyPage)
chatLobbyPage->removeChatPage(this);
if (mPCWindow)
mPCWindow->addDialog(this);
undockButton->setToolTip(tr("Redock to Main window"));
icon.addPixmap(QPixmap(":/icons/png/dock.png")) ;
undockButton->setIcon(icon) ;
undockButton->setIconSize(icon_size);
}
else
{
if (mPCWindow)
{
mPCWindow->removeDialog(this);
mPCWindow = nullptr;
}
if (chatLobbyPage)
chatLobbyPage->addChatPage(this);
undockButton->setToolTip(tr("Undock to a new window"));
icon.addPixmap(QPixmap(":/icons/png/undock.png")) ;
undockButton->setIcon(icon) ;
undockButton->setIconSize(icon_size);
}
show();
if (chatLobbyPage)// If not defined, we are on autosubscribe loop of lobby widget constructor. So don't recall it.
showDialog(RS_CHAT_FOCUS);
}

View File

@ -25,6 +25,7 @@
#include "ui_ChatLobbyDialog.h"
#include "gui/common/RSTreeWidgetItem.h"
#include "ChatDialog.h"
#include "PopupChatWindow.h"
Q_DECLARE_METATYPE(RsGxsId)
Q_DECLARE_METATYPE(QList<RsGxsId>)
@ -51,16 +52,20 @@ public:
ChatLobbyId id() const { return lobbyId ;}
void sortParcipants();
inline bool isWindowed() const { return dynamic_cast<PopupChatWindow*>(this->window()) != nullptr; }
public slots:
void leaveLobby() ;
private slots:
void participantsTreeWidgetCustomPopupMenu( QPoint point );
void textBrowserAskContextMenu(QMenu* contextMnu, QString anchorForPosition, const QPoint point);
void inviteFriends() ;
void leaveLobby() ;
void filterChanged(const QString &text);
void showInPeopleTab();
void showInPeopleTab();
void toggleWindowed(){setWindowed(!isWindowed());}
void setWindowed(bool windowed);
signals:
void lobbyLeave(ChatLobbyId) ;
void typingEventReceived(ChatLobbyId) ;
void messageReceived(bool incoming, ChatLobbyId lobby_id, QDateTime time, QString senderName, QString msg) ;
void peerJoined(ChatLobbyId) ;
@ -103,9 +108,13 @@ private:
RSTreeWidgetItemCompareRole *mParticipantCompareRole ;
QToolButton *inviteFriendsButton ;
QToolButton *undockButton ;
QToolButton *inviteFriendsButton ;
QToolButton *unsubscribeButton ;
bool mWindowedSetted;
PopupChatWindow* mPCWindow;
/** Qt Designer generated object */
Ui::ChatLobbyDialog ui;

View File

@ -64,15 +64,13 @@ static PopupChatWindow *instance = NULL;
}
/** Default constructor */
PopupChatWindow::PopupChatWindow(bool tabbed, QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags)
PopupChatWindow::PopupChatWindow(bool tabbed, QWidget *parent, Qt::WindowFlags flags)
: QMainWindow(parent, flags),tabbedWindow(tabbed),firstShow(true)
, chatDialog(nullptr),mEmptyIcon(nullptr)
{
/* Invoke Qt Designer generated QObject setup routine */
ui.setupUi(this);
tabbedWindow = tabbed;
firstShow = true;
chatDialog = NULL;
mEmptyIcon = NULL;
setAttribute(Qt::WA_DeleteOnClose);
ui.tabWidget->setVisible(tabbedWindow);
@ -204,15 +202,16 @@ void PopupChatWindow::addDialog(ChatDialog *dialog)
if (tabbedWindow) {
ui.tabWidget->addDialog(dialog);
} else {
ui.horizontalLayout->addWidget(dialog);
ui.chatcentralLayout->addWidget(dialog);
dialog->addToParent(this);
ui.horizontalLayout->setContentsMargins(0, 0, 0, 0);
chatId = dialog->getChatId();
ui.chatcentralLayout->setContentsMargins(0, 0, 0, 0);
chatId = dialog->getChatId();
chatDialog = dialog;
calculateStyle(dialog);
calculateTitle(dialog);
/* signal toggled is called */
ui.actionSetOnTop->setChecked(PeerSettings->getPrivateChatOnTop(chatId));
ui.actionSetOnTop->setChecked(PeerSettings->getPrivateChatOnTop(chatId));
QObject::connect(dialog, SIGNAL(dialogClose(ChatDialog*)), this, SLOT(dialogClose(ChatDialog*)));
}
@ -233,14 +232,15 @@ void PopupChatWindow::removeDialog(ChatDialog *dialog)
deleteLater();
}
} else {
QObject::disconnect(dialog, SIGNAL(dialogClose(ChatDialog*)), this, SLOT(dialogClose(ChatDialog*)));
if (chatDialog == dialog) {
QObject::disconnect(dialog, SIGNAL(dialogClose(ChatDialog*)), this, SLOT(dialogClose(ChatDialog*)));
saveSettings();
dialog->removeFromParent(this);
ui.horizontalLayout->removeWidget(dialog);
chatDialog = NULL;
chatId = ChatId();
ui.chatcentralLayout->removeWidget(dialog);
chatDialog = nullptr;
chatId = ChatId();
close();
deleteLater();
}
}

View File

@ -17,7 +17,7 @@
<string notr="true">MainWindow</string>
</property>
<widget class="QWidget" name="chatcentralwidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<layout class="QHBoxLayout" name="chatcentralLayout">
<property name="leftMargin">
<number>5</number>
</property>

View File

@ -69,6 +69,7 @@
<file>icons/png/chat-lobbies.png</file>
<file>icons/png/circles.png</file>
<file>icons/png/digital-key.png</file>
<file>icons/png/dock.png</file>
<file>icons/png/empty-circle.png</file>
<file>icons/png/enter.png</file>
<file>icons/png/exit.png</file>
@ -121,6 +122,7 @@
<file>icons/png/thumbs-neutral.png</file>
<file>icons/png/thumbs-up.png</file>
<file>icons/png/typing.png</file>
<file>icons/png/undock.png</file>
<file>icons/png/video.png</file>
<file>icons/quit_128.png</file>
<file>icons/search_red_128.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg4823"
version="1.1"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
xml:space="preserve"
width="80"
height="80"
viewBox="0 0 80 80"
sodipodi:docname="dock.svg"
inkscape:export-filename="/home/phenom/GIT/RetroShare/trunk/retroshare-gui/src/gui/icons/png/dock.png"
inkscape:export-xdpi="153.60001"
inkscape:export-ydpi="153.60001"><metadata
id="metadata4829"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs4827" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview4825"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:zoom="8.34386"
inkscape:cx="-8.1326614"
inkscape:cy="38.591301"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="g4831" /><g
id="g4831"
inkscape:groupmode="layer"
inkscape:label="ink_ext_XXXXXX"
transform="matrix(1.25,0,0,-1.25,0,80)"><path
inkscape:connector-curvature="0"
id="path4835"
style="fill:#039bd5;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 64,32 C 64,14.327 49.673,0 32,0 14.327,0 0,14.327 0,32 0,49.673 14.327,64 32,64 49.673,64 64,49.673 64,32" /><path
inkscape:connector-curvature="0"
id="path5452-3"
style="fill:#000000;fill-opacity:0.15686275;fill-rule:nonzero;stroke:none;stroke-width:2.16372085"
d="M 48,17.599999 C 48,15.3906 46.2094,13.6 44.000001,13.6 h -24 C 17.7906,13.6 16,15.3906 16,17.599999 16,19.809401 17.7906,21.6 20.000001,21.6 h 24 C 46.2094,21.6 48,19.809401 48,17.599999" /><path
inkscape:connector-curvature="0"
id="path5452"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.16372061"
d="M 48,19.999999 C 48,17.7906 46.2094,16 44.000001,16 h -24 C 17.7906,16 16,17.7906 16,19.999999 16,22.209401 17.7906,24 20.000001,24 h 24 C 46.2094,24 48,22.209401 48,19.999999" /><path
sodipodi:type="star"
style="fill:#000000;fill-opacity:0.15686275;stroke-width:0.80000001"
id="path4575-7"
sodipodi:sides="3"
sodipodi:cx="32.203388"
sodipodi:cy="-39.322033"
sodipodi:r1="18.807909"
sodipodi:r2="9.4039545"
sodipodi:arg1="2.6179939"
sodipodi:arg2="3.6651914"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 15.915261,-29.918079 8.144064,-14.105931 8.144064,-14.105932 8.144063,14.105932 8.144063,14.105932 -16.288127,0 z"
transform="matrix(0.98231064,0,0,0.85070592,0.36626977,79.051486)"
inkscape:transform-center-y="5.0000002" /><path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke-width:0.80000001"
id="path4575"
sodipodi:sides="3"
sodipodi:cx="32.203388"
sodipodi:cy="-39.322033"
sodipodi:r1="18.807909"
sodipodi:r2="9.4039545"
sodipodi:arg1="2.6179939"
sodipodi:arg2="3.6651914"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 15.915261,-29.918079 8.144064,-14.105931 8.144064,-14.105932 8.144063,14.105932 8.144063,14.105932 -16.288127,0 z"
transform="matrix(0.98231061,0,0,0.85070593,0.36627025,81.451486)"
inkscape:transform-center-y="5.0000009" /></g></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg4823"
version="1.1"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
xml:space="preserve"
width="80"
height="80"
viewBox="0 0 80 80"
sodipodi:docname="undock.svg"
inkscape:export-filename="/home/phenom/GIT/RetroShare/trunk/retroshare-gui/src/gui/icons/png/undock.png"
inkscape:export-xdpi="153.60001"
inkscape:export-ydpi="153.60001"><metadata
id="metadata4829"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs4827" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview4825"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:zoom="8.34386"
inkscape:cx="-8.1326614"
inkscape:cy="38.591301"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="g4831" /><g
id="g4831"
inkscape:groupmode="layer"
inkscape:label="ink_ext_XXXXXX"
transform="matrix(1.25,0,0,-1.25,0,80)"><path
inkscape:connector-curvature="0"
id="path4835"
style="fill:#039bd5;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 64,32 C 64,14.327 49.673,0 32,0 14.327,0 0,14.327 0,32 0,49.673 14.327,64 32,64 49.673,64 64,49.673 64,32" /><path
inkscape:connector-curvature="0"
id="path5452-3"
style="fill:#000000;fill-opacity:0.15686275;fill-rule:nonzero;stroke:none;stroke-width:2.16372085"
d="M 48,17.599999 C 48,15.3906 46.2094,13.6 44.000001,13.6 h -24 C 17.7906,13.6 16,15.3906 16,17.599999 16,19.809401 17.7906,21.6 20.000001,21.6 h 24 C 46.2094,21.6 48,19.809401 48,17.599999" /><path
inkscape:connector-curvature="0"
id="path5452"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.16372061"
d="M 48,19.999999 C 48,17.7906 46.2094,16 44.000001,16 h -24 C 17.7906,16 16,17.7906 16,19.999999 16,22.209401 17.7906,24 20.000001,24 h 24 C 46.2094,24 48,22.209401 48,19.999999" /><path
sodipodi:type="star"
style="fill:#000000;fill-opacity:0.15686275;stroke-width:0.80000001"
id="path4575-7"
sodipodi:sides="3"
sodipodi:cx="32.203388"
sodipodi:cy="-39.322033"
sodipodi:r1="18.807909"
sodipodi:r2="9.4039545"
sodipodi:arg1="2.6179939"
sodipodi:arg2="3.6651914"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 15.915261,-29.918079 8.144064,-14.105931 8.144064,-14.105932 8.144063,14.105932 8.144063,14.105932 -16.288127,0 z"
transform="matrix(0.98231064,0,0,-0.85070592,0.36626977,4.1485139)"
inkscape:transform-center-y="-5.0000005" /><path
sodipodi:type="star"
style="fill:#ffffff;fill-opacity:1;stroke-width:0.80000001"
id="path4575"
sodipodi:sides="3"
sodipodi:cx="32.203388"
sodipodi:cy="-39.322033"
sodipodi:r1="18.807909"
sodipodi:r2="9.4039545"
sodipodi:arg1="2.6179939"
sodipodi:arg2="3.6651914"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 15.915261,-29.918079 8.144064,-14.105931 8.144064,-14.105932 8.144063,14.105932 8.144063,14.105932 -16.288127,0 z"
transform="matrix(0.98231061,0,0,-0.85070593,0.36627025,6.5485136)"
inkscape:transform-center-y="-5.0000005" /></g></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB