├── .gitignore ├── .travis.yml ├── AUTHORS ├── LICENSE ├── README.md ├── packaging ├── linux │ ├── AppImage │ │ └── LANShare.desktop │ └── debian │ │ ├── DEBIAN │ │ └── control │ │ ├── LANShare.desktop │ │ ├── LANShare.sh │ │ └── lanshare-icon.png └── windows │ ├── LANShare_setup_script.iss │ ├── info_after.txt │ └── info_before.txt ├── screenshot.png ├── screenshot2.png ├── screenshot3.png └── src ├── LANShare.pro ├── img ├── about.png ├── cancel.png ├── clear.png ├── down.png ├── file.png ├── folder.png ├── icon.ico ├── icon.png ├── linux.png ├── osx.png ├── pause.png ├── refresh.png ├── resume.png ├── send.png ├── settings.png ├── systray-icon.png ├── up.png └── windows.png ├── main.cpp ├── model ├── device.cpp ├── device.h ├── devicelistmodel.cpp ├── devicelistmodel.h ├── transferinfo.cpp ├── transferinfo.h ├── transfertablemodel.cpp └── transfertablemodel.h ├── res.qrc ├── settings.cpp ├── settings.h ├── singleinstance.cpp ├── singleinstance.h ├── text ├── credits.html └── gpl-3.0.txt ├── transfer ├── devicebroadcaster.cpp ├── devicebroadcaster.h ├── receiver.cpp ├── receiver.h ├── sender.cpp ├── sender.h ├── transfer.cpp ├── transfer.h ├── transferserver.cpp └── transferserver.h ├── ui ├── aboutdialog.cpp ├── aboutdialog.h ├── aboutdialog.ui ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── receiverselectordialog.cpp ├── receiverselectordialog.h ├── receiverselectordialog.ui ├── settingsdialog.cpp ├── settingsdialog.h └── settingsdialog.ui ├── util.cpp └── util.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | 31 | # Qt generated files 32 | ui_*.h 33 | moc_*.cpp 34 | qrc_*.cpp 35 | 36 | build 37 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | compiler: gcc 3 | sudo: require 4 | dist: trusty 5 | 6 | before_install: 7 | - sudo add-apt-repository ppa:beineri/opt-qt593-trusty -y 8 | - sudo apt-get update -qq 9 | 10 | install: 11 | - sudo apt-get -y install qt59base 12 | - source /opt/qt*/bin/qt*-env.sh 13 | 14 | script: 15 | - cd src/ 16 | - qmake CONFIG+=release PREFIX=/usr 17 | - make -j$(nproc) 18 | # - make INSTALL_ROOT=appdir -j$(nproc) install ; find appdir/ # FIXME: https://github.com/abdularis/LAN-Share/issues/7 19 | - mkdir -p appdir/usr/bin ; cp LANShare appdir/usr/bin 20 | - mkdir -p appdir/usr/share/icons/hicolor/128x128/apps/ ; cp ../packaging/linux/debian/lanshare-icon.png appdir/usr/share/icons/hicolor/128x128/apps/lanshare.png 21 | - wget -c -nv "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" 22 | - chmod a+x linuxdeployqt-continuous-x86_64.AppImage 23 | - unset QTDIR; unset QT_PLUGIN_PATH ; unset LD_LIBRARY_PATH 24 | - export VERSION=$(git rev-parse --short HEAD) # linuxdeployqt uses this for naming the file 25 | - mkdir -p appdir/usr/share/applications/ 26 | - cp ../packaging/linux/AppImage/LANShare.desktop appdir/usr/share/applications/ 27 | - ./linuxdeployqt-continuous-x86_64.AppImage appdir/usr/share/applications/*.desktop -bundle-non-qt-libs 28 | - ./linuxdeployqt-continuous-x86_64.AppImage appdir/usr/share/applications/*.desktop -appimage 29 | 30 | after_success: 31 | - find appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq 32 | - # curl --upload-file LANShare*.AppImage https://transfer.sh/LANShare-git.$(git rev-parse --short HEAD)-x86_64.AppImage 33 | - wget -c https://github.com/probonopd/uploadtool/raw/master/upload.sh 34 | - bash upload.sh LANShare*.AppImage* 35 | 36 | branches: 37 | except: 38 | - # Do not build tags that we create when we upload to GitHub Releases 39 | - /^(?i:continuous) 40 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Abdul Aris R. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | 6 | [![Build Status](https://travis-ci.org/abdularis/LAN-Share.svg?branch=master)](https://travis-ci.org/abdularis/LAN-Share) 7 | 8 | # LAN Share 9 | LAN Share is a cross platform local area network file transfer application, built using Qt GUI framework. It can be used to transfer a whole folder, one or more files, large or small immediatelly without any additional configuration. 10 | 11 | ## Install 12 | You can download the Ubuntu package or linux AppImage or Windows executable from the release page. 13 | [https://github.com/abdularis/LAN-Share/releases](https://github.com/abdularis/LAN-Share/releases) 14 | 15 | * Using .deb (Ubuntu/Debian) 16 | 17 | download the latest version, for example `lanshare_1.2.1-1_amd64.deb` then open a terminal, navigate to directory where the downloaded package is located and type 18 | 19 | ``` 20 | $ sudo dpkg -i ./lanshare_1.2.1-1_amd64.deb 21 | ``` 22 | 23 | * Using AppImage (All Linux) 24 | 25 | simply download the AppImage and run it on all linux distribution 26 | 27 | * For Windows 28 | 29 | See the github release page or go to [Softpedia](https://www.softpedia.com/get/Internet/File-Sharing/LAN-Share.shtml) 30 | 31 | ## Compiling instructions 32 | To compile LANShare you need to install Qt tools, on Debian you can use: 33 | ``` 34 | $ sudo apt install qt5-qmake qt5-default 35 | ``` 36 | For more information about qmake you can visit this [page](https://doc.qt.io/qt-5/qmake-tutorial.html). 37 | 38 | Then you can download the sourcecode with git: 39 | 40 | ``` 41 | $ git clone https://github.com/abdularis/LAN-Share 42 | ``` 43 | and compile with: 44 | 45 | ``` 46 | $ cd LAN-Share-1.2.1/src 47 | $ qmake -o Makefile LANShare.pro 48 | $ make 49 | ``` 50 | 51 | ## Features 52 | * Send one or more files 53 | * Send folder 54 | * Send to multiple receiver at the same time 55 | * Cancel, pause and resume operations while transfering 56 | 57 | ## Usage 58 | * Computer has to be connected to a local area network (wired or wireless) 59 | * Run the application in both sender and receiver 60 | * Send the file/folder by, select *Send* (files or folder) then -> select receiver in the *'Select Receiver'* dialog, finally click *'Send'* 61 | * File/folder would automatically received by the receiver 62 | 63 | ## Screenshots 64 | 65 | ![Screenshot 1](screenshot.png) 66 | 67 | ![Screenshot 2](screenshot2.png) 68 | 69 | ![Screenshot 3](screenshot3.png) 70 | 71 | ## License 72 | GPLv3 73 | -------------------------------------------------------------------------------- /packaging/linux/AppImage/LANShare.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Name=LANShare 4 | Categories=Network; 5 | GenericName=LAN File Transfer 6 | Comment=Local Area Network (LAN) File Transfer 7 | Comment[de]=Dateien im Lokalen Netzwerk (LAN) übertragen 8 | Icon=lanshare 9 | Exec=LANShare 10 | -------------------------------------------------------------------------------- /packaging/linux/debian/DEBIAN/control: -------------------------------------------------------------------------------- 1 | Package: LANShare 2 | Version: 1.2.1-1 3 | License: GPL3 4 | Architecture: amd64 5 | Maintainer: Abdul Aris R. 6 | Section: default 7 | Priority: extra 8 | Description: LANShare is a simple open-source cross platform application that let you transfer files and/or folder through local area network(LAN) easily. You can send and receive files and folder within LAN without any additional configuration needed on each platform. It can runs on most version of Windows(XP or later) and Linux(Debian, Ubuntu, Fedora, etc). 9 | -------------------------------------------------------------------------------- /packaging/linux/debian/LANShare.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Encoding=UTF-8 3 | Version=1.2.1 4 | Type=Application 5 | Name=LANShare 6 | Categories=System 7 | GenericName=LAN File Transfer 8 | Comment=Local Area Network (LAN) File Transfer 9 | Comment[de]=Dateien im Lokalen Netzwerk (LAN) übertragen 10 | Icon=/usr/share/pixmaps/lanshare-icon.png 11 | Path=/usr/lib/LANShare 12 | Exec=/usr/lib/LANShare/LANShare.sh 13 | StartupNotify=false 14 | 15 | Name[en_US]=LANShare.d.desktop 16 | -------------------------------------------------------------------------------- /packaging/linux/debian/LANShare.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export LD_LIBRARY_PATH=./ 4 | ./LANShare -style gtk2 5 | -------------------------------------------------------------------------------- /packaging/linux/debian/lanshare-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/packaging/linux/debian/lanshare-icon.png -------------------------------------------------------------------------------- /packaging/windows/LANShare_setup_script.iss: -------------------------------------------------------------------------------- 1 | ; Script generated by the Inno Setup Script Wizard. 2 | ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! 3 | 4 | #define MyAppName "LANShare" 5 | #define MyAppVersion "1.2.1" 6 | #define MyAppExeName "LANShare.exe" 7 | 8 | [Setup] 9 | ; NOTE: The value of AppId uniquely identifies this application. 10 | ; Do not use the same AppId value in installers for other applications. 11 | ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) 12 | AppId={{A09C1E15-344D-47AF-9767-B8479736B5E8} 13 | AppName={#MyAppName} 14 | AppVersion={#MyAppVersion} 15 | ;AppVerName={#MyAppName} {#MyAppVersion} 16 | DefaultDirName={pf}\{#MyAppName} 17 | DisableProgramGroupPage=yes 18 | LicenseFile=..\..\src\text\gpl-3.0.txt 19 | InfoBeforeFile=info_before.txt 20 | InfoAfterFile=info_after.txt 21 | OutputBaseFilename=setup 22 | Compression=lzma 23 | SolidCompression=yes 24 | 25 | [Tasks] 26 | Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked 27 | 28 | [Files] 29 | Source: "bin\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs 30 | ; NOTE: Don't use "Flags: ignoreversion" on any shared system files 31 | 32 | [Icons] 33 | Name: "{commonprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" 34 | Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon 35 | 36 | [Run] 37 | Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent 38 | 39 | -------------------------------------------------------------------------------- /packaging/windows/info_after.txt: -------------------------------------------------------------------------------- 1 | Thanks for using our application. -------------------------------------------------------------------------------- /packaging/windows/info_before.txt: -------------------------------------------------------------------------------- 1 | LANShare is a simple open-source cross platform application that let you transfer files and/or folder through local area network(LAN) easily. 2 | You can send and receive files and folder within LAN without any additional configuration needed on each platform. 3 | It can runs on most version of Windows(XP or later) and Linux(Debian, Ubuntu, Fedora, etc). -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/screenshot.png -------------------------------------------------------------------------------- /screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/screenshot2.png -------------------------------------------------------------------------------- /screenshot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/screenshot3.png -------------------------------------------------------------------------------- /src/LANShare.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2016-11-20T13:00:50 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui network 8 | 9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 10 | 11 | TARGET = LANShare 12 | TEMPLATE = app 13 | CONFIG += c++17 14 | 15 | RC_ICONS += img/icon.ico 16 | 17 | SOURCES += main.cpp\ 18 | settings.cpp \ 19 | util.cpp \ 20 | singleinstance.cpp \ 21 | ui/mainwindow.cpp \ 22 | ui/receiverselectordialog.cpp \ 23 | ui/aboutdialog.cpp \ 24 | ui/settingsdialog.cpp \ 25 | transfer/devicebroadcaster.cpp \ 26 | transfer/receiver.cpp \ 27 | transfer/sender.cpp \ 28 | transfer/transfer.cpp \ 29 | transfer/transferserver.cpp \ 30 | model/device.cpp \ 31 | model/devicelistmodel.cpp \ 32 | model/transferinfo.cpp \ 33 | model/transfertablemodel.cpp 34 | 35 | HEADERS += settings.h \ 36 | util.h \ 37 | singleinstance.h \ 38 | ui/mainwindow.h \ 39 | ui/receiverselectordialog.h \ 40 | ui/aboutdialog.h \ 41 | ui/settingsdialog.h \ 42 | transfer/devicebroadcaster.h \ 43 | transfer/receiver.h \ 44 | transfer/sender.h \ 45 | transfer/transfer.h \ 46 | transfer/transferserver.h \ 47 | model/device.h \ 48 | model/devicelistmodel.h \ 49 | model/transferinfo.h \ 50 | model/transfertablemodel.h 51 | 52 | FORMS += ui/mainwindow.ui \ 53 | ui/receiverselectordialog.ui \ 54 | ui/aboutdialog.ui \ 55 | ui/settingsdialog.ui 56 | 57 | RESOURCES += \ 58 | res.qrc 59 | -------------------------------------------------------------------------------- /src/img/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/about.png -------------------------------------------------------------------------------- /src/img/cancel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/cancel.png -------------------------------------------------------------------------------- /src/img/clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/clear.png -------------------------------------------------------------------------------- /src/img/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/down.png -------------------------------------------------------------------------------- /src/img/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/file.png -------------------------------------------------------------------------------- /src/img/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/folder.png -------------------------------------------------------------------------------- /src/img/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/icon.ico -------------------------------------------------------------------------------- /src/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/icon.png -------------------------------------------------------------------------------- /src/img/linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/linux.png -------------------------------------------------------------------------------- /src/img/osx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/osx.png -------------------------------------------------------------------------------- /src/img/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/pause.png -------------------------------------------------------------------------------- /src/img/refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/refresh.png -------------------------------------------------------------------------------- /src/img/resume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/resume.png -------------------------------------------------------------------------------- /src/img/send.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/send.png -------------------------------------------------------------------------------- /src/img/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/settings.png -------------------------------------------------------------------------------- /src/img/systray-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/systray-icon.png -------------------------------------------------------------------------------- /src/img/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/up.png -------------------------------------------------------------------------------- /src/img/windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdularis/LAN-Share/aa7a3bc61e38191088bf2a68b2ed94bfee4a04af/src/img/windows.png -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "settings.h" 23 | #include "ui/mainwindow.h" 24 | #include "singleinstance.h" 25 | #include "util.h" 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | QApplication app(argc, argv); 30 | app.setQuitOnLastWindowClosed(false); 31 | 32 | SingleInstance si(PROGRAM_NAME); 33 | if (si.hasPreviousInstance()) { 34 | return EXIT_SUCCESS; 35 | } 36 | 37 | if (!si.start()) { 38 | qDebug() << si.getLastErrorString(); 39 | return EXIT_FAILURE; 40 | } 41 | 42 | app.setApplicationDisplayName(PROGRAM_NAME); 43 | app.setApplicationName(PROGRAM_NAME); 44 | app.setApplicationVersion(Util::parseAppVersion()); 45 | 46 | MainWindow mainWindow; 47 | mainWindow.show(); 48 | 49 | QObject::connect(&si, &SingleInstance::newInstanceCreated, [&mainWindow]() { 50 | mainWindow.setMainWindowVisibility(true); 51 | }); 52 | 53 | return app.exec(); 54 | } 55 | -------------------------------------------------------------------------------- /src/model/device.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include "device.h" 20 | 21 | Device::Device(const QString &id, const QString &name, const QString &osName, const QHostAddress &addr) 22 | : mId{id}, mName{name}, mOSName{osName}, mAddress{addr} 23 | { 24 | } 25 | 26 | bool Device::isValid() const 27 | { 28 | return (mId != "" && mName != "" && mOSName != "" && mAddress != QHostAddress::Null); 29 | } 30 | 31 | void Device::setId(const QString& id) 32 | { 33 | mId = id; 34 | } 35 | 36 | void Device::setName(const QString& name) 37 | { 38 | mName = name; 39 | } 40 | 41 | void Device::setAddress(const QHostAddress& address) 42 | { 43 | mAddress = address; 44 | } 45 | 46 | void Device::setOSName(const QString& osName) 47 | { 48 | mOSName = osName; 49 | } 50 | 51 | bool Device::operator==(const Device& other) const 52 | { 53 | return mId == other.getId() && mName == other.getName() && mAddress == other.getAddress(); 54 | } 55 | 56 | bool Device::operator!=(const Device& other) const 57 | { 58 | return !((*this) == other); 59 | } 60 | -------------------------------------------------------------------------------- /src/model/device.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef DEVICE_H 20 | #define DEVICE_H 21 | 22 | #include 23 | #include 24 | 25 | /* 26 | * class Device merepresentasikan Node/Computer yang terhubung ke jaringan/LAN 27 | * yang sama dan bisa bertransfer data 28 | */ 29 | class Device 30 | { 31 | public: 32 | explicit Device() = default; 33 | Device(const QString &id, const QString &name, const QString &osName, const QHostAddress &addr); 34 | 35 | inline QString getId() const { return mId; } 36 | inline QString getName() const { return mName; } 37 | inline QHostAddress getAddress() const { return mAddress; } 38 | inline QString getOSName() const { return mOSName; } 39 | bool isValid() const; 40 | 41 | void setId(const QString& id); 42 | void setName(const QString& name); 43 | void setAddress(const QHostAddress& address); 44 | void setOSName(const QString& osName); 45 | 46 | bool operator==(const Device& other) const; 47 | bool operator!=(const Device& other) const; 48 | 49 | private: 50 | QString mId{""}; 51 | QString mName{""}; 52 | QString mOSName{""}; 53 | QHostAddress mAddress{QHostAddress::Null}; 54 | }; 55 | 56 | #endif // DEVICE_H 57 | -------------------------------------------------------------------------------- /src/model/devicelistmodel.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | #include "devicelistmodel.h" 22 | #include "settings.h" 23 | 24 | DeviceListModel::DeviceListModel(DeviceBroadcaster* deviceBC, QObject* parent) 25 | : QAbstractListModel(parent) 26 | { 27 | mDBC = deviceBC; 28 | if (!mDBC) { 29 | mDBC = new DeviceBroadcaster(this); 30 | } 31 | 32 | connect(mDBC, &DeviceBroadcaster::broadcastReceived, this, &DeviceListModel::onBCReceived); 33 | } 34 | 35 | void DeviceListModel::onBCReceived(const Device &fromDevice) 36 | { 37 | QString id = fromDevice.getId(); 38 | if (id == Settings::instance()->getMyDevice().getId()) { 39 | return; 40 | } 41 | 42 | bool found = false; 43 | for(const Device& dev : mDevices) { 44 | if (dev.getId() == id) { 45 | found = true; 46 | break; 47 | } 48 | } 49 | 50 | if (!found) { 51 | beginInsertRows(QModelIndex(), mDevices.size(), mDevices.size()); 52 | mDevices.push_back(fromDevice); 53 | endInsertRows(); 54 | } 55 | } 56 | 57 | QVector DeviceListModel::getDevices() const 58 | { 59 | return mDevices; 60 | } 61 | 62 | void DeviceListModel::setDevices(const QVector &devices) 63 | { 64 | beginResetModel(); 65 | mDevices = devices; 66 | endResetModel(); 67 | } 68 | 69 | 70 | QVariant DeviceListModel::data(const QModelIndex &index, int role) const 71 | { 72 | if (index.isValid()) { 73 | Device dev = mDevices[index.row()]; 74 | switch (role) { 75 | case Qt::DisplayRole : { 76 | return dev.getName() + " (" + dev.getOSName() + ")"; 77 | } 78 | case Qt::ToolTipRole : { 79 | QString str = dev.getId() + "
" + 80 | dev.getName() + " (" + dev.getOSName() + ")
" + 81 | dev.getAddress().toString(); 82 | return str; 83 | } 84 | case Qt::DecorationRole : { 85 | QString os = dev.getOSName(); 86 | if (os == "Linux") { 87 | return QPixmap(":/img/linux.png"); 88 | } else if (os == "Windows") { 89 | return QPixmap(":/img/windows.png"); 90 | } else if (os == "Mac OSX") { 91 | return QPixmap(":/img/osx.png"); 92 | } 93 | } 94 | } 95 | 96 | } 97 | 98 | return QVariant(); 99 | } 100 | 101 | int DeviceListModel::rowCount(const QModelIndex &parent) const 102 | { 103 | Q_UNUSED(parent); 104 | return mDevices.size(); 105 | } 106 | 107 | void DeviceListModel::refresh() 108 | { 109 | beginResetModel(); 110 | mDevices.clear(); 111 | endResetModel(); 112 | } 113 | 114 | Device DeviceListModel::device(int index) const 115 | { 116 | if (index < 0 || index >= mDevices.size()) { 117 | return Device(); 118 | } 119 | 120 | return mDevices.at(index); 121 | } 122 | 123 | Device DeviceListModel::device(const QString &id) const 124 | { 125 | for (Device dev : mDevices) { 126 | if (dev.getId() == id) { 127 | return dev; 128 | } 129 | } 130 | 131 | return Device(); 132 | } 133 | 134 | Device DeviceListModel::device(const QHostAddress &address) const 135 | { 136 | for (Device dev : mDevices) { 137 | if (dev.getAddress() == address) { 138 | return dev; 139 | } 140 | } 141 | 142 | return Device(); 143 | } 144 | -------------------------------------------------------------------------------- /src/model/devicelistmodel.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef DEVICELISTMODEL_H 20 | #define DEVICELISTMODEL_H 21 | 22 | #include 23 | 24 | #include "transfer/devicebroadcaster.h" 25 | #include "device.h" 26 | 27 | class DeviceListModel : public QAbstractListModel 28 | { 29 | public: 30 | DeviceListModel(DeviceBroadcaster* deviceBC, QObject* parent = nullptr); 31 | 32 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 33 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 34 | 35 | void refresh(); 36 | 37 | Device device(int index) const; 38 | Device device(const QString& id) const; 39 | Device device(const QHostAddress& address) const; 40 | 41 | QVector getDevices() const; 42 | void setDevices(const QVector &getDevices); 43 | 44 | private Q_SLOTS: 45 | void onBCReceived(const Device &fromDevice); 46 | 47 | private: 48 | DeviceBroadcaster* mDBC; 49 | QVector mDevices; 50 | }; 51 | 52 | #endif // DEVICELISTMODEL_H 53 | -------------------------------------------------------------------------------- /src/model/transferinfo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | 20 | #include "transferinfo.h" 21 | 22 | TransferInfo::TransferInfo(Transfer* owner, QObject *parent) : 23 | QObject(parent), 24 | mState(TransferState::Idle), mLastState(TransferState::Idle), 25 | mType(TransferType::None), mProgress(0), mDataSize(0), 26 | mOwner(owner) 27 | { 28 | } 29 | 30 | bool TransferInfo::canResume() const 31 | { 32 | return mState == TransferState::Paused; 33 | } 34 | 35 | bool TransferInfo::canPause() const 36 | { 37 | return mState == TransferState::Waiting || 38 | mState == TransferState::Transfering; 39 | } 40 | 41 | bool TransferInfo::canCancel() const 42 | { 43 | return mState == TransferState::Waiting || 44 | mState == TransferState::Transfering || 45 | mState == TransferState::Paused; 46 | } 47 | 48 | void TransferInfo::setPeer(Device peer) 49 | { 50 | mPeer = std::move(peer); 51 | } 52 | 53 | void TransferInfo::setState(TransferState newState) 54 | { 55 | if (newState != mState) { 56 | TransferState tmp = mState; 57 | 58 | switch (mState) { 59 | case TransferState::Idle : { 60 | if (newState == TransferState::Waiting) { 61 | mState = newState; 62 | emit stateChanged(mState); 63 | } 64 | break; 65 | } 66 | case TransferState::Waiting : { 67 | if (newState == TransferState::Transfering || 68 | newState == TransferState::Cancelled || 69 | newState == TransferState::Paused) { 70 | mState = newState; 71 | emit stateChanged(mState); 72 | } 73 | break; 74 | } 75 | case TransferState::Transfering : { 76 | if (newState == TransferState::Disconnected || 77 | newState == TransferState::Finish || 78 | newState == TransferState::Cancelled || 79 | newState == TransferState::Paused) { 80 | mState = newState; 81 | emit stateChanged(mState); 82 | } 83 | break; 84 | } 85 | case TransferState::Paused : { 86 | if (newState == TransferState::Waiting || 87 | newState == TransferState::Transfering) { 88 | mState = mLastState; 89 | emit stateChanged(mState); 90 | } 91 | else if (newState == TransferState::Cancelled || 92 | newState == TransferState::Disconnected) { 93 | mState = newState; 94 | emit stateChanged(mState); 95 | } 96 | break; 97 | } 98 | default: 99 | break; 100 | } 101 | 102 | mLastState = tmp; 103 | } 104 | } 105 | 106 | void TransferInfo::setProgress(int newProgress) 107 | { 108 | if (newProgress != mProgress) { 109 | mProgress = newProgress; 110 | emit progressChanged(mProgress); 111 | } 112 | } 113 | 114 | void TransferInfo::setTransferType(TransferType type) 115 | { 116 | mType = type; 117 | } 118 | 119 | void TransferInfo::setDataSize(qint64 size) 120 | { 121 | mDataSize = size; 122 | } 123 | 124 | void TransferInfo::setFilePath(const QString &fileName) 125 | { 126 | mFilePath = fileName; 127 | } 128 | -------------------------------------------------------------------------------- /src/model/transferinfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | 20 | #ifndef TRANSFERINFO_H 21 | #define TRANSFERINFO_H 22 | 23 | #include 24 | 25 | #include "device.h" 26 | 27 | enum class TransferState { 28 | Idle, 29 | Waiting, 30 | Disconnected, 31 | Paused, 32 | Cancelled, 33 | Transfering, 34 | Finish 35 | }; 36 | 37 | enum class TransferType { 38 | None, 39 | Download, 40 | Upload 41 | }; 42 | 43 | class Transfer; 44 | 45 | class TransferInfo : public QObject 46 | { 47 | Q_OBJECT 48 | 49 | public: 50 | explicit TransferInfo(Transfer* owner, QObject *parent = nullptr); 51 | 52 | inline Device getPeer() const { return mPeer; } 53 | inline int getProgress() const { return mProgress; } 54 | inline TransferState getState() const { return mState; } 55 | inline TransferState getLastState() const { return mLastState; } 56 | inline TransferType getTransferType() const { return mType; } 57 | inline qint64 getDataSize() const { return mDataSize; } 58 | inline QString getFilePath() const { return mFilePath; } 59 | inline Transfer* getOwner() const { return mOwner; } 60 | 61 | bool canResume() const; 62 | bool canPause() const; 63 | bool canCancel() const; 64 | 65 | void setPeer(Device peer); 66 | void setState(TransferState state); 67 | void setTransferType(TransferType type); 68 | void setProgress(int progress); 69 | void setDataSize(qint64 size); 70 | void setFilePath(const QString& fileName); 71 | 72 | Q_SIGNALS: 73 | void done(); 74 | void errorOcurred(const QString& errStr); 75 | void progressChanged(int progress); 76 | void fileOpened(); 77 | void stateChanged(TransferState state); 78 | 79 | private: 80 | Device mPeer; 81 | TransferState mState; 82 | TransferState mLastState; 83 | TransferType mType; 84 | int mProgress; 85 | qint64 mDataSize; 86 | QString mFilePath; 87 | 88 | Transfer* mOwner; 89 | }; 90 | 91 | #endif // TRANSFERINFO_H 92 | -------------------------------------------------------------------------------- /src/model/transfertablemodel.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | 20 | #include "transfertablemodel.h" 21 | #include "util.h" 22 | 23 | TransferTableModel::TransferTableModel(QObject *parent) : 24 | QAbstractTableModel(parent) 25 | { 26 | } 27 | 28 | TransferTableModel::~TransferTableModel() 29 | { 30 | for (Transfer* t : mTransfers) { 31 | delete t; 32 | } 33 | } 34 | 35 | int TransferTableModel::rowCount(const QModelIndex &parent) const 36 | { 37 | Q_UNUSED(parent); 38 | return mTransfers.size(); 39 | } 40 | 41 | int TransferTableModel::columnCount(const QModelIndex &parent) const 42 | { 43 | Q_UNUSED(parent); 44 | return (int) Column::Count; 45 | } 46 | 47 | QVariant TransferTableModel::data(const QModelIndex &index, int role) const 48 | { 49 | if (index.isValid()) { 50 | TransferInfo* info = mTransfers.at(index.row())->getTransferInfo(); 51 | 52 | if (info) { 53 | Column col = (Column) index.column(); 54 | 55 | if (role == Qt::DisplayRole) { 56 | switch (col) { 57 | case Column::Peer : return info->getPeer().getName(); 58 | case Column::FileName : return info->getFilePath(); 59 | case Column::FileSize : return Util::sizeToString(info->getDataSize()); 60 | case Column::State : return getStateString(info->getState()); 61 | case Column::Progress : return info->getProgress(); 62 | default : break; 63 | } 64 | } 65 | else if (role == Qt::ForegroundRole && col == Column::State) { 66 | return getStateColor(info->getState()); 67 | } 68 | } 69 | } 70 | 71 | return QVariant(); 72 | } 73 | 74 | QVariant TransferTableModel::headerData(int section, Qt::Orientation orientation, int role) const 75 | { 76 | if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { 77 | Column col = (Column) section; 78 | switch (col) { 79 | case Column::Peer : return tr("Peer"); 80 | case Column::FileName : return tr("File path"); 81 | case Column::FileSize : return tr("Size"); 82 | case Column::State : return tr("Status"); 83 | case Column::Progress : return tr("Progress"); 84 | default : break; 85 | } 86 | } 87 | 88 | return QVariant(); 89 | } 90 | 91 | void TransferTableModel::insertTransfer(Transfer *t) 92 | { 93 | if (!t) { 94 | return; 95 | } 96 | 97 | beginInsertRows(QModelIndex(), 0, 0); 98 | mTransfers.prepend(t); 99 | endInsertRows(); 100 | emit dataChanged(index(1, 0), index(mTransfers.size()-1, (int) Column::Count)); 101 | 102 | TransferInfo* info = t->getTransferInfo(); 103 | connect(info, &TransferInfo::fileOpened, [=]() { 104 | int idx = mTransfers.indexOf(info->getOwner()); 105 | QModelIndex fNameIdx = index(idx, (int) Column::FileName); 106 | QModelIndex fSizeIdx = index(idx, (int) Column::FileSize); 107 | emit dataChanged(fNameIdx, fSizeIdx); 108 | }); 109 | 110 | connect(info, &TransferInfo::stateChanged, [=](TransferState state) { 111 | Q_UNUSED(state); 112 | 113 | int idx = mTransfers.indexOf(info->getOwner()); 114 | QModelIndex stateIdx = index(idx, (int) Column::State); 115 | emit dataChanged(stateIdx, stateIdx); 116 | }); 117 | } 118 | 119 | void TransferTableModel::clearCompleted() 120 | { 121 | for (int i = 0; i < mTransfers.size(); i++) { 122 | Transfer* t = mTransfers.at(i); 123 | TransferState state = t->getTransferInfo()->getState(); 124 | if (state == TransferState::Idle || 125 | state == TransferState::Finish || 126 | state == TransferState::Disconnected || 127 | state == TransferState::Cancelled) { 128 | 129 | beginRemoveRows(QModelIndex(), i, i); 130 | mTransfers.remove(i); 131 | endRemoveRows(); 132 | t->deleteLater(); 133 | i--; 134 | } 135 | } 136 | } 137 | 138 | Transfer* TransferTableModel::getTransfer(int index) const 139 | { 140 | if (index < 0 || index >= mTransfers.size()) { 141 | return nullptr; 142 | } 143 | 144 | return mTransfers.at(index); 145 | } 146 | 147 | TransferInfo* TransferTableModel::getTransferInfo(int index) const 148 | { 149 | return getTransfer(index)->getTransferInfo(); 150 | } 151 | 152 | void TransferTableModel::removeTransfer(int index) 153 | { 154 | if (index < 0 || index >= mTransfers.size()) { 155 | return; 156 | } 157 | 158 | beginRemoveRows(QModelIndex(), index, index); 159 | mTransfers.at(index)->deleteLater(); 160 | mTransfers.remove(index); 161 | endRemoveRows(); 162 | } 163 | 164 | QString TransferTableModel::getStateString(TransferState state) const 165 | { 166 | switch (state) { 167 | case TransferState::Idle : return tr("Idle"); 168 | case TransferState::Waiting : return tr("Waiting"); 169 | case TransferState::Disconnected : return tr("Disconnected"); 170 | case TransferState::Paused : return tr("Paused"); 171 | case TransferState::Cancelled : return tr("Cancelled"); 172 | case TransferState::Transfering : return tr("Transfering"); 173 | case TransferState::Finish : return tr("Finish"); 174 | } 175 | 176 | return QString(); 177 | } 178 | 179 | QColor TransferTableModel::getStateColor(TransferState state) const 180 | { 181 | switch (state) { 182 | case TransferState::Idle : return QColor("black"); 183 | case TransferState::Waiting : return QColor("orange"); 184 | case TransferState::Disconnected : return QColor("red"); 185 | case TransferState::Paused : return QColor("orange"); 186 | case TransferState::Cancelled : return QColor("red"); 187 | case TransferState::Transfering : return QColor("blue"); 188 | case TransferState::Finish : return QColor("green"); 189 | } 190 | 191 | return QColor(); 192 | } 193 | -------------------------------------------------------------------------------- /src/model/transfertablemodel.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | 20 | 21 | #ifndef TRANSFERTABLEMODEL_H 22 | #define TRANSFERTABLEMODEL_H 23 | 24 | #include 25 | #include 26 | 27 | #include "transfer/transfer.h" 28 | #include "transferinfo.h" 29 | 30 | class TransferTableModel : public QAbstractTableModel 31 | { 32 | Q_OBJECT 33 | 34 | public: 35 | explicit TransferTableModel(QObject *parent = nullptr); 36 | ~TransferTableModel() override; 37 | 38 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 39 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; 40 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 41 | QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; 42 | 43 | void insertTransfer(Transfer* t); 44 | void clearCompleted(); 45 | 46 | Transfer* getTransfer(int index) const; 47 | TransferInfo* getTransferInfo(int index) const; 48 | 49 | void removeTransfer(int index); 50 | 51 | enum class Column : int { 52 | Peer = 0, FileName, FileSize, State, Progress, 53 | Count 54 | }; 55 | 56 | private: 57 | QString getStateString(TransferState state) const; 58 | QColor getStateColor(TransferState state) const; 59 | 60 | QVector mTransfers; 61 | 62 | }; 63 | 64 | #endif // TRANSFERTABLEMODEL_H 65 | -------------------------------------------------------------------------------- /src/res.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | img/send.png 4 | img/settings.png 5 | img/about.png 6 | img/icon.png 7 | img/down.png 8 | img/up.png 9 | img/clear.png 10 | img/refresh.png 11 | img/cancel.png 12 | img/pause.png 13 | img/resume.png 14 | text/credits.html 15 | text/gpl-3.0.txt 16 | img/linux.png 17 | img/osx.png 18 | img/windows.png 19 | img/systray-icon.png 20 | img/file.png 21 | img/folder.png 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/settings.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "settings.h" 27 | 28 | #define DefaultBroadcastPort 56780 29 | #define DefaultTransferPort 17116 30 | #define DefaultBroadcastInterval 5000 // 5 secs 31 | #define DefaultFileBufferSize 98304 // 96 KB 32 | #define MaxFileBufferSize 1024*1024 // 1 MB 33 | 34 | Settings* Settings::obj = new Settings; 35 | Settings::Settings() 36 | { 37 | mThisDevice = Device(); 38 | mThisDevice.setId(QUuid::createUuid().toString()); 39 | mThisDevice.setAddress(QHostAddress::LocalHost); 40 | mThisDevice.setOSName(OS_NAME); 41 | 42 | foreach (QHostAddress address, QNetworkInterface::allAddresses()) { 43 | if (address.protocol() == QAbstractSocket::IPv4Protocol && 44 | address != QHostAddress::LocalHost) { 45 | mThisDevice.setAddress(address); 46 | break; 47 | } 48 | } 49 | 50 | loadSettings(); 51 | } 52 | 53 | void Settings::setDeviceName(const QString &name) 54 | { 55 | mThisDevice.setName(name); 56 | } 57 | 58 | void Settings::setBroadcastPort(quint16 port) 59 | { 60 | if (port > 0) 61 | mBCPort = port; 62 | } 63 | 64 | void Settings::setBroadcastInterval(quint16 interval) 65 | { 66 | mBCInterval = interval; 67 | } 68 | 69 | void Settings::setTransferPort(quint16 port) 70 | { 71 | if (port > 0) 72 | mTransferPort = port; 73 | } 74 | 75 | void Settings::setFileBufferSize(qint32 size) 76 | { 77 | if (size > 0 && size < MaxFileBufferSize) 78 | mFileBuffSize = size; 79 | } 80 | 81 | void Settings::setDownloadDir(const QString& dir) 82 | { 83 | if (!dir.isEmpty() && QDir(dir).exists()) 84 | mDownloadDir = dir; 85 | } 86 | 87 | void Settings::setReplaceExistingFile(bool replace) 88 | { 89 | mReplaceExistingFile = replace; 90 | } 91 | 92 | void Settings::loadSettings() 93 | { 94 | QSettings settings(SETTINGS_FILE); 95 | mThisDevice.setName(settings.value("DeviceName", QHostInfo::localHostName()).toString()); 96 | mBCPort = settings.value("BroadcastPort", DefaultBroadcastPort).value(); 97 | mTransferPort = settings.value("TransferPort", DefaultTransferPort).value(); 98 | mFileBuffSize = settings.value("FileBufferSize", DefaultFileBufferSize).value(); 99 | mDownloadDir = settings.value("DownloadDir", getDefaultDownloadPath()).toString(); 100 | 101 | if (!QDir(mDownloadDir).exists()) { 102 | QDir dir; 103 | dir.mkpath(mDownloadDir); 104 | } 105 | 106 | mBCInterval = settings.value("BroadcastInterval", DefaultBroadcastInterval).value(); 107 | mReplaceExistingFile = settings.value("ReplaceExistingFile", false).toBool(); 108 | } 109 | 110 | QString Settings::getDefaultDownloadPath() 111 | { 112 | #if defined (Q_OS_WIN) 113 | return 114 | QStandardPaths::locate(QStandardPaths::DownloadLocation, QString(), QStandardPaths::LocateDirectory) + "LANShareDownloads"; 115 | #else 116 | return QDir::homePath() + QDir::separator() + "LANShareDownloads"; 117 | #endif 118 | } 119 | 120 | void Settings::saveSettings() 121 | { 122 | QSettings settings(SETTINGS_FILE); 123 | settings.setValue("DeviceName", mThisDevice.getName()); 124 | settings.setValue("BroadcastPort", mBCPort); 125 | settings.setValue("TransferPort", mTransferPort); 126 | settings.setValue("FileBufferSize", mFileBuffSize); 127 | settings.setValue("DownloadDir", mDownloadDir); 128 | settings.setValue("BroadcastInterval", mBCInterval); 129 | settings.setValue("ReplaceExistingFile", mReplaceExistingFile); 130 | } 131 | 132 | void Settings::reset() 133 | { 134 | mThisDevice.setName(QHostInfo::localHostName()); 135 | mBCPort = DefaultBroadcastPort; 136 | mTransferPort = DefaultTransferPort; 137 | mBCInterval = DefaultBroadcastInterval; 138 | mFileBuffSize = DefaultFileBufferSize; 139 | mDownloadDir = getDefaultDownloadPath(); 140 | } 141 | 142 | quint16 Settings::getBroadcastPort() const 143 | { 144 | return mBCPort; 145 | } 146 | 147 | quint16 Settings::getTransferPort() const 148 | { 149 | return mTransferPort; 150 | } 151 | 152 | quint16 Settings::getBroadcastInterval() const 153 | { 154 | return mBCInterval; 155 | } 156 | 157 | qint32 Settings::getFileBufferSize() const 158 | { 159 | return mFileBuffSize; 160 | } 161 | 162 | QString Settings::getDownloadDir() const 163 | { 164 | return mDownloadDir; 165 | } 166 | 167 | Device Settings::getMyDevice() const 168 | { 169 | return mThisDevice; 170 | } 171 | 172 | QString Settings::getDeviceId() const 173 | { 174 | return mThisDevice.getId(); 175 | } 176 | 177 | QString Settings::getDeviceName() const 178 | { 179 | return mThisDevice.getName(); 180 | } 181 | 182 | QHostAddress Settings::getDeviceAddress() const 183 | { 184 | return mThisDevice.getAddress(); 185 | } 186 | 187 | bool Settings::getReplaceExistingFile() const 188 | { 189 | return mReplaceExistingFile; 190 | } 191 | 192 | -------------------------------------------------------------------------------- /src/settings.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef SETTINGS_H 20 | #define SETTINGS_H 21 | 22 | #include 23 | #include 24 | 25 | #include "model/device.h" 26 | 27 | 28 | #if defined (Q_OS_WIN) 29 | #define OS_NAME "Windows" 30 | #elif defined (Q_OS_OSX) 31 | #define OS_NAME "Mac OSX" 32 | #elif defined (Q_OS_LINUX) 33 | #define OS_NAME "Linux" 34 | #else 35 | #define OS_NAME "Unknown" 36 | #endif 37 | 38 | const QString PROGRAM_NAME{"LAN Share"}; 39 | const QString PROGRAM_DESC{"A simple program that let you transfer files over local area network (LAN) easily."}; 40 | constexpr int PROGRAM_X_VER{1}; 41 | constexpr int PROGRAM_Y_VER{2}; 42 | constexpr int PROGRAM_Z_VER{1}; 43 | const QString SETTINGS_FILE{"LANSConfig"}; 44 | 45 | class Settings 46 | { 47 | public: 48 | static Settings* instance() { return obj; } 49 | 50 | quint16 getBroadcastPort() const; 51 | quint16 getTransferPort() const; 52 | quint16 getBroadcastInterval() const; 53 | qint32 getFileBufferSize() const; 54 | QString getDownloadDir() const; 55 | 56 | Device getMyDevice() const; 57 | QString getDeviceId() const; 58 | QString getDeviceName() const; 59 | QHostAddress getDeviceAddress() const; 60 | bool getReplaceExistingFile() const; 61 | 62 | void setDeviceName(const QString& name); 63 | void setBroadcastPort(quint16 port); 64 | void setTransferPort(quint16 port); 65 | void setBroadcastInterval(quint16 interval); 66 | void setFileBufferSize(qint32 size); 67 | void setDownloadDir(const QString& dir); 68 | void setReplaceExistingFile(bool replace); 69 | 70 | void saveSettings(); 71 | void reset(); 72 | 73 | private: 74 | Settings(); 75 | void loadSettings(); 76 | 77 | QString getDefaultDownloadPath(); 78 | 79 | Device mThisDevice; 80 | quint16 mBCPort{0}; 81 | quint16 mTransferPort{0}; 82 | quint16 mBCInterval{0}; 83 | qint32 mFileBuffSize{0}; 84 | QString mDownloadDir; 85 | bool mReplaceExistingFile{false}; 86 | 87 | static Settings* obj; 88 | }; 89 | 90 | #endif // SETTINGS_H 91 | -------------------------------------------------------------------------------- /src/singleinstance.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | #include "singleinstance.h" 22 | 23 | SingleInstance::SingleInstance(const QString& name, QObject* parent) 24 | : QObject(parent), mName(name) 25 | { 26 | connect(&mServer, &QLocalServer::newConnection, this, &SingleInstance::onNewConnection); 27 | } 28 | 29 | QString SingleInstance::getLastErrorString() const 30 | { 31 | return mServer.errorString(); 32 | } 33 | 34 | bool SingleInstance::start() 35 | { 36 | mServer.removeServer(mName); 37 | return mServer.listen(mName); 38 | } 39 | 40 | bool SingleInstance::hasPreviousInstance() 41 | { 42 | QLocalSocket socket; 43 | socket.connectToServer(mName); 44 | 45 | return socket.waitForConnected(); 46 | } 47 | 48 | void SingleInstance::onNewConnection() 49 | { 50 | emit newInstanceCreated(); 51 | } 52 | -------------------------------------------------------------------------------- /src/singleinstance.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | 20 | #ifndef SINGLEINSTANCE_H 21 | #define SINGLEINSTANCE_H 22 | 23 | #include 24 | #include 25 | 26 | /* 27 | * SingleInstance, digunakan agar aplikasi hanya memiliki satu instance 28 | * yang berjalan disistem operasi 29 | */ 30 | class SingleInstance : public QObject 31 | { 32 | Q_OBJECT 33 | 34 | public: 35 | SingleInstance(const QString& id, QObject* parent = nullptr); 36 | 37 | QString getLastErrorString() const; 38 | bool start(); 39 | bool hasPreviousInstance(); 40 | 41 | Q_SIGNALS: 42 | void newInstanceCreated(); 43 | 44 | private Q_SLOTS: 45 | void onNewConnection(); 46 | 47 | private: 48 | 49 | QLocalServer mServer; 50 | QString mName; 51 | }; 52 | 53 | #endif // SINGLEINSTANCE_H 54 | -------------------------------------------------------------------------------- /src/text/credits.html: -------------------------------------------------------------------------------- 1 | 2 | 5 |

