* flesh out design for wifi settings dialog
* move the pcap shit to a betterer place
This commit is contained in:
parent
a2004785a4
commit
b7946c1384
|
@ -0,0 +1,387 @@
|
|||
/*
|
||||
Copyright 2016-2020 Arisotura
|
||||
|
||||
This file is part of melonDS.
|
||||
|
||||
melonDS 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, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
// direct LAN interface. Currently powered by libpcap, may change.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <pcap/pcap.h>
|
||||
#include "../Wifi.h"
|
||||
#include "LAN_PCap.h"
|
||||
#include "PlatformConfig.h"
|
||||
|
||||
#ifdef __WIN32__
|
||||
#include <iphlpapi.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if_packet.h>
|
||||
#endif
|
||||
|
||||
|
||||
// welp
|
||||
#ifndef PCAP_OPENFLAG_PROMISCUOUS
|
||||
#define PCAP_OPENFLAG_PROMISCUOUS 1
|
||||
#endif
|
||||
|
||||
|
||||
#define DECL_PCAP_FUNC(ret, name, args, args2) \
|
||||
typedef ret (*type_##name) args; \
|
||||
type_##name ptr_##name = NULL; \
|
||||
ret name args { return ptr_##name args2; }
|
||||
|
||||
DECL_PCAP_FUNC(int, pcap_findalldevs, (pcap_if_t** alldevs, char* errbuf), (alldevs,errbuf))
|
||||
DECL_PCAP_FUNC(void, pcap_freealldevs, (pcap_if_t* alldevs), (alldevs))
|
||||
DECL_PCAP_FUNC(pcap_t*, pcap_open_live, (const char* src, int snaplen, int flags, int readtimeout, char* errbuf), (src,snaplen,flags,readtimeout,errbuf))
|
||||
DECL_PCAP_FUNC(void, pcap_close, (pcap_t* dev), (dev))
|
||||
DECL_PCAP_FUNC(int, pcap_setnonblock, (pcap_t* dev, int nonblock, char* errbuf), (dev,nonblock,errbuf))
|
||||
DECL_PCAP_FUNC(int, pcap_sendpacket, (pcap_t* dev, const u_char* data, int len), (dev,data,len))
|
||||
DECL_PCAP_FUNC(int, pcap_dispatch, (pcap_t* dev, int num, pcap_handler callback, u_char* data), (dev,num,callback,data))
|
||||
DECL_PCAP_FUNC(const u_char*, pcap_next, (pcap_t* dev, struct pcap_pkthdr* hdr), (dev,hdr))
|
||||
|
||||
|
||||
namespace LAN_PCap
|
||||
{
|
||||
|
||||
const char* PCapLibNames[] =
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
// TODO: name for npcap in non-WinPCap mode
|
||||
"wpcap.dll",
|
||||
#else
|
||||
// Linux lib names
|
||||
"libpcap.so.1",
|
||||
"libpcap.so",
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
AdapterData* Adapters = NULL;
|
||||
int NumAdapters = 0;
|
||||
|
||||
void* PCapLib = NULL;
|
||||
pcap_t* PCapAdapter = NULL;
|
||||
AdapterData* PCapAdapterData;
|
||||
|
||||
u8 PacketBuffer[2048];
|
||||
int PacketLen;
|
||||
volatile int RXNum;
|
||||
|
||||
|
||||
#define LOAD_PCAP_FUNC(sym) \
|
||||
ptr_##sym = (type_##sym)SDL_LoadFunction(lib, #sym); \
|
||||
if (!ptr_##sym) return false;
|
||||
|
||||
bool TryLoadPCap(void* lib)
|
||||
{
|
||||
LOAD_PCAP_FUNC(pcap_findalldevs)
|
||||
LOAD_PCAP_FUNC(pcap_freealldevs)
|
||||
LOAD_PCAP_FUNC(pcap_open_live)
|
||||
LOAD_PCAP_FUNC(pcap_close)
|
||||
LOAD_PCAP_FUNC(pcap_setnonblock)
|
||||
LOAD_PCAP_FUNC(pcap_sendpacket)
|
||||
LOAD_PCAP_FUNC(pcap_dispatch)
|
||||
LOAD_PCAP_FUNC(pcap_next)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Init(bool open_adapter)
|
||||
{
|
||||
// TODO: how to deal with cases where an adapter is unplugged or changes config??
|
||||
if (!PCapLib)
|
||||
{
|
||||
PCapLib = NULL;
|
||||
|
||||
for (int i = 0; PCapLibNames[i]; i++)
|
||||
{
|
||||
void* lib = SDL_LoadObject(PCapLibNames[i]);
|
||||
if (!lib) continue;
|
||||
|
||||
if (!TryLoadPCap(lib))
|
||||
{
|
||||
SDL_UnloadObject(lib);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("PCap: lib %s, init successful\n", PCapLibNames[i]);
|
||||
PCapLib = lib;
|
||||
break;
|
||||
}
|
||||
|
||||
if (PCapLib == NULL)
|
||||
{
|
||||
printf("PCap: init failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
PCapAdapter = NULL;
|
||||
PacketLen = 0;
|
||||
RXNum = 0;
|
||||
|
||||
NumAdapters = 0;
|
||||
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
int ret;
|
||||
|
||||
pcap_if_t* alldevs;
|
||||
ret = pcap_findalldevs(&alldevs, errbuf);
|
||||
if (ret < 0 || alldevs == NULL)
|
||||
{
|
||||
printf("PCap: no devices available\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
pcap_if_t* dev = alldevs;
|
||||
while (dev) { NumAdapters++; dev = dev->next; }
|
||||
|
||||
Adapters = new AdapterData[NumAdapters];
|
||||
memset(Adapters, 0, sizeof(AdapterData)*NumAdapters);
|
||||
|
||||
AdapterData* adata = &Adapters[0];
|
||||
dev = alldevs;
|
||||
while (dev)
|
||||
{
|
||||
adata->Internal = dev;
|
||||
|
||||
#ifdef __WIN32__
|
||||
// hax
|
||||
int len = strlen(dev->name);
|
||||
len -= 12; if (len > 127) len = 127;
|
||||
strncpy(adata->DeviceName, &dev->name[12], len);
|
||||
adata->DeviceName[len] = '\0';
|
||||
#else
|
||||
strncpy(adata->DeviceName, dev->name, 127);
|
||||
adata->DeviceName[127] = '\0';
|
||||
|
||||
strncpy(adata->FriendlyName, adata->DeviceName, 127);
|
||||
adata->FriendlyName[127] = '\0';
|
||||
#endif // __WIN32__
|
||||
|
||||
dev = dev->next;
|
||||
adata++;
|
||||
}
|
||||
|
||||
#ifdef __WIN32__
|
||||
|
||||
ULONG bufsize = 16384;
|
||||
IP_ADAPTER_ADDRESSES* buf = (IP_ADAPTER_ADDRESSES*)HeapAlloc(GetProcessHeap(), 0, bufsize);
|
||||
ULONG uret = GetAdaptersAddresses(AF_INET, 0, NULL, buf, &bufsize);
|
||||
if (uret == ERROR_BUFFER_OVERFLOW)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
buf = (IP_ADAPTER_ADDRESSES*)HeapAlloc(GetProcessHeap(), 0, bufsize);
|
||||
uret = GetAdaptersAddresses(AF_INET, 0, NULL, buf, &bufsize);
|
||||
}
|
||||
if (uret != ERROR_SUCCESS)
|
||||
{
|
||||
printf("GetAdaptersAddresses() shat itself: %08X\n", uret);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < NumAdapters; i++)
|
||||
{
|
||||
adata = &Adapters[i];
|
||||
IP_ADAPTER_ADDRESSES* addr = buf;
|
||||
while (addr)
|
||||
{
|
||||
if (strcmp(addr->AdapterName, adata->DeviceName))
|
||||
{
|
||||
addr = addr->Next;
|
||||
continue;
|
||||
}
|
||||
|
||||
WideCharToMultiByte(CP_UTF8, 0, addr->FriendlyName, 127, adata->FriendlyName, 127, NULL, NULL);
|
||||
adata->FriendlyName[127] = '\0';
|
||||
|
||||
WideCharToMultiByte(CP_UTF8, 0, addr->Description, 127, adata->Description, 127, NULL, NULL);
|
||||
adata->Description[127] = '\0';
|
||||
|
||||
if (addr->PhysicalAddressLength != 6)
|
||||
{
|
||||
printf("weird MAC addr length %d for %s\n", addr->PhysicalAddressLength, addr->AdapterName);
|
||||
}
|
||||
else
|
||||
memcpy(adata->MAC, addr->PhysicalAddress, 6);
|
||||
|
||||
IP_ADAPTER_UNICAST_ADDRESS* ipaddr = addr->FirstUnicastAddress;
|
||||
while (ipaddr)
|
||||
{
|
||||
SOCKADDR* sa = ipaddr->Address.lpSockaddr;
|
||||
if (sa->sa_family == AF_INET)
|
||||
{
|
||||
struct in_addr sa4 = ((sockaddr_in*)sa)->sin_addr;
|
||||
memcpy(adata->IP_v4, &sa4, 4);
|
||||
}
|
||||
|
||||
ipaddr = ipaddr->Next;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
|
||||
#else
|
||||
|
||||
struct ifaddrs* addrs;
|
||||
if (getifaddrs(&addrs) != 0)
|
||||
{
|
||||
printf("getifaddrs() shat itself :(\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < NumAdapters; i++)
|
||||
{
|
||||
adata = &Adapters[i];
|
||||
struct ifaddrs* curaddr = addrs;
|
||||
while (curaddr)
|
||||
{
|
||||
if (strcmp(curaddr->ifa_name, adata->DeviceName))
|
||||
{
|
||||
curaddr = curaddr->ifa_next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!curaddr->ifa_addr)
|
||||
{
|
||||
printf("Device (%s) does not have an address :/\n", curaddr->ifa_name);
|
||||
curaddr = curaddr->ifa_next;
|
||||
continue;
|
||||
}
|
||||
|
||||
u16 af = curaddr->ifa_addr->sa_family;
|
||||
if (af == AF_INET)
|
||||
{
|
||||
struct sockaddr_in* sa = (sockaddr_in*)curaddr->ifa_addr;
|
||||
memcpy(adata->IP_v4, &sa->sin_addr, 4);
|
||||
}
|
||||
else if (af == AF_PACKET)
|
||||
{
|
||||
struct sockaddr_ll* sa = (sockaddr_ll*)curaddr->ifa_addr;
|
||||
if (sa->sll_halen != 6)
|
||||
printf("weird MAC length %d for %s\n", sa->sll_halen, curaddr->ifa_name);
|
||||
else
|
||||
memcpy(adata->MAC, sa->sll_addr, 6);
|
||||
}
|
||||
|
||||
curaddr = curaddr->ifa_next;
|
||||
}
|
||||
}
|
||||
|
||||
freeifaddrs(addrs);
|
||||
|
||||
#endif // __WIN32__
|
||||
|
||||
if (!open_adapter) return true;
|
||||
if (PCapAdapter) pcap_close(PCapAdapter);
|
||||
|
||||
// open pcap device
|
||||
PCapAdapterData = &Adapters[0];
|
||||
for (int i = 0; i < NumAdapters; i++)
|
||||
{
|
||||
if (!strncmp(Adapters[i].DeviceName, Config::LANDevice, 128))
|
||||
PCapAdapterData = &Adapters[i];
|
||||
}
|
||||
|
||||
dev = (pcap_if_t*)PCapAdapterData->Internal;
|
||||
PCapAdapter = pcap_open_live(dev->name, 2048, PCAP_OPENFLAG_PROMISCUOUS, 1, errbuf);
|
||||
if (!PCapAdapter)
|
||||
{
|
||||
printf("PCap: failed to open adapter %s\n", errbuf);
|
||||
return false;
|
||||
}
|
||||
|
||||
pcap_freealldevs(alldevs);
|
||||
|
||||
if (pcap_setnonblock(PCapAdapter, 1, errbuf) < 0)
|
||||
{
|
||||
printf("PCap: failed to set nonblocking mode\n");
|
||||
pcap_close(PCapAdapter); PCapAdapter = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeInit()
|
||||
{
|
||||
if (PCapLib)
|
||||
{
|
||||
if (PCapAdapter)
|
||||
{
|
||||
pcap_close(PCapAdapter);
|
||||
PCapAdapter = NULL;
|
||||
}
|
||||
|
||||
SDL_UnloadObject(PCapLib);
|
||||
PCapLib = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RXCallback(u_char* blarg, const struct pcap_pkthdr* header, const u_char* data)
|
||||
{
|
||||
while (RXNum > 0);
|
||||
|
||||
if (header->len > 2048-64) return;
|
||||
|
||||
PacketLen = header->len;
|
||||
memcpy(PacketBuffer, data, PacketLen);
|
||||
RXNum = 1;
|
||||
}
|
||||
|
||||
int SendPacket(u8* data, int len)
|
||||
{
|
||||
if (PCapAdapter == NULL)
|
||||
return 0;
|
||||
|
||||
if (len > 2048)
|
||||
{
|
||||
printf("LAN_SendPacket: error: packet too long (%d)\n", len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pcap_sendpacket(PCapAdapter, data, len);
|
||||
// TODO: check success
|
||||
return len;
|
||||
}
|
||||
|
||||
int RecvPacket(u8* data)
|
||||
{
|
||||
if (PCapAdapter == NULL)
|
||||
return 0;
|
||||
|
||||
int ret = 0;
|
||||
if (RXNum > 0)
|
||||
{
|
||||
memcpy(data, PacketBuffer, PacketLen);
|
||||
ret = PacketLen;
|
||||
RXNum = 0;
|
||||
}
|
||||
|
||||
pcap_dispatch(PCapAdapter, 1, RXCallback, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Copyright 2016-2020 Arisotura
|
||||
|
||||
This file is part of melonDS.
|
||||
|
||||
melonDS 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, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef LAN_PCAP_H
|
||||
#define LAN_PCAP_H
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
namespace LAN_PCap
|
||||
{
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char DeviceName[128];
|
||||
char FriendlyName[128];
|
||||
char Description[128];
|
||||
|
||||
u8 MAC[6];
|
||||
u8 IP_v4[4];
|
||||
|
||||
void* Internal;
|
||||
|
||||
} AdapterData;
|
||||
|
||||
|
||||
extern AdapterData* Adapters;
|
||||
extern int NumAdapters;
|
||||
|
||||
|
||||
bool Init(bool open_adapter);
|
||||
void DeInit();
|
||||
|
||||
int SendPacket(u8* data, int len);
|
||||
int RecvPacket(u8* data);
|
||||
|
||||
}
|
||||
|
||||
#endif // LAN_PCAP_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
Copyright 2016-2020 Arisotura
|
||||
|
||||
This file is part of melonDS.
|
||||
|
||||
melonDS 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, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
melonDS 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 melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef LAN_SOCKET_H
|
||||
#define LAN_SOCKET_H
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
namespace LAN_Socket
|
||||
{
|
||||
|
||||
//
|
||||
|
||||
|
||||
bool Init();
|
||||
void DeInit();
|
||||
|
||||
int SendPacket(u8* data, int len);
|
||||
int RecvPacket(u8* data);
|
||||
|
||||
}
|
||||
|
||||
#endif // LAN_SOCKET_H
|
|
@ -0,0 +1,165 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>WifiSettingsDialog</class>
|
||||
<widget class="QDialog" name="WifiSettingsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>479</width>
|
||||
<height>217</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Wifi settings - melonDS</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetFixedSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Local</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="cbBindAnyAddr">
|
||||
<property name="whatsThis">
|
||||
<string><html><head/><body><p>Enabling this allows (theoretically) playing local multiplayer games over a local network. It may or may not help make for a better connection in general.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Bind socket to any address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Online</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>MAC address:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="cbDirectMode">
|
||||
<property name="whatsThis">
|
||||
<string><html><head/><body><p>Direct mode directly routes network traffic to the host network. It is the most reliable, but requires an ethernet connection.</p><p><br/></p><p>Non-direct mode uses a layer of emulation to get around this, but is more prone to problems.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Direct mode [TEXT PLACEHOLDER]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="cbxDirectAdapter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>350</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="whatsThis">
|
||||
<string><html><head/><body><p>Selects the network adapter through which to route network traffic under direct mode.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Network adapter:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>IP address:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="lblAdapterMAC">
|
||||
<property name="text">
|
||||
<string>[PLACEHOLDER]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="lblAdapterIP">
|
||||
<property name="text">
|
||||
<string>[PLACEHOLDER]</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>WifiSettingsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>WifiSettingsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
Loading…
Reference in New Issue