Created by Abdul Aris R.

6 |


7 |

Icons by icons8.com

8 | -------------------------------------------------------------------------------- /src/transfer/devicebroadcaster.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include "devicebroadcaster.h" 20 | #include "settings.h" 21 | 22 | #include 23 | 24 | DeviceBroadcaster::DeviceBroadcaster(QObject *parent) : QObject(parent) 25 | { 26 | connect(&mTimer, &QTimer::timeout, this, &DeviceBroadcaster::sendBroadcast); 27 | connect(&mUdpSock, &QUdpSocket::readyRead, this, &DeviceBroadcaster::processBroadcast); 28 | 29 | mUdpSock.bind(Settings::instance()->getBroadcastPort(), QUdpSocket::ShareAddress); 30 | } 31 | 32 | void DeviceBroadcaster::start() 33 | { 34 | sendBroadcast(); 35 | if (!mTimer.isActive()) 36 | mTimer.start(Settings::instance()->getBroadcastInterval()); 37 | } 38 | 39 | void DeviceBroadcaster::sendBroadcast() 40 | { 41 | int port = Settings::instance()->getBroadcastPort(); 42 | Device dev = Settings::instance()->getMyDevice(); 43 | QJsonObject obj(QJsonObject::fromVariantMap({ 44 | {"id", dev.getId()}, 45 | {"name", dev.getName()}, 46 | {"os", dev.getOSName()}, 47 | {"port", port} 48 | })); 49 | 50 | QVector addresses = getBroadcastAddressFromInterfaces(); 51 | QByteArray data(QJsonDocument(obj).toJson(QJsonDocument::Compact)); 52 | foreach (QHostAddress address, addresses) { 53 | mUdpSock.writeDatagram(data, address, port); 54 | } 55 | } 56 | 57 | /* 58 | * proses broadcast yang diterima dari Device lain di jaringan 59 | */ 60 | void DeviceBroadcaster::processBroadcast() 61 | { 62 | while (mUdpSock.hasPendingDatagrams()) { 63 | QByteArray data; 64 | 65 | qint64 datagramSize = mUdpSock.pendingDatagramSize(); 66 | assert(datagramSize <= std::numeric_limits ::max()); 67 | 68 | data.resize(static_cast(datagramSize)); 69 | QHostAddress sender; 70 | 71 | mUdpSock.readDatagram(data.data(), data.size(), &sender); 72 | 73 | QJsonObject obj = QJsonDocument::fromJson(data).object(); 74 | if (obj.keys().length() == 4) { 75 | if (obj.value("port").toVariant().value() == 76 | Settings::instance()->getBroadcastPort()) { 77 | 78 | Device device{obj.value("id").toString(), obj.value("name").toString(), 79 | obj.value("os").toString(), sender}; 80 | emit broadcastReceived(device); 81 | } 82 | } 83 | } 84 | } 85 | 86 | QVector DeviceBroadcaster::getBroadcastAddressFromInterfaces() 87 | { 88 | QVector addresses; 89 | foreach (QNetworkInterface iface, QNetworkInterface::allInterfaces()) { 90 | if (iface.flags() & QNetworkInterface::CanBroadcast) { 91 | foreach (QNetworkAddressEntry addressEntry, iface.addressEntries()) { 92 | if (!addressEntry.broadcast().isNull()) { 93 | addresses.push_back(addressEntry.broadcast()); 94 | } 95 | } 96 | } 97 | } 98 | return addresses; 99 | } 100 | -------------------------------------------------------------------------------- /src/transfer/devicebroadcaster.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef DEVICEBROADCASTER_H 20 | #define DEVICEBROADCASTER_H 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "model/device.h" 27 | 28 | /* 29 | * DeviceBroadcaster digunakan untuk membroadcast Device, 30 | * dengan mengirim packet data berisi informasi Device menggunakan 31 | * protokol UDP 32 | */ 33 | class DeviceBroadcaster : public QObject 34 | { 35 | Q_OBJECT 36 | 37 | public: 38 | explicit DeviceBroadcaster(QObject *parent = nullptr); 39 | 40 | Q_SIGNALS: 41 | void broadcastReceived(const Device& fromDevice); 42 | 43 | public Q_SLOTS: 44 | void start(); 45 | void sendBroadcast(); 46 | 47 | private Q_SLOTS: 48 | void processBroadcast(); 49 | 50 | private: 51 | QVector getBroadcastAddressFromInterfaces(); 52 | 53 | QTimer mTimer; 54 | QUdpSocket mUdpSock; 55 | }; 56 | 57 | #endif // DEVICEBROADCASTER_H 58 | -------------------------------------------------------------------------------- /src/transfer/receiver.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "util.h" 24 | #include "receiver.h" 25 | #include "settings.h" 26 | 27 | Receiver::Receiver(const Device& sender, QTcpSocket* socket, QObject* parent) 28 | : Transfer(socket, parent), mSenderDev(sender), mFileSize(0), mBytesRead(0) 29 | { 30 | mInfo->setState(TransferState::Waiting); 31 | connect(mSocket, &QTcpSocket::disconnected, this, &Receiver::onDisconnected); 32 | 33 | mInfo->setTransferType(TransferType::Download); 34 | mInfo->setPeer(sender); 35 | } 36 | 37 | void Receiver::resume() 38 | { 39 | if (mInfo->canResume()) { 40 | mInfo->setState(mInfo->getLastState()); 41 | writePacket(0, PacketType::Resume, QByteArray()); 42 | } 43 | } 44 | 45 | void Receiver::pause() 46 | { 47 | if (mInfo->canPause()) { 48 | mInfo->setState(TransferState::Paused); 49 | writePacket(0, PacketType::Pause, QByteArray()); 50 | } 51 | } 52 | 53 | void Receiver::cancel() 54 | { 55 | if (mInfo->canCancel()) { 56 | mInfo->setState(TransferState::Cancelled); 57 | mInfo->setProgress(0); 58 | clearReadBuffer(); 59 | writePacket(0, PacketType::Cancel, QByteArray()); 60 | mFile->remove(); 61 | } 62 | } 63 | 64 | void Receiver::onDisconnected() 65 | { 66 | mInfo->setState(TransferState::Disconnected); 67 | emit mInfo->errorOcurred("Sender disconnected"); 68 | } 69 | 70 | void Receiver::processHeaderPacket(QByteArray& data) 71 | { 72 | QJsonObject obj = QJsonDocument::fromJson(data).object(); 73 | mFileSize = obj.value("size").toVariant().value(); 74 | mInfo->setDataSize(mFileSize); 75 | 76 | QString fileName = obj.value("name").toString(); 77 | QString folderName = obj.value("folder").toString(); 78 | QString dstFolderPath = Settings::instance()->getDownloadDir(); 79 | if (!folderName.isEmpty()) 80 | dstFolderPath = dstFolderPath + QDir::separator() + folderName; 81 | 82 | /* 83 | * Jika folder didalam Download Dir tidak ada maka buat folder tsb. 84 | */ 85 | QDir dir(dstFolderPath); 86 | if (!dir.exists()) { 87 | dir.mkpath(dstFolderPath); 88 | } 89 | 90 | QString dstFilePath = dstFolderPath + QDir::separator() + fileName; 91 | /* 92 | * Jika opsi overwrite tdk dicentang maka rename file agar tdk tertindih 93 | */ 94 | if (!Settings::instance()->getReplaceExistingFile()) { 95 | dstFilePath = Util::getUniqueFileName(fileName, dstFolderPath); 96 | } 97 | 98 | mInfo->setFilePath(dstFilePath); 99 | mFile = new QFile(dstFilePath, this); 100 | if (mFile->open(QIODevice::WriteOnly)) { 101 | mInfo->setState(TransferState::Transfering); 102 | emit mInfo->fileOpened(); 103 | } 104 | else { 105 | emit mInfo->errorOcurred(tr("Failed to write ") + dstFilePath); 106 | } 107 | } 108 | 109 | void Receiver::processDataPacket(QByteArray& data) 110 | { 111 | if (mFile && mBytesRead + data.size() <= mFileSize) { 112 | mFile->write(data); 113 | mBytesRead += data.size(); 114 | 115 | mInfo->setProgress( (int)(mBytesRead * 100 / mFileSize) ); 116 | } 117 | } 118 | 119 | void Receiver::processFinishPacket(QByteArray& data) 120 | { 121 | Q_UNUSED(data); 122 | 123 | mInfo->setState(TransferState::Finish); 124 | mFile->close(); 125 | mSocket->disconnectFromHost(); 126 | emit mInfo->done(); 127 | } 128 | 129 | void Receiver::processCancelPacket(QByteArray& data) 130 | { 131 | Q_UNUSED(data); 132 | 133 | mInfo->setState(TransferState::Cancelled); 134 | mInfo->setProgress(0); 135 | clearReadBuffer(); 136 | mFile->remove(); 137 | mSocket->disconnectFromHost(); 138 | } 139 | -------------------------------------------------------------------------------- /src/transfer/receiver.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef RECEIVER_H 20 | #define RECEIVER_H 21 | 22 | #include "transfer.h" 23 | #include "model/device.h" 24 | 25 | class Receiver : public Transfer 26 | { 27 | public: 28 | Receiver(const Device& sender, QTcpSocket* socket, QObject* parent = nullptr); 29 | 30 | inline Device getSender() const { return mSenderDev; } 31 | inline qint64 getReceivedFileSize() const { return mFileSize; } 32 | inline qint64 getBytesWritten() const { return mBytesRead; } 33 | 34 | void resume() override; 35 | void pause() override; 36 | void cancel() override; 37 | 38 | private Q_SLOTS: 39 | void onDisconnected(); 40 | 41 | private: 42 | void processHeaderPacket(QByteArray& data) override; 43 | void processDataPacket(QByteArray& data) override; 44 | void processFinishPacket(QByteArray& data) override; 45 | void processCancelPacket(QByteArray& data) override; 46 | 47 | Device mSenderDev; 48 | 49 | qint64 mFileSize; 50 | qint64 mBytesRead; 51 | }; 52 | 53 | #endif // RECEIVER_H 54 | -------------------------------------------------------------------------------- /src/transfer/sender.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "settings.h" 25 | #include "sender.h" 26 | 27 | Sender::Sender(const Device& receiver, const QString& folderName, const QString& filePath, QObject* parent) 28 | : Transfer(nullptr, parent), mReceiverDev(receiver), mFilePath(filePath), mFolderName(folderName) 29 | { 30 | mFileSize = -1; 31 | mBytesRemaining = -1; 32 | 33 | mFileBuffSize = Settings::instance()->getFileBufferSize(); 34 | mFileBuff.resize(mFileBuffSize); 35 | 36 | mCancelled = false; 37 | mPaused = false; 38 | mPausedByReceiver = false; 39 | mIsHeaderSent = false; 40 | 41 | mInfo->setTransferType(TransferType::Upload); 42 | mInfo->setPeer(receiver); 43 | } 44 | 45 | bool Sender::start() 46 | { 47 | mInfo->setFilePath(mFilePath); 48 | mFile = new QFile(mFilePath, this); 49 | bool ok = mFile->open(QIODevice::ReadOnly); 50 | if (ok) { 51 | mFileSize = mFile->size(); 52 | mInfo->setDataSize(mFileSize); 53 | mBytesRemaining = mFileSize; 54 | emit mInfo->fileOpened(); 55 | } 56 | 57 | if (mFileSize > 0) { 58 | QHostAddress receiverAddress = mReceiverDev.getAddress(); 59 | setSocket(new QTcpSocket(this)); 60 | mSocket->connectToHost(receiverAddress, Settings::instance()->getTransferPort(), QAbstractSocket::ReadWrite); 61 | mInfo->setState(TransferState::Waiting); 62 | 63 | connect(mSocket, &QTcpSocket::bytesWritten, this, &Sender::onBytesWritten); 64 | connect(mSocket, &QTcpSocket::connected, this, &Sender::onConnected); 65 | connect(mSocket, &QTcpSocket::disconnected, this, &Sender::onDisconnected); 66 | } 67 | 68 | return ok && mSocket; 69 | } 70 | 71 | void Sender::resume() 72 | { 73 | if (mInfo->canResume()) { 74 | mInfo->setState(mInfo->getLastState()); 75 | mPaused = false; 76 | sendData(); 77 | } 78 | } 79 | 80 | void Sender::pause() 81 | { 82 | if (mInfo->canPause()) { 83 | mInfo->setState(TransferState::Paused); 84 | mPaused = true; 85 | } 86 | } 87 | 88 | void Sender::cancel() 89 | { 90 | if (mInfo->canCancel()) { 91 | writePacket(0, PacketType::Cancel, QByteArray()); 92 | mInfo->setState(TransferState::Cancelled); 93 | mInfo->setProgress(0); 94 | mCancelled = true; 95 | } 96 | } 97 | 98 | void Sender::onConnected() 99 | { 100 | mInfo->setState(TransferState::Transfering); 101 | sendHeader(); 102 | } 103 | 104 | void Sender::onDisconnected() 105 | { 106 | mInfo->setState(TransferState::Disconnected); 107 | emit mInfo->errorOcurred(tr("Receiver disconnected")); 108 | } 109 | 110 | void Sender::onBytesWritten(qint64 bytes) 111 | { 112 | Q_UNUSED(bytes); 113 | 114 | if (!mSocket->bytesToWrite()) { 115 | sendData(); 116 | } 117 | } 118 | 119 | void Sender::finish() 120 | { 121 | mFile->close(); 122 | mInfo->setState(TransferState::Finish); 123 | emit mInfo->done(); 124 | 125 | writePacket(0, PacketType::Finish, QByteArray()); 126 | } 127 | 128 | void Sender::sendData() 129 | { 130 | if (!mBytesRemaining || mCancelled || mPausedByReceiver || mPaused) 131 | return; 132 | 133 | if (mBytesRemaining < mFileBuffSize) { 134 | mFileBuff.resize(mBytesRemaining); 135 | mFileBuffSize = mFileBuff.size(); 136 | } 137 | 138 | qint64 bytesRead = mFile->read(mFileBuff.data(), mFileBuffSize); 139 | if (bytesRead == -1) { 140 | emit mInfo->errorOcurred(tr("Error while reading file.")); 141 | return; 142 | } 143 | 144 | mBytesRemaining -= bytesRead; 145 | if (mBytesRemaining < 0) 146 | mBytesRemaining = 0; 147 | 148 | mInfo->setProgress( (int) ((mFileSize-mBytesRemaining) * 100 / mFileSize) ); 149 | 150 | writePacket(mFileBuffSize, PacketType::Data, mFileBuff); 151 | 152 | if (!mBytesRemaining) { 153 | finish(); 154 | } 155 | } 156 | 157 | void Sender::sendHeader() 158 | { 159 | QString fName = QDir(mFile->fileName()).dirName(); 160 | 161 | QJsonObject obj( QJsonObject::fromVariantMap({ 162 | {"name", fName}, 163 | {"folder", mFolderName }, 164 | {"size", mFileSize} 165 | })); 166 | 167 | QByteArray headerData( QJsonDocument(obj).toJson() ); 168 | 169 | writePacket(headerData.size(), PacketType::Header, headerData); 170 | mIsHeaderSent = true; 171 | } 172 | 173 | void Sender::processCancelPacket(QByteArray& data) 174 | { 175 | Q_UNUSED(data); 176 | 177 | mInfo->setState(TransferState::Cancelled); 178 | mInfo->setProgress(0); 179 | mSocket->disconnectFromHost(); 180 | mCancelled = true; 181 | } 182 | 183 | void Sender::processPausePacket(QByteArray& data) 184 | { 185 | Q_UNUSED(data); 186 | 187 | mPausedByReceiver = true; 188 | } 189 | 190 | void Sender::processResumePacket(QByteArray& data) 191 | { 192 | Q_UNUSED(data); 193 | 194 | mPausedByReceiver = false; 195 | if (mIsHeaderSent) 196 | sendData(); 197 | else 198 | sendHeader(); 199 | } 200 | 201 | -------------------------------------------------------------------------------- /src/transfer/sender.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef SENDER_H 20 | #define SENDER_H 21 | 22 | #include "transfer.h" 23 | #include "model/device.h" 24 | 25 | class Sender : public Transfer 26 | { 27 | public: 28 | Sender(const Device& receiver, const QString& folderName, const QString& filePath, QObject* parent = nullptr); 29 | 30 | bool start(); 31 | 32 | Device getReceiver() const { return mReceiverDev; } 33 | 34 | void resume() override; 35 | void pause() override; 36 | void cancel() override; 37 | 38 | private Q_SLOTS: 39 | void onBytesWritten(qint64 bytes); 40 | void onConnected(); 41 | void onDisconnected(); 42 | 43 | private: 44 | void finish(); 45 | void sendData(); 46 | void sendHeader(); 47 | 48 | void processCancelPacket(QByteArray& data) override; 49 | void processPausePacket(QByteArray& data) override; 50 | void processResumePacket(QByteArray& data) override; 51 | 52 | Device mReceiverDev; 53 | QString mFilePath; 54 | QString mFolderName; 55 | qint64 mFileSize; 56 | qint64 mBytesRemaining; 57 | 58 | QByteArray mFileBuff; 59 | qint32 mFileBuffSize; 60 | 61 | bool mCancelled; 62 | bool mPaused; 63 | bool mPausedByReceiver; 64 | bool mIsHeaderSent; 65 | }; 66 | 67 | #endif // SENDER_H 68 | -------------------------------------------------------------------------------- /src/transfer/transfer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include "transfer.h" 20 | 21 | Transfer::Transfer(QTcpSocket* socket, QObject* parent) 22 | : QObject(parent), mFile(nullptr), mSocket(nullptr), 23 | mPacketSize(-1) 24 | { 25 | mInfo = new TransferInfo(this, this); 26 | setSocket(socket); 27 | mHeaderSize = sizeof(PacketType) + sizeof(mPacketSize); 28 | } 29 | 30 | void Transfer::resume() 31 | { 32 | 33 | } 34 | 35 | void Transfer::pause() 36 | { 37 | 38 | } 39 | 40 | void Transfer::cancel() 41 | { 42 | 43 | } 44 | 45 | void Transfer::onReadyRead() 46 | { 47 | /* 48 | * Abaikan data yg diterima jika state transfer 'Cancelled' (Dibatalkan) 49 | */ 50 | if (mInfo->getState() == TransferState::Cancelled) 51 | return; 52 | 53 | mBuff.append(mSocket->readAll()); 54 | 55 | /* 56 | * Jika ukuran buffer sudah >= ukuran header, maka pda buffer tsb 57 | * terdapat data header yg dpt kita extrak 58 | * dt header --> packet size (4 bytes) & packet type (1 byte) 59 | */ 60 | while (mBuff.size() >= mHeaderSize) { 61 | if (mPacketSize < 0) { 62 | memcpy(&mPacketSize, mBuff.constData(), sizeof(mPacketSize)); 63 | mBuff.remove(0, sizeof(mPacketSize)); 64 | } 65 | 66 | if (mBuff.size() > mPacketSize) { 67 | PacketType type = static_cast(mBuff.at(0)); 68 | QByteArray data = mBuff.mid(1, mPacketSize); 69 | 70 | processPacket(data, type); 71 | mBuff.remove(0, mPacketSize + 1); 72 | 73 | mPacketSize = -1; 74 | } 75 | else { 76 | break; 77 | } 78 | } 79 | } 80 | 81 | void Transfer::writePacket(qint32 packetDataSize, PacketType type, const QByteArray &data) 82 | { 83 | if (mSocket) { 84 | mSocket->write(reinterpret_cast(&packetDataSize), sizeof(packetDataSize)); 85 | mSocket->write(reinterpret_cast(&type), sizeof(type)); 86 | mSocket->write(data); 87 | } 88 | } 89 | 90 | void Transfer::processPacket(QByteArray &data, PacketType type) 91 | { 92 | switch (type) { 93 | case PacketType::Header : processHeaderPacket(data); break; 94 | case PacketType::Data : processDataPacket(data); break; 95 | case PacketType::Finish : processFinishPacket(data); break; 96 | case PacketType::Cancel : processCancelPacket(data); break; 97 | case PacketType::Pause : processPausePacket(data); break; 98 | case PacketType::Resume : processResumePacket(data); break; 99 | } 100 | } 101 | 102 | void Transfer::processHeaderPacket(QByteArray& data) 103 | { 104 | Q_UNUSED(data); 105 | } 106 | 107 | void Transfer::processDataPacket(QByteArray& data) 108 | { 109 | Q_UNUSED(data); 110 | } 111 | 112 | void Transfer::processFinishPacket(QByteArray& data) 113 | { 114 | Q_UNUSED(data); 115 | } 116 | 117 | void Transfer::processCancelPacket(QByteArray& data) 118 | { 119 | Q_UNUSED(data); 120 | } 121 | 122 | void Transfer::processPausePacket(QByteArray& data) 123 | { 124 | Q_UNUSED(data); 125 | } 126 | 127 | void Transfer::processResumePacket(QByteArray& data) 128 | { 129 | Q_UNUSED(data); 130 | } 131 | 132 | 133 | void Transfer::clearReadBuffer() 134 | { 135 | mBuff.clear(); 136 | mPacketSize = -1; 137 | } 138 | 139 | void Transfer::setSocket(QTcpSocket *socket) 140 | { 141 | if (socket) { 142 | mSocket = socket; 143 | connect(mSocket, &QTcpSocket::readyRead, this, &Transfer::onReadyRead); 144 | } 145 | } 146 | 147 | -------------------------------------------------------------------------------- /src/transfer/transfer.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef TRANSFER_H 20 | #define TRANSFER_H 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "model/device.h" 27 | #include "model/transferinfo.h" 28 | 29 | 30 | enum class PacketType : char 31 | { 32 | Header = 0x01, 33 | Data, 34 | Finish, 35 | Cancel, 36 | Pause, 37 | Resume 38 | }; 39 | 40 | class Transfer : public QObject 41 | { 42 | Q_OBJECT 43 | 44 | public: 45 | Transfer(QTcpSocket* socket, QObject* parent = nullptr); 46 | 47 | inline QFile* getFile() const { return mFile; } 48 | inline QTcpSocket* getSocket() const { return mSocket; } 49 | inline TransferInfo* getTransferInfo() const { return mInfo; } 50 | 51 | virtual void resume(); 52 | virtual void pause(); 53 | virtual void cancel(); 54 | 55 | protected: 56 | void clearReadBuffer(); 57 | void setSocket(QTcpSocket* socket); 58 | 59 | virtual void processPacket(QByteArray& data, PacketType type); 60 | virtual void processHeaderPacket(QByteArray& data); 61 | virtual void processDataPacket(QByteArray& data); 62 | virtual void processFinishPacket(QByteArray& data); 63 | virtual void processCancelPacket(QByteArray& data); 64 | virtual void processPausePacket(QByteArray& data); 65 | virtual void processResumePacket(QByteArray& data); 66 | 67 | virtual void writePacket(qint32 packetDataSize, PacketType type, const QByteArray& data); 68 | 69 | QFile* mFile; 70 | QTcpSocket* mSocket; 71 | TransferInfo* mInfo; 72 | 73 | private Q_SLOTS: 74 | void onReadyRead(); 75 | 76 | private: 77 | 78 | // 79 | QByteArray mBuff; 80 | qint32 mPacketSize; 81 | 82 | int mHeaderSize; 83 | }; 84 | 85 | #endif // TRANSFER_H 86 | -------------------------------------------------------------------------------- /src/transfer/transferserver.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include "transferserver.h" 20 | 21 | #include "settings.h" 22 | 23 | TransferServer::TransferServer(DeviceListModel* devList, QObject *parent) : QObject(parent) 24 | { 25 | mDevList = devList; 26 | mServer = new QTcpServer(this); 27 | connect(mServer, &QTcpServer::newConnection, this, &TransferServer::onNewConnection); 28 | } 29 | 30 | bool TransferServer::listen(const QHostAddress &addr) 31 | { 32 | return mServer->listen(addr, Settings::instance()->getTransferPort()); 33 | } 34 | 35 | void TransferServer::onNewConnection() 36 | { 37 | QTcpSocket* socket = mServer->nextPendingConnection(); 38 | if (socket) { 39 | Device dev = mDevList->device(socket->peerAddress()); 40 | Receiver* rec = new Receiver(dev, socket); 41 | mReceivers.push_back(rec); 42 | emit newReceiverAdded(rec); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/transfer/transferserver.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef TRANSFERSERVER_H 20 | #define TRANSFERSERVER_H 21 | 22 | #include 23 | #include 24 | 25 | #include "receiver.h" 26 | #include "model/devicelistmodel.h" 27 | 28 | class TransferServer : public QObject 29 | { 30 | Q_OBJECT 31 | 32 | public: 33 | explicit TransferServer(DeviceListModel* devList, QObject *parent = nullptr); 34 | 35 | bool listen(const QHostAddress& addr = QHostAddress::Any); 36 | 37 | Q_SIGNALS: 38 | void newReceiverAdded(Receiver* receiver); 39 | 40 | private Q_SLOTS: 41 | void onNewConnection(); 42 | 43 | private: 44 | DeviceListModel* mDevList; 45 | QTcpServer* mServer; 46 | QVector mReceivers; 47 | }; 48 | 49 | #endif // TRANSFERSERVER_H 50 | -------------------------------------------------------------------------------- /src/ui/aboutdialog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | #include "aboutdialog.h" 22 | #include "ui_aboutdialog.h" 23 | #include "settings.h" 24 | #include "util.h" 25 | 26 | AboutDialog::AboutDialog(QWidget *parent) : 27 | QDialog(parent), 28 | ui(new Ui::AboutDialog), 29 | mCredits(""), mLicense("") 30 | { 31 | ui->setupUi(this); 32 | 33 | ui->programNameLbl->setText(PROGRAM_NAME); 34 | ui->programVersionLbl->setText(Util::parseAppVersion(false)); 35 | ui->programDescLbl->setText(PROGRAM_DESC); 36 | 37 | ui->textEdit->setVisible(false); 38 | } 39 | 40 | AboutDialog::~AboutDialog() 41 | { 42 | delete ui; 43 | } 44 | 45 | void AboutDialog::onCreditsClicked(bool checked) 46 | { 47 | if (checked) { 48 | if (mCredits.isEmpty()) { 49 | QFile file(":/text/credits.html"); 50 | file.open(QIODevice::ReadOnly); 51 | mCredits = file.readAll(); 52 | } 53 | ui->textEdit->setText(mCredits); 54 | } 55 | 56 | ui->textContent->setVisible(!checked); 57 | ui->textEdit->setVisible(checked); 58 | ui->licenseBtn->setChecked(false); 59 | } 60 | 61 | void AboutDialog::onLicenseClicked(bool checked) 62 | { 63 | if (checked) { 64 | if (mLicense.isEmpty()) { 65 | QFile file(":/text/gpl-3.0.txt"); 66 | file.open(QIODevice::ReadOnly); 67 | mLicense = file.readAll(); 68 | } 69 | ui->textEdit->setText(mLicense); 70 | } 71 | 72 | ui->textContent->setVisible(!checked); 73 | ui->textEdit->setVisible(checked); 74 | ui->creditBtn->setChecked(false); 75 | } 76 | -------------------------------------------------------------------------------- /src/ui/aboutdialog.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef ABOUTDIALOG_H 20 | #define ABOUTDIALOG_H 21 | 22 | #include 23 | 24 | namespace Ui { 25 | class AboutDialog; 26 | } 27 | 28 | class AboutDialog : public QDialog 29 | { 30 | Q_OBJECT 31 | 32 | public: 33 | explicit AboutDialog(QWidget *parent = nullptr); 34 | ~AboutDialog() override; 35 | 36 | private Q_SLOTS: 37 | void onCreditsClicked(bool checked); 38 | void onLicenseClicked(bool checked); 39 | 40 | private: 41 | 42 | Ui::AboutDialog *ui; 43 | 44 | QString mCredits; 45 | QString mLicense; 46 | }; 47 | 48 | #endif // ABOUTDIALOG_H 49 | -------------------------------------------------------------------------------- /src/ui/aboutdialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | AboutDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 480 10 | 350 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | 21 | 480 22 | 350 23 | 24 | 25 | 26 | 27 | 480 28 | 350 29 | 30 | 31 | 32 | About 33 | 34 | 35 | 36 | :/img/about.png:/img/about.png 37 | 38 | 39 | 40 | 41 | 42 | 43 | 0 44 | 0 45 | 46 | 47 | 48 | 49 | 16777215 50 | 16777215 51 | 52 | 53 | 54 | 55 | 56 | 57 | :/img/icon.png 58 | 59 | 60 | false 61 | 62 | 63 | Qt::AlignCenter 64 | 65 | 66 | 67 | 68 | 69 | 70 | font-weight: bold 71 | 72 | 73 | TextLabel 74 | 75 | 76 | Qt::AlignCenter 77 | 78 | 79 | true 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 0 88 | 89 | 90 | 9 91 | 92 | 93 | 0 94 | 95 | 96 | 97 | 98 | color: rgb(31, 31, 31); 99 | 100 | 101 | TextLabel 102 | 103 | 104 | Qt::AlignCenter 105 | 106 | 107 | true 108 | 109 | 110 | 111 | 112 | 113 | 114 | color: rgb(31, 31, 31); 115 | 116 | 117 | TextLabel 118 | 119 | 120 | Qt::AlignCenter 121 | 122 | 123 | true 124 | 125 | 126 | 127 | 128 | 129 | 130 | Qt::Vertical 131 | 132 | 133 | 134 | 20 135 | 40 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | Qt::Horizontal 144 | 145 | 146 | 147 | 148 | 149 | 150 | <html><head/><body><p><span style=" font-size:8pt; color:#2b2b2b;">Copyright (c) 2016, Abdul Aris R.</span></p></body></html> 151 | 152 | 153 | Qt::AlignCenter 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | font: 8pt "Sans"; 164 | 165 | 166 | true 167 | 168 | 169 | Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse 170 | 171 | 172 | 173 | 174 | 175 | 176 | 6 177 | 178 | 179 | 180 | 181 | Credits 182 | 183 | 184 | true 185 | 186 | 187 | false 188 | 189 | 190 | 191 | 192 | 193 | 194 | License 195 | 196 | 197 | true 198 | 199 | 200 | false 201 | 202 | 203 | 204 | 205 | 206 | 207 | Qt::Horizontal 208 | 209 | 210 | 211 | 40 212 | 20 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 70 222 | 0 223 | 224 | 225 | 226 | 227 | 16777215 228 | 16777215 229 | 230 | 231 | 232 | Close 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | pushButton_3 246 | clicked() 247 | AboutDialog 248 | accept() 249 | 250 | 251 | 389 252 | 309 253 | 254 | 255 | 236 256 | 261 257 | 258 | 259 | 260 | 261 | creditBtn 262 | clicked(bool) 263 | AboutDialog 264 | onCreditsClicked(bool) 265 | 266 | 267 | 18 268 | 300 269 | 270 | 271 | 3 272 | 294 273 | 274 | 275 | 276 | 277 | licenseBtn 278 | clicked(bool) 279 | AboutDialog 280 | onLicenseClicked(bool) 281 | 282 | 283 | 140 284 | 300 285 | 286 | 287 | 208 288 | 290 289 | 290 | 291 | 292 | 293 | 294 | onCreditsClicked(bool) 295 | onLicenseClicked(bool) 296 | 297 | 298 | -------------------------------------------------------------------------------- /src/ui/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "mainwindow.h" 31 | #include "ui_mainwindow.h" 32 | 33 | #include "receiverselectordialog.h" 34 | #include "settingsdialog.h" 35 | #include "settings.h" 36 | #include "aboutdialog.h" 37 | #include "util.h" 38 | #include "transfer/sender.h" 39 | #include "transfer/receiver.h" 40 | 41 | MainWindow::MainWindow(QWidget *parent) : 42 | QMainWindow(parent), 43 | ui(new Ui::MainWindow) 44 | { 45 | ui->setupUi(this); 46 | setupActions(); 47 | setupToolbar(); 48 | setupSystrayIcon(); 49 | setWindowTitle(PROGRAM_NAME); 50 | 51 | mBroadcaster = new DeviceBroadcaster(this); 52 | mBroadcaster->start(); 53 | mSenderModel = new TransferTableModel(this); 54 | mReceiverModel = new TransferTableModel(this); 55 | mDeviceModel = new DeviceListModel(mBroadcaster, this); 56 | mTransServer = new TransferServer(mDeviceModel, this); 57 | mTransServer->listen(); 58 | 59 | // mSenderModel->setHeaderData((int) TransferTableModel::Column::Peer, Qt::Horizontal, tr("Receiver")); 60 | // mReceiverModel->setHeaderData((int) TransferTableModel::Column::Peer, Qt::Horizontal, tr("Sender")); 61 | 62 | ui->senderTableView->setModel(mSenderModel); 63 | ui->receiverTableView->setModel(mReceiverModel); 64 | 65 | ui->senderTableView->setColumnWidth((int)TransferTableModel::Column::FileName, 340); 66 | ui->senderTableView->setColumnWidth((int)TransferTableModel::Column::Progress, 160); 67 | 68 | ui->receiverTableView->setColumnWidth((int)TransferTableModel::Column::FileName, 340); 69 | ui->receiverTableView->setColumnWidth((int)TransferTableModel::Column::Progress, 160); 70 | 71 | connectSignals(); 72 | } 73 | 74 | MainWindow::~MainWindow() 75 | { 76 | delete ui; 77 | } 78 | 79 | /* 80 | * Sebelum ditutup, check apakah masih terdapat proses trasfer 81 | * yg berlangsung, (Sending atau Receiving) 82 | */ 83 | void MainWindow::closeEvent(QCloseEvent *event) 84 | { 85 | if (mSystrayIcon && mSystrayIcon->isVisible() && !mForceQuit) { 86 | setMainWindowVisibility(false); 87 | event->ignore(); 88 | return; 89 | } 90 | 91 | auto checkTransferState = [](Transfer* t) { 92 | if (!t) 93 | return false; 94 | TransferState state = t->getTransferInfo()->getState(); 95 | return state == TransferState::Paused || 96 | state == TransferState::Transfering || 97 | state == TransferState::Waiting; 98 | }; 99 | 100 | auto checkTransferModel = [&](TransferTableModel* model) { 101 | int count = model->rowCount(); 102 | for (int i = 0; i < count; i++) { 103 | Transfer* t = model->getTransfer(i); 104 | if (checkTransferState(t)) { 105 | return true; 106 | } 107 | } 108 | 109 | return false; 110 | }; 111 | 112 | bool needToConfirm = checkTransferModel(mSenderModel); 113 | if (!needToConfirm) 114 | needToConfirm = checkTransferModel(mReceiverModel); 115 | 116 | if (needToConfirm) { 117 | QMessageBox::StandardButton ret = 118 | QMessageBox::question(this, tr("Confirm close"), 119 | tr("You are about to close & abort all transfers. Do you want to continue?")); 120 | if (ret == QMessageBox::No) { 121 | event->ignore(); 122 | mForceQuit = false; 123 | return; 124 | } 125 | } 126 | 127 | event->accept(); 128 | qApp->quit(); 129 | } 130 | 131 | void MainWindow::setMainWindowVisibility(bool visible) 132 | { 133 | if (visible) { 134 | showNormal(); 135 | setWindowState(Qt::WindowNoState); 136 | qApp->processEvents(); 137 | setWindowState(Qt::WindowActive); 138 | qApp->processEvents(); 139 | qApp->setActiveWindow(this); 140 | qApp->processEvents(); 141 | } 142 | else { 143 | hide(); 144 | } 145 | } 146 | 147 | void MainWindow::connectSignals() 148 | { 149 | connect(mTransServer, &TransferServer::newReceiverAdded, this, &MainWindow::onNewReceiverAdded); 150 | 151 | QItemSelectionModel* senderSel = ui->senderTableView->selectionModel(); 152 | connect(senderSel, &QItemSelectionModel::selectionChanged, 153 | this, &MainWindow::onSenderTableSelectionChanged); 154 | 155 | QItemSelectionModel* receiverSel = ui->receiverTableView->selectionModel(); 156 | connect(receiverSel, &QItemSelectionModel::selectionChanged, 157 | this, &MainWindow::onReceiverTableSelectionChanged); 158 | } 159 | 160 | void MainWindow::sendFile(const QString& folderName, const QString &filePath, const Device &receiver) 161 | { 162 | Sender* sender = new Sender(receiver, folderName, filePath, this); 163 | sender->start(); 164 | mSenderModel->insertTransfer(sender); 165 | QModelIndex progressIdx = mSenderModel->index(0, (int)TransferTableModel::Column::Progress); 166 | 167 | /* 168 | * tambah progress bar pada item transfer 169 | */ 170 | QProgressBar* progress = new QProgressBar(); 171 | connect(sender->getTransferInfo(), &TransferInfo::progressChanged, progress, &QProgressBar::setValue); 172 | 173 | ui->senderTableView->setIndexWidget(progressIdx, progress); 174 | ui->senderTableView->scrollToTop(); 175 | } 176 | 177 | void MainWindow::selectReceiversAndSendTheFiles(QVector > dirNameAndFullPath) 178 | { 179 | ReceiverSelectorDialog dialog(mDeviceModel); 180 | if (dialog.exec() == QDialog::Accepted) { 181 | QVector receivers = dialog.getSelectedDevices(); 182 | for (const Device& receiver : receivers) { 183 | if (receiver.isValid()) { 184 | 185 | /* 186 | * Memastikan bahwa device/kompuer ini terdaftar di penerima 187 | * Just to make sure. 188 | */ 189 | mBroadcaster->sendBroadcast(); 190 | for (const auto& p : dirNameAndFullPath) { 191 | sendFile(p.first, p.second, receiver); 192 | } 193 | 194 | } 195 | } 196 | } 197 | } 198 | 199 | void MainWindow::onShowMainWindowTriggered() 200 | { 201 | setMainWindowVisibility(true); 202 | } 203 | 204 | void MainWindow::onSendFilesActionTriggered() 205 | { 206 | QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select files")); 207 | if (fileNames.size() <= 0) 208 | return; 209 | 210 | QVector > pairs; 211 | for (const auto& fName : fileNames) 212 | pairs.push_back( QPair("", fName) ); 213 | 214 | selectReceiversAndSendTheFiles(pairs); 215 | } 216 | 217 | void MainWindow::onSendFolderActionTriggered() 218 | { 219 | QStringList dirs; 220 | QFileDialog fDialog(this); 221 | fDialog.setOption(QFileDialog::DontUseNativeDialog, true); 222 | fDialog.setFileMode(QFileDialog::Directory); 223 | fDialog.setOption(QFileDialog::ShowDirsOnly); 224 | 225 | /* 226 | * Enable multiple foder selection 227 | */ 228 | QListView* lView = fDialog.findChild("listView"); 229 | if (lView) 230 | lView->setSelectionMode(QAbstractItemView::ExtendedSelection); 231 | QTreeView* tView = fDialog.findChild("treeView"); 232 | if (tView) 233 | tView->setSelectionMode(QAbstractItemView::ExtendedSelection); 234 | 235 | if (!fDialog.exec()) { 236 | return; 237 | } 238 | 239 | /* 240 | * Iterate through all selected folders 241 | */ 242 | QVector< QPair > pairs; 243 | dirs = fDialog.selectedFiles(); 244 | for (const auto& dirName : dirs) { 245 | 246 | QDir dir(dirName); 247 | QVector< QPair > ps = 248 | Util::getInnerDirNameAndFullFilePath(dir, dir.dirName()); 249 | pairs.append(ps); 250 | } 251 | 252 | selectReceiversAndSendTheFiles(pairs); 253 | } 254 | 255 | void MainWindow::onSettingsActionTriggered() 256 | { 257 | SettingsDialog dialog; 258 | dialog.exec(); 259 | } 260 | 261 | void MainWindow::onAboutActionTriggered() 262 | { 263 | AboutDialog dialog; 264 | dialog.exec(); 265 | } 266 | 267 | void MainWindow::onNewReceiverAdded(Receiver *rec) 268 | { 269 | QProgressBar* progress = new QProgressBar(); 270 | connect(rec->getTransferInfo(), &TransferInfo::progressChanged, progress, &QProgressBar::setValue); 271 | mReceiverModel->insertTransfer(rec); 272 | QModelIndex progressIdx = mReceiverModel->index(0, (int)TransferTableModel::Column::Progress); 273 | 274 | ui->receiverTableView->setIndexWidget(progressIdx, progress); 275 | ui->receiverTableView->scrollToTop(); 276 | } 277 | 278 | void MainWindow::onSenderTableSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected) 279 | { 280 | if (selected.size() > 0) { 281 | 282 | QModelIndex first = selected.indexes().first(); 283 | if (first.isValid()) { 284 | TransferInfo* ti = mSenderModel->getTransferInfo(first.row()); 285 | ui->resumeSenderBtn->setEnabled(ti->canResume()); 286 | ui->pauseSenderBtn->setEnabled(ti->canPause()); 287 | ui->cancelSenderBtn->setEnabled(ti->canCancel()); 288 | 289 | connect(ti, &TransferInfo::stateChanged, this, &MainWindow::onSelectedSenderStateChanged); 290 | } 291 | 292 | } 293 | 294 | if (deselected.size() > 0) { 295 | 296 | QModelIndex first = deselected.indexes().first(); 297 | if (first.isValid()) { 298 | TransferInfo* ti = mSenderModel->getTransferInfo(first.row()); 299 | disconnect(ti, &TransferInfo::stateChanged, this, &MainWindow::onSelectedSenderStateChanged); 300 | } 301 | 302 | } 303 | } 304 | 305 | void MainWindow::onSenderTableDoubleClicked(const QModelIndex& index) 306 | { 307 | Q_UNUSED(index); 308 | openSenderFileInCurrentIndex(); 309 | } 310 | 311 | void MainWindow::onSenderClearClicked() 312 | { 313 | mSenderModel->clearCompleted(); 314 | } 315 | 316 | void MainWindow::onSenderCancelClicked() 317 | { 318 | QModelIndex currIndex = ui->senderTableView->currentIndex(); 319 | if (currIndex.isValid()) { 320 | Transfer* sender = mSenderModel->getTransfer(currIndex.row()); 321 | sender->cancel(); 322 | } 323 | } 324 | 325 | void MainWindow::onSenderPauseClicked() 326 | { 327 | QModelIndex currIndex = ui->senderTableView->currentIndex(); 328 | if (currIndex.isValid()) { 329 | Transfer* sender = mSenderModel->getTransfer(currIndex.row()); 330 | sender->pause(); 331 | } 332 | } 333 | 334 | void MainWindow::onSenderResumeClicked() 335 | { 336 | QModelIndex currIndex = ui->senderTableView->currentIndex(); 337 | if (currIndex.isValid()) { 338 | Transfer* sender = mSenderModel->getTransfer(currIndex.row()); 339 | sender->resume(); 340 | } 341 | } 342 | 343 | 344 | void MainWindow::onReceiverTableDoubleClicked(const QModelIndex& index) 345 | { 346 | if (index.isValid()) { 347 | TransferInfo* ti = mReceiverModel->getTransferInfo(index.row()); 348 | if (ti && ti->getState() == TransferState::Finish) 349 | openReceiverFileInCurrentIndex(); 350 | } 351 | } 352 | 353 | void MainWindow::onReceiverClearClicked() 354 | { 355 | mReceiverModel->clearCompleted(); 356 | } 357 | 358 | void MainWindow::onReceiverTableSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected) 359 | { 360 | if (selected.size() > 0) { 361 | 362 | QModelIndex first = selected.indexes().first(); 363 | if (first.isValid()) { 364 | TransferInfo* ti = mReceiverModel->getTransferInfo(first.row()); 365 | ui->resumeReceiverBtn->setEnabled(ti->canResume()); 366 | ui->pauseReceiverBtn->setEnabled(ti->canPause()); 367 | ui->cancelReceiverBtn->setEnabled(ti->canCancel()); 368 | 369 | connect(ti, &TransferInfo::stateChanged, this, &MainWindow::onSelectedReceiverStateChanged); 370 | } 371 | 372 | } 373 | 374 | if (deselected.size() > 0) { 375 | 376 | QModelIndex first = deselected.indexes().first(); 377 | if (first.isValid()) { 378 | TransferInfo* ti = mReceiverModel->getTransferInfo(first.row()); 379 | disconnect(ti, &TransferInfo::stateChanged, this, &MainWindow::onSelectedReceiverStateChanged); 380 | } 381 | 382 | } 383 | } 384 | 385 | void MainWindow::onReceiverCancelClicked() 386 | { 387 | QModelIndex currIndex = ui->receiverTableView->currentIndex(); 388 | if (currIndex.isValid()) { 389 | Transfer* rec = mReceiverModel->getTransfer(currIndex.row()); 390 | rec->cancel(); 391 | } 392 | } 393 | 394 | void MainWindow::onReceiverPauseClicked() 395 | { 396 | QModelIndex currIndex = ui->receiverTableView->currentIndex(); 397 | if (currIndex.isValid()) { 398 | Transfer* rec = mReceiverModel->getTransfer(currIndex.row()); 399 | rec->pause(); 400 | } 401 | } 402 | 403 | void MainWindow::onReceiverResumeClicked() 404 | { 405 | QModelIndex currIndex = ui->receiverTableView->currentIndex(); 406 | if (currIndex.isValid()) { 407 | Transfer* rec = mReceiverModel->getTransfer(currIndex.row()); 408 | rec->resume(); 409 | } 410 | } 411 | 412 | void MainWindow::onSenderTableContextMenuRequested(const QPoint& pos) 413 | { 414 | QModelIndex currIndex = ui->senderTableView->indexAt(pos); 415 | QMenu contextMenu; 416 | 417 | if (currIndex.isValid()) { 418 | TransferInfo* ti = mSenderModel->getTransferInfo(currIndex.row()); 419 | TransferState state = ti->getState(); 420 | bool enableRemove = state == TransferState::Finish || 421 | state == TransferState::Cancelled || 422 | state == TransferState::Disconnected || 423 | state == TransferState::Idle; 424 | 425 | mSenderRemoveAction->setEnabled(enableRemove); 426 | mSenderPauseAction->setEnabled(ti->canPause()); 427 | mSenderResumeAction->setEnabled(ti->canResume()); 428 | mSenderCancelAction->setEnabled(ti->canCancel()); 429 | 430 | contextMenu.addAction(mSenderOpenAction); 431 | contextMenu.addAction(mSenderOpenFolderAction); 432 | contextMenu.addSeparator(); 433 | contextMenu.addAction(mSendFilesAction); 434 | contextMenu.addAction(mSendFolderAction); 435 | contextMenu.addSeparator(); 436 | contextMenu.addAction(mSenderRemoveAction); 437 | contextMenu.addAction(mSenderClearAction); 438 | contextMenu.addSeparator(); 439 | contextMenu.addAction(mSenderPauseAction); 440 | contextMenu.addAction(mSenderResumeAction); 441 | contextMenu.addAction(mSenderCancelAction); 442 | } 443 | else { 444 | contextMenu.addAction(mSendFilesAction); 445 | contextMenu.addAction(mSendFolderAction); 446 | contextMenu.addSeparator(); 447 | contextMenu.addAction(mSenderClearAction); 448 | } 449 | 450 | QPoint globPos = ui->senderTableView->mapToGlobal(pos); 451 | contextMenu.exec(globPos); 452 | } 453 | 454 | void MainWindow::onReceiverTableContextMenuRequested(const QPoint& pos) 455 | { 456 | QModelIndex currIndex = ui->receiverTableView->indexAt(pos); 457 | QMenu contextMenu; 458 | 459 | if (currIndex.isValid()) { 460 | TransferInfo* ti = mReceiverModel->getTransferInfo(currIndex.row()); 461 | TransferState state = ti->getState(); 462 | bool enableFileMenu = state == TransferState::Finish; 463 | bool enableRemove = state == TransferState::Finish || 464 | state == TransferState::Cancelled || 465 | state == TransferState::Disconnected || 466 | state == TransferState::Idle; 467 | 468 | mRecOpenAction->setEnabled(enableFileMenu); 469 | mRecOpenFolderAction->setEnabled(enableFileMenu); 470 | mRecRemoveAction->setEnabled(enableFileMenu | enableRemove); 471 | mRecDeleteAction->setEnabled(enableFileMenu); 472 | mRecPauseAction->setEnabled(ti->canPause()); 473 | mRecResumeAction->setEnabled(ti->canResume()); 474 | mRecCancelAction->setEnabled(ti->canCancel()); 475 | 476 | contextMenu.addAction(mRecOpenAction); 477 | contextMenu.addAction(mRecOpenFolderAction); 478 | contextMenu.addAction(mRecRemoveAction); 479 | contextMenu.addAction(mRecDeleteAction); 480 | contextMenu.addAction(mRecClearAction); 481 | contextMenu.addSeparator(); 482 | contextMenu.addAction(mRecPauseAction); 483 | contextMenu.addAction(mRecResumeAction); 484 | contextMenu.addAction(mRecCancelAction); 485 | } 486 | else { 487 | contextMenu.addAction(mRecClearAction); 488 | } 489 | 490 | QPoint globPos = ui->receiverTableView->mapToGlobal(pos); 491 | contextMenu.exec(globPos); 492 | } 493 | 494 | void MainWindow::openSenderFileInCurrentIndex() 495 | { 496 | QModelIndex currIndex = ui->senderTableView->currentIndex(); 497 | QModelIndex fileNameIndex = mSenderModel->index(currIndex.row(), (int)TransferTableModel::Column::FileName); 498 | QString fileName = mSenderModel->data(fileNameIndex).toString(); 499 | 500 | QDesktopServices::openUrl(QUrl::fromLocalFile(fileName)); 501 | } 502 | 503 | void MainWindow::openSenderFolderInCurrentIndex() 504 | { 505 | QModelIndex currIndex = ui->senderTableView->currentIndex(); 506 | QModelIndex fileNameIndex = mSenderModel->index(currIndex.row(), (int)TransferTableModel::Column::FileName); 507 | QString dir = QFileInfo(mSenderModel->data(fileNameIndex).toString()).absoluteDir().absolutePath(); 508 | 509 | QDesktopServices::openUrl(QUrl::fromLocalFile(dir)); 510 | } 511 | 512 | void MainWindow::removeSenderItemInCurrentIndex() 513 | { 514 | QModelIndex currIndex = ui->senderTableView->currentIndex(); 515 | mSenderModel->removeTransfer(currIndex.row()); 516 | } 517 | 518 | void MainWindow::openReceiverFileInCurrentIndex() 519 | { 520 | QModelIndex currIndex = ui->receiverTableView->currentIndex(); 521 | QModelIndex fileNameIndex = mReceiverModel->index(currIndex.row(), (int)TransferTableModel::Column::FileName); 522 | QString fileName = mReceiverModel->data(fileNameIndex).toString(); 523 | 524 | QDesktopServices::openUrl(QUrl::fromLocalFile(fileName)); 525 | } 526 | 527 | void MainWindow::openReceiverFolderInCurrentIndex() 528 | { 529 | QModelIndex currIndex = ui->receiverTableView->currentIndex(); 530 | QModelIndex fileNameIndex = mReceiverModel->index(currIndex.row(), (int)TransferTableModel::Column::FileName); 531 | QString dir = QFileInfo(mReceiverModel->data(fileNameIndex).toString()).absoluteDir().absolutePath(); 532 | 533 | QDesktopServices::openUrl(QUrl::fromLocalFile(dir)); 534 | } 535 | 536 | void MainWindow::removeReceiverItemInCurrentIndex() 537 | { 538 | QModelIndex currIndex = ui->receiverTableView->currentIndex(); 539 | mReceiverModel->removeTransfer(currIndex.row()); 540 | } 541 | 542 | void MainWindow::deleteReceiverFileInCurrentIndex() 543 | { 544 | QModelIndex currIndex = ui->receiverTableView->currentIndex(); 545 | QModelIndex fileNameIndex = mReceiverModel->index(currIndex.row(), (int)TransferTableModel::Column::FileName); 546 | QString fileName = mReceiverModel->data(fileNameIndex).toString(); 547 | 548 | QString str = "Are you sure wants to delete

" + fileName + "?"; 549 | QMessageBox::StandardButton ret = QMessageBox::question(this, tr("Delete"), str); 550 | if (ret == QMessageBox::Yes) { 551 | QFile::remove(fileName); 552 | mReceiverModel->removeTransfer(currIndex.row()); 553 | } 554 | } 555 | 556 | void MainWindow::onSelectedSenderStateChanged(TransferState state) 557 | { 558 | ui->resumeSenderBtn->setEnabled(state == TransferState::Paused); 559 | ui->pauseSenderBtn->setEnabled(state == TransferState::Transfering || state == TransferState::Waiting); 560 | ui->cancelSenderBtn->setEnabled(state == TransferState::Transfering || state == TransferState::Waiting || 561 | state == TransferState::Paused); 562 | } 563 | 564 | void MainWindow::onSelectedReceiverStateChanged(TransferState state) 565 | { 566 | ui->resumeReceiverBtn->setEnabled(state == TransferState::Paused); 567 | ui->pauseReceiverBtn->setEnabled(state == TransferState::Transfering || state == TransferState::Waiting); 568 | ui->cancelReceiverBtn->setEnabled(state == TransferState::Transfering || state == TransferState::Waiting || 569 | state == TransferState::Paused); 570 | } 571 | 572 | void MainWindow::quitApp() 573 | { 574 | mForceQuit = true; 575 | close(); 576 | } 577 | 578 | void MainWindow::setupToolbar() 579 | { 580 | QMenu* sendMenu = new QMenu(); 581 | sendMenu->addAction(mSendFilesAction); 582 | sendMenu->addAction(mSendFolderAction); 583 | 584 | QToolButton* sendBtn = new QToolButton(); 585 | sendBtn->setPopupMode(QToolButton::InstantPopup); 586 | sendBtn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 587 | sendBtn->setText(tr("Send")); 588 | sendBtn->setIcon(QIcon(":/img/send.png")); 589 | sendBtn->setMenu(sendMenu); 590 | ui->mainToolBar->addWidget(sendBtn); 591 | ui->mainToolBar->addSeparator(); 592 | 593 | ui->mainToolBar->addAction(mSettingsAction); 594 | 595 | QWidget* spacer = new QWidget(); 596 | spacer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); 597 | ui->mainToolBar->addWidget(spacer); 598 | 599 | QMenu* menu = new QMenu(); 600 | menu->addAction(mAboutAction); 601 | menu->addAction(mAboutQtAction); 602 | 603 | QToolButton* aboutBtn = new QToolButton(); 604 | aboutBtn->setText(tr("About")); 605 | aboutBtn->setToolTip(tr("About this program")); 606 | aboutBtn->setIcon(QIcon(":/img/about.png")); 607 | aboutBtn->setMenu(menu); 608 | aboutBtn->setPopupMode(QToolButton::InstantPopup); 609 | ui->mainToolBar->addWidget(aboutBtn); 610 | } 611 | 612 | void MainWindow::setupActions() 613 | { 614 | mShowMainWindowAction = new QAction(tr("Show Main Window"), this); 615 | connect(mShowMainWindowAction, &QAction::triggered, this, &MainWindow::onShowMainWindowTriggered); 616 | mSendFilesAction = new QAction(QIcon(":/img/file.png"), tr("Send files..."), this); 617 | connect(mSendFilesAction, &QAction::triggered, this, &MainWindow::onSendFilesActionTriggered); 618 | mSendFolderAction = new QAction(QIcon(":/img/folder.png"), tr("Send folders..."), this); 619 | connect(mSendFolderAction, &QAction::triggered, this, &MainWindow::onSendFolderActionTriggered); 620 | mSettingsAction = new QAction(QIcon(":/img/settings.png"), tr("Settings"), this); 621 | connect(mSettingsAction, &QAction::triggered, this, &MainWindow::onSettingsActionTriggered); 622 | mAboutAction = new QAction(QIcon(":/img/about.png"), tr("About"), this); 623 | mAboutAction->setMenuRole(QAction::AboutRole); 624 | connect(mAboutAction, &QAction::triggered, this, &MainWindow::onAboutActionTriggered); 625 | mAboutQtAction = new QAction(tr("About Qt"), this); 626 | mAboutQtAction->setMenuRole(QAction::AboutQtRole); 627 | connect(mAboutQtAction, &QAction::triggered, QApplication::instance(), &QApplication::aboutQt); 628 | mQuitAction = new QAction(tr("Quit"), this); 629 | connect(mQuitAction, &QAction::triggered, this, &MainWindow::quitApp); 630 | 631 | mSenderOpenAction = new QAction(tr("Open"), this); 632 | connect(mSenderOpenAction, &QAction::triggered, this, &MainWindow::openSenderFileInCurrentIndex); 633 | mSenderOpenFolderAction = new QAction(tr("Open folder"), this); 634 | connect(mSenderOpenFolderAction, &QAction::triggered, this, &MainWindow::openSenderFolderInCurrentIndex); 635 | mSenderRemoveAction = new QAction(QIcon(":/img/remove.png"), tr("Remove"), this); 636 | connect(mSenderRemoveAction, &QAction::triggered, this, &MainWindow::removeSenderItemInCurrentIndex); 637 | mSenderClearAction = new QAction(QIcon(":/img/clear.png"), tr("Clear"), this); 638 | connect(mSenderClearAction, &QAction::triggered, this, &MainWindow::onSenderClearClicked); 639 | mSenderPauseAction = new QAction(QIcon(":/img/pause.png"), tr("Pause"), this); 640 | connect(mSenderPauseAction, &QAction::triggered, this, &MainWindow::onSenderPauseClicked); 641 | mSenderResumeAction = new QAction(QIcon(":/img/resume.png"), tr("Resume"), this); 642 | connect(mSenderResumeAction, &QAction::triggered, this, &MainWindow::onSenderResumeClicked); 643 | mSenderCancelAction = new QAction(QIcon(":/img/cancel.png"), tr("Cancel"), this); 644 | connect(mSenderCancelAction, &QAction::triggered, this, &MainWindow::onSenderCancelClicked); 645 | 646 | mRecOpenAction = new QAction(tr("Open"), this); 647 | connect(mRecOpenAction, &QAction::triggered, this, &MainWindow::openReceiverFileInCurrentIndex); 648 | mRecOpenFolderAction = new QAction(tr("Open folder"), this); 649 | connect(mRecOpenFolderAction, &QAction::triggered, this, &MainWindow::openReceiverFolderInCurrentIndex); 650 | mRecRemoveAction = new QAction(QIcon(":/img/remove.png"), tr("Remove"), this); 651 | connect(mRecRemoveAction, &QAction::triggered, this, &MainWindow::removeReceiverItemInCurrentIndex); 652 | mRecDeleteAction = new QAction(tr("Delete from disk"), this); 653 | connect(mRecDeleteAction, &QAction::triggered, this, &MainWindow::deleteReceiverFileInCurrentIndex); 654 | mRecClearAction = new QAction(QIcon(":/img/clear.png"), tr("Clear"), this); 655 | connect(mRecClearAction, &QAction::triggered, this, &MainWindow::onReceiverClearClicked); 656 | mRecPauseAction = new QAction(QIcon(":/img/pause.png"), tr("Pause"), this); 657 | connect(mRecPauseAction, &QAction::triggered, this, &MainWindow::onReceiverPauseClicked); 658 | mRecResumeAction = new QAction(QIcon(":/img/resume.png"), tr("Resume"), this); 659 | connect(mRecResumeAction, &QAction::triggered, this, &MainWindow::onReceiverResumeClicked); 660 | mRecCancelAction = new QAction(QIcon(":/img/cancel.png"), tr("Cancel"), this); 661 | connect(mRecCancelAction, &QAction::triggered, this, &MainWindow::onReceiverCancelClicked); 662 | } 663 | 664 | void MainWindow::setupSystrayIcon() 665 | { 666 | if (!QSystemTrayIcon::isSystemTrayAvailable()) { 667 | mSystrayIcon = nullptr; 668 | return; 669 | } 670 | 671 | mSystrayMenu = new QMenu(this); 672 | mSystrayMenu->addAction(mShowMainWindowAction); 673 | mSystrayMenu->addSeparator(); 674 | mSystrayMenu->addAction(mSendFilesAction); 675 | mSystrayMenu->addAction(mSendFolderAction); 676 | mSystrayMenu->addSeparator(); 677 | mSystrayMenu->addAction(mAboutAction); 678 | mSystrayMenu->addAction(mAboutQtAction); 679 | mSystrayMenu->addSeparator(); 680 | mSystrayMenu->addAction(mQuitAction); 681 | 682 | mSystrayIcon = new QSystemTrayIcon(QIcon(":/img/systray-icon.png"), this); 683 | mSystrayIcon->setToolTip(PROGRAM_NAME); 684 | mSystrayIcon->setContextMenu(mSystrayMenu); 685 | mSystrayIcon->show(); 686 | } 687 | -------------------------------------------------------------------------------- /src/ui/mainwindow.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef MAINWINDOW_H 20 | #define MAINWINDOW_H 21 | 22 | #include 23 | #include 24 | 25 | #include "model/transfertablemodel.h" 26 | #include "model/devicelistmodel.h" 27 | #include "transfer/devicebroadcaster.h" 28 | #include "transfer/transferserver.h" 29 | 30 | namespace Ui { 31 | class MainWindow; 32 | } 33 | 34 | class MainWindow : public QMainWindow 35 | { 36 | Q_OBJECT 37 | 38 | public: 39 | explicit MainWindow(QWidget *parent = nullptr); 40 | ~MainWindow() override; 41 | 42 | protected: 43 | void closeEvent(QCloseEvent* event) override; 44 | 45 | public Q_SLOTS: 46 | void setMainWindowVisibility(bool visible = true); 47 | 48 | private Q_SLOTS: 49 | void onShowMainWindowTriggered(); 50 | void onSendFilesActionTriggered(); 51 | void onSendFolderActionTriggered(); 52 | void onSettingsActionTriggered(); 53 | void onAboutActionTriggered(); 54 | 55 | void onNewReceiverAdded(Receiver* rec); 56 | 57 | void onSenderTableDoubleClicked(const QModelIndex& index); 58 | void onSenderClearClicked(); 59 | void onSenderCancelClicked(); 60 | void onSenderPauseClicked(); 61 | void onSenderResumeClicked(); 62 | 63 | void onReceiverTableDoubleClicked(const QModelIndex& index); 64 | void onReceiverClearClicked(); 65 | void onReceiverCancelClicked(); 66 | void onReceiverPauseClicked(); 67 | void onReceiverResumeClicked(); 68 | 69 | void onSenderTableSelectionChanged(const QItemSelection& selected, 70 | const QItemSelection& deselected); 71 | void onReceiverTableSelectionChanged(const QItemSelection& selected, 72 | const QItemSelection& deselected); 73 | 74 | void onSenderTableContextMenuRequested(const QPoint& pos); 75 | void onReceiverTableContextMenuRequested(const QPoint& pos); 76 | 77 | void openSenderFileInCurrentIndex(); 78 | void openSenderFolderInCurrentIndex(); 79 | void removeSenderItemInCurrentIndex(); 80 | 81 | void openReceiverFileInCurrentIndex(); 82 | void openReceiverFolderInCurrentIndex(); 83 | void removeReceiverItemInCurrentIndex(); 84 | void deleteReceiverFileInCurrentIndex(); 85 | 86 | void onSelectedSenderStateChanged(TransferState state); 87 | void onSelectedReceiverStateChanged(TransferState state); 88 | 89 | void quitApp(); 90 | 91 | private: 92 | void setupActions(); 93 | void setupToolbar(); 94 | void setupSystrayIcon(); 95 | void connectSignals(); 96 | void sendFile(const QString& folderName, const QString& fileName, const Device& receiver); 97 | void selectReceiversAndSendTheFiles(QVector > dirNameAndFullPath); 98 | 99 | bool anyActiveSender(); 100 | bool anyActiveReceiver(); 101 | 102 | bool mForceQuit{false}; 103 | Ui::MainWindow *ui; 104 | QSystemTrayIcon* mSystrayIcon; 105 | QMenu* mSystrayMenu; 106 | 107 | TransferTableModel* mSenderModel; 108 | TransferTableModel* mReceiverModel; 109 | DeviceListModel* mDeviceModel; 110 | 111 | DeviceBroadcaster* mBroadcaster; 112 | TransferServer* mTransServer; 113 | 114 | QAction* mShowMainWindowAction; 115 | QAction* mSendFilesAction; 116 | QAction* mSendFolderAction; 117 | QAction* mSettingsAction; 118 | QAction* mAboutAction; 119 | QAction* mAboutQtAction; 120 | QAction* mQuitAction; 121 | 122 | QAction* mSenderOpenAction; 123 | QAction* mSenderOpenFolderAction; 124 | QAction* mSenderRemoveAction; 125 | QAction* mSenderClearAction; 126 | QAction* mSenderPauseAction; 127 | QAction* mSenderResumeAction; 128 | QAction* mSenderCancelAction; 129 | 130 | QAction* mRecOpenAction; 131 | QAction* mRecOpenFolderAction; 132 | QAction* mRecRemoveAction; 133 | QAction* mRecDeleteAction; 134 | QAction* mRecClearAction; 135 | QAction* mRecPauseAction; 136 | QAction* mRecResumeAction; 137 | QAction* mRecCancelAction; 138 | }; 139 | 140 | #endif // MAINWINDOW_H 141 | -------------------------------------------------------------------------------- /src/ui/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 920 10 | 500 11 | 12 | 13 | 14 | Locally 15 | 16 | 17 | 18 | :/img/icon.png:/img/icon.png 19 | 20 | 21 | 22 | 23 | 24 | 25 | 2 26 | 27 | 28 | Qt::Vertical 29 | 30 | 31 | true 32 | 33 | 34 | false 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | :/img/up.png 47 | 48 | 49 | false 50 | 51 | 52 | 53 | 54 | 55 | 56 | Uploads 57 | 58 | 59 | 60 | 61 | 62 | 63 | Qt::Horizontal 64 | 65 | 66 | 67 | 40 68 | 20 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | false 77 | 78 | 79 | Resume 80 | 81 | 82 | 83 | 84 | 85 | 86 | :/img/resume.png:/img/resume.png 87 | 88 | 89 | 90 | 18 91 | 18 92 | 93 | 94 | 95 | true 96 | 97 | 98 | 99 | 100 | 101 | 102 | false 103 | 104 | 105 | Pause 106 | 107 | 108 | 109 | 110 | 111 | 112 | :/img/pause.png:/img/pause.png 113 | 114 | 115 | 116 | 18 117 | 18 118 | 119 | 120 | 121 | true 122 | 123 | 124 | 125 | 126 | 127 | 128 | false 129 | 130 | 131 | Cancel selected item 132 | 133 | 134 | Cancel 135 | 136 | 137 | 138 | :/img/cancel.png:/img/cancel.png 139 | 140 | 141 | 142 | 18 143 | 18 144 | 145 | 146 | 147 | true 148 | 149 | 150 | 151 | 152 | 153 | 154 | Clear completed items 155 | 156 | 157 | 158 | 159 | 160 | 161 | :/img/clear.png:/img/clear.png 162 | 163 | 164 | 165 | 18 166 | 18 167 | 168 | 169 | 170 | true 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | Qt::CustomContextMenu 180 | 181 | 182 | QAbstractItemView::SingleSelection 183 | 184 | 185 | QAbstractItemView::SelectRows 186 | 187 | 188 | QAbstractItemView::ScrollPerPixel 189 | 190 | 191 | QAbstractItemView::ScrollPerPixel 192 | 193 | 194 | false 195 | 196 | 197 | true 198 | 199 | 200 | false 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | :/img/down.png 217 | 218 | 219 | 220 | 221 | 222 | 223 | Downloads 224 | 225 | 226 | 227 | 228 | 229 | 230 | Qt::Horizontal 231 | 232 | 233 | 234 | 40 235 | 20 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | false 244 | 245 | 246 | Resume 247 | 248 | 249 | 250 | 251 | 252 | 253 | :/img/resume.png:/img/resume.png 254 | 255 | 256 | 257 | 18 258 | 18 259 | 260 | 261 | 262 | true 263 | 264 | 265 | 266 | 267 | 268 | 269 | false 270 | 271 | 272 | Pause 273 | 274 | 275 | 276 | 277 | 278 | 279 | :/img/pause.png:/img/pause.png 280 | 281 | 282 | 283 | 18 284 | 18 285 | 286 | 287 | 288 | true 289 | 290 | 291 | 292 | 293 | 294 | 295 | false 296 | 297 | 298 | Cancel selected item 299 | 300 | 301 | Cancel 302 | 303 | 304 | 305 | :/img/cancel.png:/img/cancel.png 306 | 307 | 308 | 309 | 18 310 | 18 311 | 312 | 313 | 314 | true 315 | 316 | 317 | 318 | 319 | 320 | 321 | Clear completed items 322 | 323 | 324 | 325 | 326 | 327 | 328 | :/img/clear.png:/img/clear.png 329 | 330 | 331 | 332 | 18 333 | 18 334 | 335 | 336 | 337 | true 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | Qt::CustomContextMenu 347 | 348 | 349 | QAbstractItemView::SingleSelection 350 | 351 | 352 | QAbstractItemView::SelectRows 353 | 354 | 355 | QAbstractItemView::ScrollPerPixel 356 | 357 | 358 | QAbstractItemView::ScrollPerPixel 359 | 360 | 361 | false 362 | 363 | 364 | true 365 | 366 | 367 | false 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | false 380 | 381 | 382 | Qt::LeftToolBarArea 383 | 384 | 385 | 386 | 58 387 | 38 388 | 389 | 390 | 391 | Qt::ToolButtonTextUnderIcon 392 | 393 | 394 | false 395 | 396 | 397 | LeftToolBarArea 398 | 399 | 400 | false 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | senderTableView 411 | doubleClicked(QModelIndex) 412 | MainWindow 413 | onSenderTableDoubleClicked(QModelIndex) 414 | 415 | 416 | 157 417 | 91 418 | 419 | 420 | 79 421 | 39 422 | 423 | 424 | 425 | 426 | receiverTableView 427 | doubleClicked(QModelIndex) 428 | MainWindow 429 | onReceiverTableDoubleClicked(QModelIndex) 430 | 431 | 432 | 290 433 | 335 434 | 435 | 436 | 82 437 | 265 438 | 439 | 440 | 441 | 442 | pushButton_2 443 | clicked() 444 | MainWindow 445 | onSenderClearClicked() 446 | 447 | 448 | 908 449 | 31 450 | 451 | 452 | 709 453 | 3 454 | 455 | 456 | 457 | 458 | pushButton 459 | clicked() 460 | MainWindow 461 | onReceiverClearClicked() 462 | 463 | 464 | 908 465 | 277 466 | 467 | 468 | 512 469 | 1 470 | 471 | 472 | 473 | 474 | cancelReceiverBtn 475 | clicked() 476 | MainWindow 477 | onReceiverCancelClicked() 478 | 479 | 480 | 818 481 | 266 482 | 483 | 484 | 952 485 | 317 486 | 487 | 488 | 489 | 490 | pauseReceiverBtn 491 | clicked() 492 | MainWindow 493 | onReceiverPauseClicked() 494 | 495 | 496 | 777 497 | 265 498 | 499 | 500 | 930 501 | 284 502 | 503 | 504 | 505 | 506 | resumeReceiverBtn 507 | clicked() 508 | MainWindow 509 | onReceiverResumeClicked() 510 | 511 | 512 | 734 513 | 266 514 | 515 | 516 | 925 517 | 364 518 | 519 | 520 | 521 | 522 | senderTableView 523 | customContextMenuRequested(QPoint) 524 | MainWindow 525 | onSenderTableContextMenuRequested(QPoint) 526 | 527 | 528 | 301 529 | 127 530 | 531 | 532 | -27 533 | 96 534 | 535 | 536 | 537 | 538 | receiverTableView 539 | customContextMenuRequested(QPoint) 540 | MainWindow 541 | onReceiverTableContextMenuRequested(QPoint) 542 | 543 | 544 | 211 545 | 359 546 | 547 | 548 | -35 549 | 333 550 | 551 | 552 | 553 | 554 | cancelSenderBtn 555 | clicked() 556 | MainWindow 557 | onSenderCancelClicked() 558 | 559 | 560 | 815 561 | 22 562 | 563 | 564 | 551 565 | 8 566 | 567 | 568 | 569 | 570 | pauseSenderBtn 571 | clicked() 572 | MainWindow 573 | onSenderPauseClicked() 574 | 575 | 576 | 772 577 | 27 578 | 579 | 580 | 1043 581 | 47 582 | 583 | 584 | 585 | 586 | resumeSenderBtn 587 | clicked() 588 | MainWindow 589 | onSenderResumeClicked() 590 | 591 | 592 | 733 593 | 21 594 | 595 | 596 | 932 597 | 99 598 | 599 | 600 | 601 | 602 | 603 | onSendActionTriggered() 604 | onSettingsActionTriggered() 605 | onAboutActionTriggered() 606 | onSenderTableDoubleClicked(QModelIndex) 607 | onReceiverTableDoubleClicked(QModelIndex) 608 | onSenderClearClicked() 609 | onReceiverClearClicked() 610 | onSenderCancelClicked() 611 | onSenderPauseClicked() 612 | onSenderResumeClicked() 613 | onReceiverCancelClicked() 614 | onReceiverPauseClicked() 615 | onReceiverResumeClicked() 616 | onSenderTableContextMenuRequested(QPoint) 617 | onReceiverTableContextMenuRequested(QPoint) 618 | onSendFolderActionTriggered() 619 | 620 | 621 | -------------------------------------------------------------------------------- /src/ui/receiverselectordialog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | #include "receiverselectordialog.h" 22 | #include "ui_receiverselectordialog.h" 23 | 24 | #include "model/devicelistmodel.h" 25 | #include "model/device.h" 26 | 27 | ReceiverSelectorDialog::ReceiverSelectorDialog(DeviceListModel* model, QWidget *parent) : 28 | QDialog(parent), 29 | ui(new Ui::ReceiverSelectorDialog), 30 | mModel(model) 31 | { 32 | ui->setupUi(this); 33 | 34 | ui->listView->setModel(mModel); 35 | ui->listView->setCurrentIndex(QModelIndex()); 36 | 37 | model->refresh(); 38 | } 39 | 40 | ReceiverSelectorDialog::~ReceiverSelectorDialog() 41 | { 42 | delete ui; 43 | } 44 | 45 | Device ReceiverSelectorDialog::getSelectedDevice() const 46 | { 47 | QModelIndex currIndex = ui->listView->currentIndex(); 48 | if (currIndex.isValid()) { 49 | return mModel->device(currIndex.row()); 50 | } 51 | 52 | return Device(); 53 | } 54 | 55 | QVector ReceiverSelectorDialog::getSelectedDevices() const 56 | { 57 | QVector devices; 58 | QItemSelectionModel* selModel = ui->listView->selectionModel(); 59 | if (selModel) { 60 | 61 | QModelIndexList selected = selModel->selectedIndexes(); 62 | for (auto selectedIndex : selected) { 63 | if (selectedIndex.isValid()) { 64 | devices.push_back(mModel->device(selectedIndex.row())); 65 | } 66 | } 67 | } 68 | 69 | return devices; 70 | } 71 | 72 | void ReceiverSelectorDialog::onSendClicked() 73 | { 74 | QModelIndex currIndex = ui->listView->currentIndex(); 75 | if (currIndex.isValid()) 76 | accept(); 77 | else 78 | QMessageBox::information(this, tr("Info"), tr("Please select receivers.")); 79 | } 80 | 81 | void ReceiverSelectorDialog::onRefreshClicked() 82 | { 83 | mModel->refresh(); 84 | } 85 | -------------------------------------------------------------------------------- /src/ui/receiverselectordialog.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef RECEIVERSELECTORDIALOG_H 20 | #define RECEIVERSELECTORDIALOG_H 21 | 22 | #include 23 | 24 | class DeviceListModel; 25 | class Device; 26 | 27 | namespace Ui { 28 | class ReceiverSelectorDialog; 29 | } 30 | 31 | class ReceiverSelectorDialog : public QDialog 32 | { 33 | Q_OBJECT 34 | 35 | public: 36 | explicit ReceiverSelectorDialog(DeviceListModel* model, QWidget *parent = nullptr); 37 | ~ReceiverSelectorDialog() override; 38 | 39 | Device getSelectedDevice() const; 40 | QVector getSelectedDevices() const; 41 | 42 | private Q_SLOTS: 43 | void onSendClicked(); 44 | void onRefreshClicked(); 45 | 46 | private: 47 | Ui::ReceiverSelectorDialog *ui; 48 | 49 | DeviceListModel* mModel; 50 | }; 51 | 52 | #endif // RECEIVERSELECTORDIALOG_H 53 | -------------------------------------------------------------------------------- /src/ui/receiverselectordialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ReceiverSelectorDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 380 10 | 300 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | 21 | 380 22 | 300 23 | 24 | 25 | 26 | 27 | 380 28 | 300 29 | 30 | 31 | 32 | Select Receiver 33 | 34 | 35 | 36 | :/img/icon.png:/img/icon.png 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Select receiver 45 | 46 | 47 | 48 | 49 | 50 | 51 | Qt::Horizontal 52 | 53 | 54 | 55 | 40 56 | 20 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Refresh list 65 | 66 | 67 | 68 | 69 | 70 | 71 | :/img/refresh.png:/img/refresh.png 72 | 73 | 74 | 75 | 18 76 | 18 77 | 78 | 79 | 80 | true 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | You can select multiple receivers 90 | 91 | 92 | QAbstractItemView::ExtendedSelection 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | true 101 | 102 | 103 | 104 | Note: it is possible to select multiple receivers for multicast using Ctrl+MouseClick or Ctrl+A 105 | 106 | 107 | true 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | Qt::Horizontal 117 | 118 | 119 | 120 | 40 121 | 20 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | Cancel 130 | 131 | 132 | 133 | 134 | 135 | 136 | Send 137 | 138 | 139 | true 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | pushButton_2 153 | clicked() 154 | ReceiverSelectorDialog 155 | reject() 156 | 157 | 158 | 193 159 | 289 160 | 161 | 162 | 92 163 | 236 164 | 165 | 166 | 167 | 168 | pushButton 169 | clicked() 170 | ReceiverSelectorDialog 171 | onSendClicked() 172 | 173 | 174 | 279 175 | 289 176 | 177 | 178 | 312 179 | 244 180 | 181 | 182 | 183 | 184 | pushButton_3 185 | clicked() 186 | ReceiverSelectorDialog 187 | onRefreshClicked() 188 | 189 | 190 | 268 191 | 21 192 | 193 | 194 | 219 195 | 14 196 | 197 | 198 | 199 | 200 | 201 | onSendClicked() 202 | onRefreshClicked() 203 | 204 | 205 | -------------------------------------------------------------------------------- /src/ui/settingsdialog.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | #include "settingsdialog.h" 22 | #include "ui_settingsdialog.h" 23 | 24 | #include "settings.h" 25 | 26 | SettingsDialog::SettingsDialog(QWidget *parent) : 27 | QDialog(parent), 28 | ui(new Ui::SettingsDialog) 29 | { 30 | ui->setupUi(this); 31 | assign(); 32 | } 33 | 34 | SettingsDialog::~SettingsDialog() 35 | { 36 | delete ui; 37 | } 38 | 39 | void SettingsDialog::onCancelClicked() 40 | { 41 | reject(); 42 | } 43 | 44 | void SettingsDialog::onSaveClicked() 45 | { 46 | Settings* set = Settings::instance(); 47 | 48 | QString name = ui->deviceNameLineEdit->text(); 49 | if (!name.isEmpty()) 50 | set->setDeviceName(name); 51 | 52 | set->setBroadcastPort(ui->bcPortSpinBox->value()); 53 | set->setTransferPort(ui->transferPortSpinBox->value()); 54 | set->setFileBufferSize(ui->buffSizeSpinBox->value() * 1024); 55 | set->setDeviceName(ui->deviceNameLineEdit->text()); 56 | set->setDownloadDir(ui->downDirlineEdit->text()); 57 | set->setBroadcastInterval(ui->bcIntervalSpinBox->value()); 58 | set->setReplaceExistingFile(ui->overwriteCheckBox->isChecked()); 59 | 60 | set->saveSettings(); 61 | 62 | accept(); 63 | } 64 | 65 | void SettingsDialog::onResetClicked() 66 | { 67 | Settings::instance()->reset(); 68 | assign(); 69 | } 70 | 71 | void SettingsDialog::onSelectDownDirClicked() 72 | { 73 | QString dirName = Settings::instance()->getDownloadDir(); 74 | QString newDirName = QFileDialog::getExistingDirectory(this, tr("Select a directory"), dirName); 75 | 76 | if (!newDirName.isEmpty()) 77 | ui->downDirlineEdit->setText(newDirName); 78 | } 79 | 80 | void SettingsDialog::assign() 81 | { 82 | Settings* sets = Settings::instance(); 83 | Device me = sets->getMyDevice(); 84 | 85 | ui->deviceIdLabel->setText(me.getId()); 86 | ui->ipAddrLabel->setText(me.getAddress().toString()); 87 | ui->osNameLabel->setText(me.getOSName()); 88 | ui->deviceNameLineEdit->setText(me.getName()); 89 | ui->downDirlineEdit->setText(sets->getDownloadDir()); 90 | 91 | ui->bcPortSpinBox->setValue(sets->getBroadcastPort()); 92 | ui->transferPortSpinBox->setValue(sets->getTransferPort()); 93 | ui->buffSizeSpinBox->setValue(sets->getFileBufferSize() / 1024); 94 | ui->bcIntervalSpinBox->setValue(sets->getBroadcastInterval()); 95 | ui->overwriteCheckBox->setChecked(sets->getReplaceExistingFile()); 96 | } 97 | -------------------------------------------------------------------------------- /src/ui/settingsdialog.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef SETTINGSDIALOG_H 20 | #define SETTINGSDIALOG_H 21 | 22 | #include 23 | 24 | namespace Ui { 25 | class SettingsDialog; 26 | } 27 | 28 | class SettingsDialog : public QDialog 29 | { 30 | Q_OBJECT 31 | 32 | public: 33 | explicit SettingsDialog(QWidget *parent = nullptr); 34 | ~SettingsDialog() override; 35 | 36 | private Q_SLOTS: 37 | void onCancelClicked(); 38 | void onSaveClicked(); 39 | void onResetClicked(); 40 | void onSelectDownDirClicked(); 41 | 42 | private: 43 | void assign(); 44 | 45 | Ui::SettingsDialog *ui; 46 | }; 47 | 48 | #endif // SETTINGSDIALOG_H 49 | -------------------------------------------------------------------------------- /src/ui/settingsdialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | SettingsDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 450 10 | 470 11 | 12 | 13 | 14 | 15 | 450 16 | 470 17 | 18 | 19 | 20 | 21 | 450 22 | 470 23 | 24 | 25 | 26 | Settings 27 | 28 | 29 | 30 | :/img/settings.png:/img/settings.png 31 | 32 | 33 | 34 | 35 | 36 | 0 37 | 38 | 39 | 40 | General 41 | 42 | 43 | 44 | 45 | 46 | Profile 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | Id: 55 | 56 | 57 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 0 66 | 22 67 | 68 | 69 | 70 | 71 | 72 | 73 | - 74 | 75 | 76 | true 77 | 78 | 79 | 80 | 81 | 82 | 83 | Ip Address: 84 | 85 | 86 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 0 95 | 22 96 | 97 | 98 | 99 | 100 | 101 | 102 | - 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 230 113 | 0 114 | 115 | 116 | 117 | 118 | 119 | 120 | 30 121 | 122 | 123 | 124 | 125 | 126 | 127 | Qt::Horizontal 128 | 129 | 130 | 131 | 40 132 | 20 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 0 144 | 0 145 | 146 | 147 | 148 | 149 | 0 150 | 22 151 | 152 | 153 | 154 | - 155 | 156 | 157 | 158 | 159 | 160 | 161 | OS Name: 162 | 163 | 164 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 165 | 166 | 167 | 168 | 169 | 170 | 171 | Name: 172 | 173 | 174 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | Directory 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | Download Dir: 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 0 206 | 0 207 | 208 | 209 | 210 | 211 | 28 212 | 0 213 | 214 | 215 | 216 | 217 | 28 218 | 16777215 219 | 220 | 221 | 222 | ... 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | true 235 | 236 | 237 | Behavior 238 | 239 | 240 | 241 | 242 | 243 | true 244 | 245 | 246 | Overwrite existing file 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | false 256 | 257 | 258 | Max. Current Transfers: 259 | 260 | 261 | 262 | 263 | 264 | 265 | false 266 | 267 | 268 | 1 269 | 270 | 271 | 100 272 | 273 | 274 | 275 | 276 | 277 | 278 | Qt::Horizontal 279 | 280 | 281 | 282 | 40 283 | 20 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | Qt::Vertical 297 | 298 | 299 | 300 | 20 301 | 47 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | Network 311 | 312 | 313 | 314 | 315 | 316 | Broadcast 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | Broadcast Port: 327 | 328 | 329 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 330 | 331 | 332 | 333 | 334 | 335 | 336 | 65535 337 | 338 | 339 | 340 | 341 | 342 | 343 | Broadcast Interval: 344 | 345 | 346 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 347 | 348 | 349 | 350 | 351 | 352 | 353 | ms 354 | 355 | 356 | 1000 357 | 358 | 359 | 20000 360 | 361 | 362 | 50 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | Qt::Horizontal 372 | 373 | 374 | 375 | 40 376 | 20 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | Transfer 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | Transfer Port: 399 | 400 | 401 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 402 | 403 | 404 | 405 | 406 | 407 | 408 | 65535 409 | 410 | 411 | 412 | 413 | 414 | 415 | Qt::Horizontal 416 | 417 | 418 | 419 | 40 420 | 20 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | Buffer Size: 433 | 434 | 435 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 436 | 437 | 438 | 439 | 440 | 441 | 442 | KB 443 | 444 | 445 | 446 | 447 | 448 | 8 449 | 450 | 451 | 1024 452 | 453 | 454 | 455 | 456 | 457 | 458 | Qt::Horizontal 459 | 460 | 461 | 462 | 40 463 | 20 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | Qt::Vertical 477 | 478 | 479 | 480 | 20 481 | 167 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | Reset 496 | 497 | 498 | 499 | 500 | 501 | 502 | Qt::Horizontal 503 | 504 | 505 | 506 | 40 507 | 20 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | Cancel 516 | 517 | 518 | 519 | 520 | 521 | 522 | Save 523 | 524 | 525 | true 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | pushButton_2 539 | clicked() 540 | SettingsDialog 541 | onCancelClicked() 542 | 543 | 544 | 303 545 | 359 546 | 547 | 548 | 79 549 | 301 550 | 551 | 552 | 553 | 554 | pushButton 555 | clicked() 556 | SettingsDialog 557 | onSaveClicked() 558 | 559 | 560 | 389 561 | 359 562 | 563 | 564 | 323 565 | 300 566 | 567 | 568 | 569 | 570 | pushButton_3 571 | clicked() 572 | SettingsDialog 573 | onResetClicked() 574 | 575 | 576 | 71 577 | 359 578 | 579 | 580 | 76 581 | 274 582 | 583 | 584 | 585 | 586 | selectDirBtn 587 | clicked() 588 | SettingsDialog 589 | onSelectDownDirClicked() 590 | 591 | 592 | 366 593 | 134 594 | 595 | 596 | 393 597 | 169 598 | 599 | 600 | 601 | 602 | 603 | onCancelClicked() 604 | onSaveClicked() 605 | onResetClicked() 606 | onSelectDownDirClicked() 607 | 608 | 609 | -------------------------------------------------------------------------------- /src/util.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | #include "util.h" 22 | #include "settings.h" 23 | 24 | QString Util::sizeToString(qint64 size) 25 | { 26 | int count = 0; 27 | double f_size = size; 28 | while (f_size >= 1024) { 29 | f_size /= 1024; 30 | count++; 31 | } 32 | 33 | QString suffix; 34 | switch (count) { 35 | case 0 : suffix = " B"; break; 36 | case 1 : suffix = " KB"; break; 37 | case 2 : suffix = " MB"; break; 38 | case 3 : suffix = " GB"; break; 39 | case 4 : suffix = " TB"; break; 40 | } 41 | 42 | return QString::number(f_size, 'f', 2).append(suffix); 43 | } 44 | 45 | QVector< QPair > 46 | Util::getInnerDirNameAndFullFilePath(const QDir& startingDir, const QString& innerDirName) 47 | { 48 | QVector< QPair > pairs; 49 | 50 | QFileInfoList fiList = startingDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Files); 51 | for (const auto& fi : fiList) 52 | pairs.push_back( QPair(innerDirName, fi.filePath()) ); 53 | 54 | fiList = startingDir.entryInfoList(QDir::NoDotAndDotDot | QDir::Dirs); 55 | for (const auto& fi : fiList) { 56 | QString newInnerDirName; 57 | if (innerDirName.isEmpty()) 58 | newInnerDirName = fi.fileName(); 59 | else 60 | newInnerDirName = innerDirName + QDir::separator() + fi.fileName(); 61 | 62 | QVector< QPair > otherPairs = 63 | getInnerDirNameAndFullFilePath( QDir(fi.filePath()), newInnerDirName ); 64 | 65 | pairs.append(otherPairs); 66 | } 67 | 68 | return pairs; 69 | } 70 | 71 | QString Util::parseAppVersion(bool onlyVerNum) 72 | { 73 | if (onlyVerNum) { 74 | return QString::number(PROGRAM_X_VER) + "." + 75 | QString::number(PROGRAM_Y_VER) + "." + 76 | QString::number(PROGRAM_Z_VER); 77 | } 78 | 79 | return "v " + QString::number(PROGRAM_X_VER) + "." + 80 | QString::number(PROGRAM_Y_VER) + "." + 81 | QString::number(PROGRAM_Z_VER) + 82 | " (" + QString(OS_NAME) + ")"; 83 | } 84 | 85 | /* 86 | * cek file path (folderName+fileName). 87 | * jika file dengan nama "fileName" sudah ada 88 | * maka cek lagi untuk "fileName (1)" jika masih ada chek lagi untuk "fileName (2)" dst. 89 | * kemudian return file path untuk nama file yang belum ada. 90 | */ 91 | QString Util::getUniqueFileName(const QString& fileName, const QString& folderPath) 92 | { 93 | int count = 1; 94 | QString originalFilePath = folderPath + QDir::separator() + fileName; 95 | QString fPath = originalFilePath; 96 | while (QFile::exists(fPath)) { 97 | QFileInfo fInfo(originalFilePath); 98 | QString baseName = fInfo.baseName() + " (" + QString::number(count) + ")"; 99 | fPath = folderPath + QDir::separator() + baseName + "." + fInfo.completeSuffix(); 100 | count++; 101 | } 102 | 103 | return fPath; 104 | } 105 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | LANShare - LAN file transfer. 3 | Copyright (C) 2016 Abdul Aris R. 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef UTIL_H 20 | #define UTIL_H 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | class Util 28 | { 29 | public: 30 | static QString sizeToString(qint64 size); 31 | 32 | /* 33 | * relative dir name 34 | * | +------> full path to file inside relative dir name 35 | * | | 36 | * QPair 37 | */ 38 | static QVector< QPair > 39 | getInnerDirNameAndFullFilePath(const QDir& startingDir, const QString& innerDirName); 40 | 41 | static QString parseAppVersion(bool onlyVerNum = true); 42 | 43 | static QString getUniqueFileName(const QString& fileName, const QString& folderPath); 44 | }; 45 | 46 | #endif // UTIL_H 47 | --------------------------------------------------------------------------------