Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:AndnoVember:LXQT
nm-tray
_service:obs_scm:nm-tray-0.3.0.19~git.29290df.o...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:nm-tray-0.3.0.19~git.29290df.obscpio of Package nm-tray
070701174038B5000081A40000000200000002000000015A3D9FC900000A5F000000FD0000001000000000000000000000002C00000000nm-tray-0.3.0.19~git.29290df/CMakeLists.txtproject(nm-tray) cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) set(NM_TRAY_VERSION "0.3.0") set(QT_MIN_VERSION "5.4.0") set(CMAKE_AUTOMOC on) set(CMAKE_AUTOUIC on) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Widgets Gui Network DBus LinguistTools ) find_package(KF5NetworkManagerQt "5.24.0" REQUIRED) include(GNUInstallDirs) set(TRANSLATION_DIR "${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT_NAME}") add_definitions(-DQT_NO_SIGNALS_SLOTS_KEYWORDS "-DTRANSLATION_DIR=\"${TRANSLATION_DIR}\"" "-DNM_TRAY_VERSION=\"${NM_TRAY_VERSION}\"") if (NOT NM_TRAY_XDG_AUTOSTART_DIR) #Note: we need the default to be /etc... (not the ${CMAKE_INSTALL_PREFIX}/etc) set(NM_TRAY_XDG_AUTOSTART_DIR "/${CMAKE_INSTALL_SYSCONFDIR}/xdg/autostart") endif () message(STATUS "Translations destination dir: ${TRANSLATION_DIR}") message(STATUS "Autostart .desktop entry destination dir: ${NM_TRAY_XDG_AUTOSTART_DIR}\n (can be overriden by setting the NM_TRAY_XDG_AUTOSTART_DIR cmake variable)") set(SRCS src/log.cpp src/icons.cpp src/nmmodel.cpp src/nmproxy.cpp src/connectioninfo.cpp src/nmlist.cpp src/menuview.cpp src/windowmenu.cpp src/tray.cpp src/translate.cpp src/main.cpp ) file(GLOB TSS "translations/${PROJECT_NAME}_*.ts") if (UPDATE_TRANSLATIONS) message(WARNING "!! Disable updating translation after make (-DUPDATE_TRANSLATIONS=no) to avoid 'make clean' delete them !!") qt5_create_translation(QMS "translations/${PROJECT_NAME}.ts" ${TSS} "src") else () qt5_add_translation(QMS ${TSS}) endif() qt5_add_dbus_interface(SRCS dbus/org.freedesktop.Notifications.xml dbus/org.freedesktop.Notifications ) add_executable(nm-tray ${SRCS} ${QMS} ) set_property(TARGET nm-tray PROPERTY CXX_STANDARD 11) set_property(TARGET nm-tray PROPERTY CXX_STANDARD_REQUIRED on) target_link_libraries(nm-tray Qt5::Widgets Qt5::Gui KF5::NetworkManagerQt ) if (WITH_MODEMMANAGER_SUPPORT) target_link_libraries(nm-tray KF5::ModemManagerQt) endif() install(TARGETS nm-tray RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}" COMPONENT runtime) install(FILES ${QMS} DESTINATION "${TRANSLATION_DIR}" COMPONENT translations) install(FILES "resources/nm-tray.desktop" DESTINATION "${CMAKE_INSTALL_FULL_DATAROOTDIR}/applications" COMPONENT data) install(FILES "resources/nm-tray-autostart.desktop" DESTINATION "${NM_TRAY_XDG_AUTOSTART_DIR}" COMPONENT data) install(FILES "resources/nm-tray.conf" DESTINATION "${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT_NAME}" COMPONENT data) 070701174038B6000081A40000000200000002000000015A3D9FC9000046AC000000FD0000001000000000000000000000002500000000nm-tray-0.3.0.19~git.29290df/COPYING GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> Copyright (C) <year> <name of author> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. <signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. 070701174038B7000081A40000000200000002000000015A3D9FC900000509000000FD0000001000000000000000000000002700000000nm-tray-0.3.0.19~git.29290df/README.md# nm-tray **nm-tray** is a simple [NetworkManager](https://wiki.gnome.org/Projects/NetworkManager) front end with information icon residing in system tray (like e.g. nm-applet). It's a pure Qt application. For interaction with *NetworkManager* it uses API provided by [**KF5::NetworkManagerQt**](https://projects.kde.org/projects/frameworks/networkmanager-qt) -> plain DBus communication. ## License This software is licensed under [GNU GPLv2 or later](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html) ## Build example git clone https://github.com/palinek/nm-tray.git cd nm-tray mkdir build cd build cmake .. make ./nm-tray ## Packages For [arch users](https://www.archlinux.org/) there is an AUR packge [nm-tray-git](https://aur.archlinux.org/packages/nm-tray-git/) (thanks to [pmattern](https://github.com/pmattern)). For [openSUSE users](https://www.opensuse.org/) there is a [package](https://build.opensuse.org/package/show/X11:LXQt:git/nm-tray) in the [X11:LXQt:git](https://build.opensuse.org/project/show/X11:LXQt:git) devel project of OBS. ## Translations Thanks to [Weblate](https://weblate.org/) anyone can help us to localize nm-tray by using the [hosted weblate service](https://hosted.weblate.org/projects/nm-tray/translations/). 070701178A0EC3000041ED0000000200000002000000025A3D9FC900000000000000FD0000001000000000000000000000002200000000nm-tray-0.3.0.19~git.29290df/dbus070701178A0EC4000081A40000000200000002000000015A3D9FC9000005E8000000FD0000001000000000000000000000004400000000nm-tray-0.3.0.19~git.29290df/dbus/org.freedesktop.Notifications.xml<?xml version="1.0"?> <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> <node> <interface name="org.freedesktop.Notifications"> <method name="GetServerInformation"> <arg direction="out" type="s" name="name"/> <arg direction="out" type="s" name="vendor"/> <arg direction="out" type="s" name="version"/> <arg direction="out" type="s" name="spec_version"/> </method> <method name="CloseNotification"> <arg direction="in" type="u" name="id"/> </method> <method name="Notify"> <annotation value="QVariantMap" name="org.qtproject.QtDBus.QtTypeName.In6"/> <arg direction="in" type="s" name="app_name"/> <arg direction="in" type="u" name="replaces_id"/> <arg direction="in" type="s" name="app_icon"/> <arg direction="in" type="s" name="summary"/> <arg direction="in" type="s" name="body"/> <arg direction="in" type="as" name="actions"/> <arg direction="in" type="a{sv}" name="hints"/> <arg direction="in" type="i" name="expire_timeout"/> <arg direction="out" type="u" name="id"/> </method> <method name="GetCapabilities"> <arg direction="out" type="as" name="capabilities"/> </method> <signal name="ActionInvoked"> <arg type="u"/> <arg type="s"/> </signal> <signal name="NotificationClosed"> <arg type="u"/> <arg type="u"/> </signal> </interface> </node> 070701178C0FD5000041ED0000000200000002000000025A3D9FC900000000000000FD0000001000000000000000000000002700000000nm-tray-0.3.0.19~git.29290df/resources070701178C0FD6000081A40000000200000002000000015A3D9FC900000076000000FD0000001000000000000000000000004100000000nm-tray-0.3.0.19~git.29290df/resources/nm-tray-autostart.desktop[Desktop Entry] Type=Application Name=nm-tray TryExec=nm-tray Exec=nm-tray NotShowIn=KDE;GNOME; X-LXQt-Need-Tray=true 070701178C0FD7000081A40000000200000002000000015A3D9FC90000004B000000FD0000001000000000000000000000003400000000nm-tray-0.3.0.19~git.29290df/resources/nm-tray.conf[General] connectionsEditor=xterm, -e, nmtui-edit enableNotifications=true 070701178C0FD8000081A40000000200000002000000015A3D9FC9000000AB000000FD0000001000000000000000000000003700000000nm-tray-0.3.0.19~git.29290df/resources/nm-tray.desktop[Desktop Entry] Type=Application Name=nm-tray Comment=NetworkManager frontend (tray icon) Icon=network-transmit TryExec=nm-tray Exec=nm-tray Categories=System;Monitor;Qt; 07070117A67183000041ED0000000200000002000000025A3D9FC900000000000000FD0000001000000000000000000000002100000000nm-tray-0.3.0.19~git.29290df/src07070117A67459000081A40000000200000002000000015A3D9FC900000FB4000000FD0000001000000000000000000000003400000000nm-tray-0.3.0.19~git.29290df/src/connectioninfo.cpp/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #include "connectioninfo.h" #include "ui_connectioninfo.h" #include "nmproxy.h" #include <QScrollArea> #include <QLabel> #include <QItemSelection> #include <QSortFilterProxyModel> ConnectionInfo::ConnectionInfo(NmModel * model, QWidget *parent) : QDialog{parent} , ui{new Ui::ConnectionInfo} , mModel{model} , mActive{new NmProxy} , mSorted{new QSortFilterProxyModel} { setAttribute(Qt::WA_DeleteOnClose); ui->setupUi(this); mActive->setNmModel(mModel, NmModel::ActiveConnectionType); mSorted->setSortCaseSensitivity(Qt::CaseInsensitive); mSorted->sort(0); mSorted->setSourceModel(mActive.data()); for (int i = 0, row_cnt = mSorted->rowCount(); i < row_cnt; ++i) { addTab(mSorted->index(i, 0)); } connect(mSorted.data(), &QAbstractItemModel::rowsInserted, [this] (QModelIndex const & parent, int first, int last) { ui->tabWidget->setUpdatesEnabled(false); for (int i = first; i <= last; ++i) addTab(mSorted->index(i, 0, parent)); ui->tabWidget->setUpdatesEnabled(true); }); connect(mSorted.data(), &QAbstractItemModel::rowsAboutToBeRemoved, [this] (QModelIndex const & parent, int first, int last) { ui->tabWidget->setUpdatesEnabled(false); for (int i = first; i <= last; ++i) removeTab(mSorted->index(i, 0, parent)); ui->tabWidget->setUpdatesEnabled(true); }); connect(mSorted.data(), &QAbstractItemModel::dataChanged, [this] (const QModelIndex & topLeft, const QModelIndex & bottomRight, const QVector<int> & /*roles*/) { ui->tabWidget->setUpdatesEnabled(false); for (auto const & i : QItemSelection{topLeft, bottomRight}.indexes()) changeTab(i); ui->tabWidget->setUpdatesEnabled(true); }); } ConnectionInfo::~ConnectionInfo() { } void ConnectionInfo::addTab(QModelIndex const & index) { QScrollArea * content = new QScrollArea; QLabel * l = new QLabel{mSorted->data(index, NmModel::ActiveConnectionInfoRole).toString()}; content->setWidget(l); //QTabWidget takes ownership of the page (if we will not take it back) ui->tabWidget->insertTab(index.row(), content, mSorted->data(index, NmModel::IconRole).value<QIcon>(), mSorted->data(index, NmModel::NameRole).toString()); } void ConnectionInfo::removeTab(QModelIndex const & index) { const int i = index.row(); QWidget * w = ui->tabWidget->widget(i); ui->tabWidget->removeTab(i); w->deleteLater(); } void ConnectionInfo::changeTab(QModelIndex const & index) { const int i = index.row(); QScrollArea * content = qobject_cast<QScrollArea *>(ui->tabWidget->widget(i)); Q_ASSERT(nullptr != content); // Note: the text is HTML formatted and the QLabel probably creates some DOM internal represntation. // Should the DOM structure change, the QLabel will not update correctly upon the plain setText() content->setWidget(new QLabel{mSorted->data(index, NmModel::ActiveConnectionInfoRole).toString()}); ui->tabWidget->tabBar()->setTabText(i, mSorted->data(index, NmModel::NameRole).toString()); ui->tabWidget->tabBar()->setTabIcon(i, mSorted->data(index, NmModel::IconRole).value<QIcon>()); } 07070117A6745A000081A40000000200000002000000015A3D9FC9000005C9000000FD0000001000000000000000000000003200000000nm-tray-0.3.0.19~git.29290df/src/connectioninfo.h/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #ifndef CONNECTIONINFO_H #define CONNECTIONINFO_H #include <QDialog> namespace Ui { class ConnectionInfo; } class NmModel; class NmProxy; class QSortFilterProxyModel; class ConnectionInfo : public QDialog { Q_OBJECT public: explicit ConnectionInfo(NmModel * model, QWidget *parent = nullptr); ~ConnectionInfo(); private: void addTab(QModelIndex const & index); void removeTab(QModelIndex const & index); void changeTab(QModelIndex const & index); private: QScopedPointer<Ui::ConnectionInfo> ui; NmModel * mModel; QScopedPointer<NmProxy> mActive; QScopedPointer<QSortFilterProxyModel> mSorted; }; #endif // CONNECTIONINFO_H 07070117A6745F000081A40000000200000002000000015A3D9FC90000030E000000FD0000001000000000000000000000003300000000nm-tray-0.3.0.19~git.29290df/src/connectioninfo.ui<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>ConnectionInfo</class> <widget class="QDialog" name="ConnectionInfo"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>570</width> <height>614</height> </rect> </property> <property name="windowTitle"> <string>Connection information</string> </property> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> <widget class="QTabWidget" name="tabWidget"> <property name="currentIndex"> <number>-1</number> </property> <property name="iconSize"> <size> <width>32</width> <height>32</height> </size> </property> </widget> </item> </layout> </widget> <resources/> <connections/> </ui> 07070117A67460000081A40000000200000002000000015A3D9FC900001408000000FD0000001000000000000000000000002B00000000nm-tray-0.3.0.19~git.29290df/src/icons.cpp/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #include "icons.h" #include <QStringList> #include <QDebug> namespace icons { QIcon getIcon(Icon ico) { static const QStringList i_empty; QStringList const * icon_names = &i_empty; switch (ico) { case NETWORK_OFFLINE: static const QStringList i_network_offline = { QStringLiteral("network-offline-symbolic") }; icon_names = &i_network_offline; break; case NETWORK_WIRED: static const QStringList i_network_wired = { QStringLiteral("network-wired-symbolic") }; icon_names = &i_network_wired; break; case NETWORK_WIRED_DISCONNECTED: static const QStringList i_network_wired_disconnected = { QStringLiteral("network-wired-disconnected-symbolic") }; icon_names = &i_network_wired_disconnected; break; case NETWORK_WIFI_DISCONNECTED: static const QStringList i_wifi_disconnected = { QStringLiteral("network-wireless-disconnected-symbolic") }; icon_names = &i_wifi_disconnected; break; case NETWORK_WIFI_ACQUIRING: static const QStringList i_wifi_acquiring = { QStringLiteral("network-wireless-acquiring-symbolic") }; icon_names = &i_wifi_acquiring; break; case NETWORK_WIFI_NONE: static const QStringList i_wifi_none = { QStringLiteral("network-wireless-signal-none-symbolic"), QStringLiteral("network-wireless-connected-00-symbolic") }; icon_names = &i_wifi_none; break; case NETWORK_WIFI_WEAK: static const QStringList i_wifi_weak = { QStringLiteral("network-wireless-signal-weak-symbolic"), QStringLiteral("network-wireless-connected-25-symbolic") }; icon_names = &i_wifi_weak; break; case NETWORK_WIFI_OK: static const QStringList i_wifi_ok = { QStringLiteral("network-wireless-signal-ok-symbolic"), QStringLiteral("network-wireless-connected-50-symbolic") }; icon_names = &i_wifi_ok; break; case NETWORK_WIFI_GOOD: static const QStringList i_wifi_good = { QStringLiteral("network-wireless-signal-good-symbolic"), QStringLiteral("network-wireless-connected-75-symbolic") }; icon_names = &i_wifi_good; break; case NETWORK_WIFI_EXCELENT: static const QStringList i_wifi_excelent = { QStringLiteral("network-wireless-signal-excellent-symbolic"), QStringLiteral("network-wireless-connected-100-symbolic") }; icon_names = &i_wifi_excelent; break; case NETWORK_VPN: static const QStringList i_network_vpn = { QStringLiteral("network-vpn") }; icon_names = &i_network_vpn; break; case SECURITY_LOW: static const QStringList i_security_low = { QStringLiteral("security-low-symbolic") }; icon_names = &i_security_low; break; case SECURITY_HIGH: static const QStringList i_security_high = { QStringLiteral("security-high-symbolic") }; icon_names = &i_security_high; break; case PREFERENCES_NETWORK: static const QStringList i_preferences_network = { QStringLiteral("preferences-system-network") }; icon_names = &i_preferences_network; break; }; for (auto const & name : *icon_names) { QIcon icon{QIcon::fromTheme(name)}; if (!icon.isNull()) return icon; } //TODO: fallback!?! return QIcon::fromTheme(QStringLiteral("network-transmit")); } Icon wifiSignalIcon(const int signal) { if (0 >= signal) return icons::NETWORK_WIFI_NONE; else if (25 >= signal) return icons::NETWORK_WIFI_WEAK; else if (50 >= signal) return icons::NETWORK_WIFI_OK; else if (75 >= signal) return icons::NETWORK_WIFI_GOOD; else return icons::NETWORK_WIFI_EXCELENT; } } 07070117A67461000081A40000000200000002000000015A3D9FC9000005A0000000FD0000001000000000000000000000002900000000nm-tray-0.3.0.19~git.29290df/src/icons.h/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #if !defined(ICONS_H) #define ICONS_H #include <QIcon> namespace icons { enum Icon { NETWORK_OFFLINE , NETWORK_WIRED , NETWORK_WIRED_DISCONNECTED , NETWORK_WIFI_ACQUIRING , NETWORK_WIFI_NONE , NETWORK_WIFI_WEAK , NETWORK_WIFI_OK , NETWORK_WIFI_GOOD , NETWORK_WIFI_EXCELENT , NETWORK_WIFI_DISCONNECTED , NETWORK_VPN , SECURITY_LOW , SECURITY_HIGH , PREFERENCES_NETWORK }; QIcon getIcon(Icon ico); Icon wifiSignalIcon(const int signal); } #endif 07070117A67462000081A40000000200000002000000015A3D9FC9000003CB000000FD0000001000000000000000000000002900000000nm-tray-0.3.0.19~git.29290df/src/log.cpp/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #include "log.h" #include <QtGlobal> #if defined(NDEBUG) Q_LOGGING_CATEGORY(NM_TRAY, "nm-tray", QtInfoMsg) #else Q_LOGGING_CATEGORY(NM_TRAY, "nm-tray") #endif 07070117A67463000081A40000000200000002000000015A3D9FC90000039F000000FD0000001000000000000000000000002700000000nm-tray-0.3.0.19~git.29290df/src/log.h/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #if !defined(LOG_H) #define LOG_H #include <QLoggingCategory> Q_DECLARE_LOGGING_CATEGORY(NM_TRAY) #endif //LOG_H 07070117A67464000081A40000000200000002000000015A3D9FC9000004BA000000FD0000001000000000000000000000002A00000000nm-tray-0.3.0.19~git.29290df/src/main.cpp/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #include <QApplication> #include "tray.h" #include "icons.h" int main(int argc, char * argv[]) { QApplication app{argc, argv}; app.setOrganizationName(QStringLiteral("nm-tray")); app.setApplicationName(QStringLiteral("nm-tray")); app.setWindowIcon(icons::getIcon(icons::PREFERENCES_NETWORK)); app.setQuitOnLastWindowClosed(false); Tray tray; return app.exec(); } 07070117A67465000081A40000000200000002000000015A3D9FC90000132F000000FD0000001000000000000000000000002E00000000nm-tray-0.3.0.19~git.29290df/src/menuview.cpp/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2016~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #include "menuview.h" #include "nmmodel.h" #include <QSortFilterProxyModel> #include <QScrollBar> #include <QProxyStyle> #include <QStyledItemDelegate> #include <QApplication> #include <QPainter> #include <QDebug> namespace { class SingleActivateStyle : public QProxyStyle { public: using QProxyStyle::QProxyStyle; virtual int styleHint(StyleHint hint, const QStyleOption * option = 0, const QWidget * widget = 0, QStyleHintReturn * returnData = 0) const override { if(hint == QStyle::SH_ItemView_ActivateItemOnSingleClick) return 1; return QProxyStyle::styleHint(hint, option, widget, returnData); } }; class MultiIconDelegate : public QStyledItemDelegate { public: using QStyledItemDelegate::QStyledItemDelegate; void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { Q_ASSERT(index.isValid()); QStyleOptionViewItem opt = option; initStyleOption(&opt, index); //add the security overlay icon QIcon sec_icon = qvariant_cast<QIcon>(index.data(NmModel::IconSecurityRole)); if (!sec_icon.isNull()) { QPixmap res_pixmap = opt.icon.pixmap(opt.decorationSize); QPainter p{&res_pixmap}; QSize sec_size = res_pixmap.size(); sec_size /= 2; QPoint sec_pos = res_pixmap.rect().bottomRight(); sec_pos -= QPoint{sec_size.width(), sec_size.height()}; p.drawPixmap(sec_pos, sec_icon.pixmap(sec_size)); opt.icon = QIcon{res_pixmap}; } QStyle *style = option.widget ? option.widget->style() : QApplication::style(); style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, option.widget); } }; } MenuView::MenuView(QAbstractItemModel * model, QWidget * parent /*= nullptr*/) : QListView(parent) , mProxy{new QSortFilterProxyModel{this}} , mMaxItemsToShow(10) { setEditTriggers(NoEditTriggers); setSizeAdjustPolicy(AdjustToContents); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setSelectionBehavior(SelectRows); setSelectionMode(NoSelection); setFrameShape(QFrame::HLine); setFrameShadow(QFrame::Plain); setStyle(new SingleActivateStyle); mProxy->setSourceModel(model); mProxy->setDynamicSortFilter(true); mProxy->setFilterRole(Qt::DisplayRole); mProxy->setFilterCaseSensitivity(Qt::CaseInsensitive); mProxy->setSortRole(Qt::DisplayRole); mProxy->setSortCaseSensitivity(Qt::CaseInsensitive); mProxy->sort(0); { QScopedPointer<QItemSelectionModel> guard{selectionModel()}; setModel(mProxy); } { QScopedPointer<QAbstractItemDelegate> guard{itemDelegate()}; setItemDelegate(new MultiIconDelegate{this}); } } void MenuView::setFilter(QString const & filter) { mProxy->setFilterFixedString(filter); const int count = mProxy->rowCount(); if (0 < count) { if (count > mMaxItemsToShow) { setCurrentIndex(mProxy->index(mMaxItemsToShow - 1, 0)); verticalScrollBar()->triggerAction(QScrollBar::SliderToMinimum); } else { setCurrentIndex(mProxy->index(count - 1, 0)); } } } void MenuView::setMaxItemsToShow(int max) { mMaxItemsToShow = max; } void MenuView::activateCurrent() { QModelIndex const index = currentIndex(); if (index.isValid()) emit activated(index); } QSize MenuView::viewportSizeHint() const { const int count = mProxy->rowCount(); QSize s{0, 0}; if (0 < count) { const bool scrollable = mMaxItemsToShow < count; s.setWidth(sizeHintForColumn(0) + (scrollable ? verticalScrollBar()->sizeHint().width() : 0)); s.setHeight(sizeHintForRow(0) * (scrollable ? mMaxItemsToShow : count)); } return s; } QSize MenuView::minimumSizeHint() const { return QSize{0, 0}; } 07070117A67466000081A40000000200000002000000015A3D9FC9000006A4000000FD0000001000000000000000000000002C00000000nm-tray-0.3.0.19~git.29290df/src/menuview.h/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2016~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #if !defined(MENU_VIEW_H) #define MENU_VIEW_H #include <QListView> class QAbstractItemModel; class QSortFilterProxyModel; class MenuView : public QListView { Q_OBJECT public: MenuView(QAbstractItemModel * model, QWidget * parent = nullptr); /*! \brief Sets the filter for entries to be presented */ void setFilter(QString const & filter); /*! \brief Set the maximum number of items/results to show */ void setMaxItemsToShow(int max); /*! \brief Set the maximum width of item to show */ void setMaxItemWidth(int max); public Q_SLOTS: /*! \brief Trigger action on currently active item */ void activateCurrent(); protected: virtual QSize viewportSizeHint() const override; virtual QSize minimumSizeHint() const override; private: QSortFilterProxyModel * mProxy; int mMaxItemsToShow; }; #endif //MENU_VIEW_H 07070117A67467000081A40000000200000002000000015A3D9FC900000CE3000000FD0000001000000000000000000000002C00000000nm-tray-0.3.0.19~git.29290df/src/nmlist.cpp/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #include "nmlist.h" #include "ui_nmlist.h" #include "nmmodel.h" #include "nmproxy.h" #include <QSortFilterProxyModel> template <typename T> void installDblClick(QAbstractItemView * view, QAbstractItemModel * m) { T * net_model = qobject_cast<T *>(m); if (net_model) { QAbstractProxyModel * proxy = qobject_cast<QAbstractProxyModel *>(view->model()); Q_ASSERT(nullptr != proxy && proxy->sourceModel() == net_model); QObject::connect(view, &QAbstractItemView::doubleClicked, [net_model, proxy] (QModelIndex const & i) { QModelIndex source_i = proxy->mapToSource(i); switch (static_cast<NmModel::ItemType>(net_model->data(source_i, NmModel::ItemTypeRole).toInt())) { case NmModel::ActiveConnectionType: net_model->deactivateConnection(source_i); break; case NmModel::WifiNetworkType: case NmModel::ConnectionType: net_model->activateConnection(source_i); break; default: //do nothing break; } }); } } NmList::NmList(QString const & title, QAbstractItemModel * m, QWidget *parent) : QDialog(parent) , ui(new Ui::NmList) { ui->setupUi(this); setWindowTitle(title); Q_ASSERT(qobject_cast<NmModel*>(m)); QSortFilterProxyModel * proxy_sort = new QSortFilterProxyModel{this}; proxy_sort->setSortCaseSensitivity(Qt::CaseInsensitive); proxy_sort->sort(0); proxy_sort->setSourceModel(m); ui->treeView->setModel(proxy_sort); installDblClick<NmModel>(ui->treeView, m); NmProxy * proxy = new NmProxy(this); proxy->setNmModel(qobject_cast<NmModel*>(m), NmModel::ActiveConnectionType); proxy_sort = new QSortFilterProxyModel{this}; proxy_sort->setSortCaseSensitivity(Qt::CaseInsensitive); proxy_sort->sort(0); proxy_sort->setSourceModel(proxy); ui->listActive->setModel(proxy_sort); installDblClick<NmProxy>(ui->listActive, proxy); proxy = new NmProxy(this); proxy->setNmModel(qobject_cast<NmModel*>(m), NmModel::WifiNetworkType); proxy_sort = new QSortFilterProxyModel{this}; proxy_sort->setSortCaseSensitivity(Qt::CaseInsensitive); proxy_sort->sort(0); proxy_sort->setSourceModel(proxy); ui->listWifi->setModel(proxy_sort); installDblClick<NmProxy>(ui->listWifi, proxy); } NmList::~NmList() { delete ui; } 07070117A67468000081A40000000200000002000000015A3D9FC900000475000000FD0000001000000000000000000000002A00000000nm-tray-0.3.0.19~git.29290df/src/nmlist.h/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #ifndef NMLIST_H #define NMLIST_H #include <QDialog> namespace Ui { class NmList; } class QAbstractItemModel; class NmList : public QDialog { Q_OBJECT public: explicit NmList(QString const & title, QAbstractItemModel * m, QWidget *parent = nullptr); ~NmList(); private: Ui::NmList *ui; }; #endif // NMLIST_H 07070117A67469000081A40000000200000002000000015A3D9FC90000055A000000FD0000001000000000000000000000002B00000000nm-tray-0.3.0.19~git.29290df/src/nmlist.ui<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>NmList</class> <widget class="QDialog" name="NmList"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>565</width> <height>507</height> </rect> </property> <property name="windowTitle"> <string>Dialog</string> </property> <layout class="QGridLayout" name="gridLayout_2"> <item row="2" column="0"> <widget class="QLabel" name="labelAll"> <property name="text"> <string>All information</string> </property> </widget> </item> <item row="1" column="0"> <widget class="QListView" name="listActive"/> </item> <item row="0" column="0"> <widget class="QLabel" name="labelActive"> <property name="text"> <string>Active connections</string> </property> </widget> </item> <item row="1" column="1"> <widget class="QListView" name="listWifi"/> </item> <item row="0" column="1"> <widget class="QLabel" name="labelWifi"> <property name="text"> <string>Available wireless</string> </property> </widget> </item> <item row="3" column="0" colspan="2"> <widget class="QTreeView" name="treeView"> <attribute name="headerVisible"> <bool>false</bool> </attribute> </widget> </item> </layout> </widget> <resources/> <connections/> </ui> 07070117A6746A000081A40000000200000002000000015A3D9FC9000101D1000000FD0000001000000000000000000000002D00000000nm-tray-0.3.0.19~git.29290df/src/nmmodel.cpp/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #include "nmmodel.h" #include "nmmodel_p.h" #include "icons.h" #include "log.h" #include <NetworkManagerQt/GenericTypes> #include <NetworkManagerQt/VpnConnection> #include <NetworkManagerQt/WirelessDevice> #include <NetworkManagerQt/AdslDevice> #include <NetworkManagerQt/WiredDevice> #include <NetworkManagerQt/WimaxDevice> #include <NetworkManagerQt/VlanDevice> #include <NetworkManagerQt/BondDevice> #include <NetworkManagerQt/BridgeDevice> #include <NetworkManagerQt/GenericDevice> #include <NetworkManagerQt/InfinibandDevice> #include <NetworkManagerQt/BluetoothDevice> #include <NetworkManagerQt/OlpcMeshDevice> #include <NetworkManagerQt/TeamDevice> #include <NetworkManagerQt/WirelessSetting> #include <NetworkManagerQt/WirelessSecuritySetting> #include <NetworkManagerQt/Utils> #include <NetworkManagerQt/ConnectionSettings> #include <QDBusPendingCallWatcher> #include <QInputDialog> namespace { NetworkManager::ConnectionSettings::Ptr assembleWpaXPskSettings(const NetworkManager::AccessPoint::Ptr accessPoint) { //TODO: enhance getting the password from user bool ok; QString password = QInputDialog::getText(nullptr, NmModel::tr("nm-tray - wireless password") , NmModel::tr("Password is needed for connection to '%1':").arg(accessPoint->ssid()) , QLineEdit::Password, QString(), &ok); if (!ok) return NetworkManager::ConnectionSettings::Ptr{nullptr}; NetworkManager::ConnectionSettings::Ptr settings{new NetworkManager::ConnectionSettings{NetworkManager::ConnectionSettings::Wireless}}; settings->setId(accessPoint->ssid()); settings->setUuid(NetworkManager::ConnectionSettings::createNewUuid()); settings->setAutoconnect(true); //Note: workaround for wrongly (randomly) initialized gateway-ping-timeout settings->setGatewayPingTimeout(0); NetworkManager::WirelessSetting::Ptr wifi_sett = settings->setting(NetworkManager::Setting::Wireless).dynamicCast<NetworkManager::WirelessSetting>(); wifi_sett->setInitialized(true); wifi_sett->setSsid(accessPoint->ssid().toUtf8()); wifi_sett->setSecurity("802-11-wireless-security"); NetworkManager::WirelessSecuritySetting::Ptr security_sett = settings->setting(NetworkManager::Setting::WirelessSecurity).dynamicCast<NetworkManager::WirelessSecuritySetting>(); security_sett->setInitialized(true); if (NetworkManager::AccessPoint::Adhoc == accessPoint->mode()) { wifi_sett->setMode(NetworkManager::WirelessSetting::Adhoc); security_sett->setKeyMgmt(NetworkManager::WirelessSecuritySetting::WpaNone); } else { security_sett->setKeyMgmt(NetworkManager::WirelessSecuritySetting::WpaPsk); } security_sett->setPsk(password); return settings; } } NmModelPrivate::NmModelPrivate() { insertActiveConnections(); insertConnections(); insertDevices(); insertWifiNetworks(); //initialize NetworkManager signals connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceAdded, this, &NmModelPrivate::onDeviceAdded); connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceRemoved, this, &NmModelPrivate::onDeviceRemoved); connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionAdded, this, &NmModelPrivate::onActiveConnectionAdded); connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionRemoved, this, &NmModelPrivate::onActiveConnectionRemoved); connect(NetworkManager::settingsNotifier(), &NetworkManager::SettingsNotifier::connectionAdded, this, &NmModelPrivate::onConnectionAdded); connect(NetworkManager::settingsNotifier(), &NetworkManager::SettingsNotifier::connectionRemoved, this, static_cast<void (NmModelPrivate::*)(QString const &)>(&NmModelPrivate::onConnectionRemoved)); // Note: the connectionRemoved is never emitted in case network-manager service stop, // we need remove the connections manually. connect(NetworkManager::notifier(), &NetworkManager::Notifier::serviceDisappeared, this, &NmModelPrivate::clearConnections); //qCDebug(NM_TRAY) << mActiveConns.size() << mConnections.size() << mDevices.size(); } NmModelPrivate::~NmModelPrivate() { } void NmModelPrivate::removeActiveConnection(int pos) { //active connections signals NetworkManager::ActiveConnection::Ptr conn = mActiveConns.takeAt(pos); conn->disconnect(this); } void NmModelPrivate::clearActiveConnections() { while (0 < mActiveConns.size()) removeActiveConnection(0); } void NmModelPrivate::addActiveConnection(NetworkManager::ActiveConnection::Ptr conn) { mActiveConns.push_back(conn); connect(conn.data(), &NetworkManager::ActiveConnection::connectionChanged, this, &NmModelPrivate::onActiveConnectionUpdated); connect(conn.data(), &NetworkManager::ActiveConnection::default4Changed, this, &NmModelPrivate::onActiveConnectionUpdated); connect(conn.data(), &NetworkManager::ActiveConnection::default6Changed, this, &NmModelPrivate::onActiveConnectionUpdated); connect(conn.data(), &NetworkManager::ActiveConnection::dhcp4ConfigChanged, this, &NmModelPrivate::onActiveConnectionUpdated); connect(conn.data(), &NetworkManager::ActiveConnection::dhcp6ConfigChanged, this, &NmModelPrivate::onActiveConnectionUpdated); connect(conn.data(), &NetworkManager::ActiveConnection::ipV4ConfigChanged, this, &NmModelPrivate::onActiveConnectionUpdated); connect(conn.data(), &NetworkManager::ActiveConnection::ipV6ConfigChanged, this, &NmModelPrivate::onActiveConnectionUpdated); connect(conn.data(), &NetworkManager::ActiveConnection::idChanged, this, &NmModelPrivate::onActiveConnectionUpdated); connect(conn.data(), &NetworkManager::ActiveConnection::typeChanged, this, &NmModelPrivate::onActiveConnectionUpdated); connect(conn.data(), &NetworkManager::ActiveConnection::masterChanged, this, &NmModelPrivate::onActiveConnectionUpdated); connect(conn.data(), &NetworkManager::ActiveConnection::specificObjectChanged, this, &NmModelPrivate::onActiveConnectionUpdated); connect(conn.data(), &NetworkManager::ActiveConnection::stateChanged, this, &NmModelPrivate::onActiveConnectionUpdated); connect(conn.data(), &NetworkManager::ActiveConnection::vpnChanged, this, &NmModelPrivate::onActiveConnectionUpdated); connect(conn.data(), &NetworkManager::ActiveConnection::uuidChanged, this, &NmModelPrivate::onActiveConnectionUpdated); connect(conn.data(), &NetworkManager::ActiveConnection::devicesChanged, this, &NmModelPrivate::onActiveConnectionUpdated); if (conn->vpn()) { connect(qobject_cast<NetworkManager::VpnConnection *>(conn.data()), &NetworkManager::VpnConnection::bannerChanged, this, &NmModelPrivate::onActiveConnectionUpdated); connect(qobject_cast<NetworkManager::VpnConnection *>(conn.data()), &NetworkManager::VpnConnection::stateChanged, this, &NmModelPrivate::onActiveConnectionUpdated); } } void NmModelPrivate::insertActiveConnections() { for (auto const & conn : NetworkManager::activeConnections()) addActiveConnection(conn); } void NmModelPrivate::removeConnection(int pos) { //connections signals NetworkManager::Connection::Ptr conn = mConnections.takeAt(pos); conn->disconnect(this); } void NmModelPrivate::clearConnections() { while (0 < mConnections.size()) removeConnection(0); } void NmModelPrivate::addConnection(NetworkManager::Connection::Ptr conn) { mConnections.push_back(conn); //connections signals connect(conn.data(), &NetworkManager::Connection::updated, this, &NmModelPrivate::onConnectionUpdated); connect(conn.data(), &NetworkManager::Connection::removed, this, static_cast<void (NmModelPrivate::*)()>(&NmModelPrivate::onConnectionRemoved)); } void NmModelPrivate::insertConnections() { for (auto const & conn : NetworkManager::listConnections()) addConnection(conn); } void NmModelPrivate::removeDevice(int pos) { //connections signals NetworkManager::Device::Ptr device = mDevices.takeAt(pos); device->disconnect(this); } void NmModelPrivate::clearDevices() { while (0 < mDevices.size()) removeDevice(0); } void NmModelPrivate::addDevice(NetworkManager::Device::Ptr device) { mDevices.push_back(device); //device signals connect(device.data(), &NetworkManager::Device::stateChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::activeConnectionChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::autoconnectChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::availableConnectionChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::availableConnectionAppeared, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::availableConnectionDisappeared, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::capabilitiesChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::dhcp4ConfigChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::dhcp6ConfigChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::driverChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::driverVersionChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::firmwareMissingChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::firmwareVersionChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::interfaceNameChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::ipV4AddressChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::ipV4ConfigChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::ipV6ConfigChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::ipInterfaceChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::managedChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::physicalPortIdChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::mtuChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::nmPluginMissingChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::meteredChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::connectionStateChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::stateReasonChanged, this, &NmModelPrivate::onDeviceUpdated); connect(device.data(), &NetworkManager::Device::udiChanged, this, &NmModelPrivate::onDeviceUpdated); switch (device->type()) { case NetworkManager::Ethernet: connect(qobject_cast<NetworkManager::WiredDevice *>(device.data()), &NetworkManager::WiredDevice::bitRateChanged, this, &NmModelPrivate::onDeviceUpdated); connect(qobject_cast<NetworkManager::WiredDevice *>(device.data()), &NetworkManager::WiredDevice::carrierChanged, this, &NmModelPrivate::onDeviceUpdated); connect(qobject_cast<NetworkManager::WiredDevice *>(device.data()), &NetworkManager::WiredDevice::hardwareAddressChanged, this, &NmModelPrivate::onDeviceUpdated); connect(qobject_cast<NetworkManager::WiredDevice *>(device.data()), &NetworkManager::WiredDevice::permanentHardwareAddressChanged, this, &NmModelPrivate::onDeviceUpdated); break; case NetworkManager::Device::Wifi: connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::bitRateChanged, this, &NmModelPrivate::onDeviceUpdated); connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::activeAccessPointChanged, this, &NmModelPrivate::onDeviceUpdated); connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::modeChanged, this, &NmModelPrivate::onDeviceUpdated); connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::wirelessCapabilitiesChanged, this, &NmModelPrivate::onDeviceUpdated); connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::hardwareAddressChanged, this, &NmModelPrivate::onDeviceUpdated); connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::permanentHardwareAddressChanged, this, &NmModelPrivate::onDeviceUpdated); connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::wirelessPropertiesChanged, this, &NmModelPrivate::onDeviceUpdated); connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::accessPointAppeared, this, &NmModelPrivate::onDeviceUpdated); connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::accessPointDisappeared, this, &NmModelPrivate::onDeviceUpdated); connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::networkAppeared, this, &NmModelPrivate::onWifiNetworkAppeared); connect(qobject_cast<NetworkManager::WirelessDevice *>(device.data()), &NetworkManager::WirelessDevice::networkDisappeared, this, &NmModelPrivate::onWifiNetworkDisappeared); break; default: //TODO: other device types! break; } } void NmModelPrivate::insertDevices() { for (auto const & device : NetworkManager::networkInterfaces()) addDevice(device); } void NmModelPrivate::removeWifiNetwork(int pos) { //network signals NetworkManager::WirelessNetwork::Ptr net = mWifiNets.takeAt(pos); net->disconnect(this); } void NmModelPrivate::clearWifiNetworks() { while (0 < mWifiNets.size()) removeWifiNetwork(0); } void NmModelPrivate::addWifiNetwork(NetworkManager::WirelessNetwork::Ptr net) { mWifiNets.push_back(net); //device signals connect(net.data(), &NetworkManager::WirelessNetwork::signalStrengthChanged, this, &NmModelPrivate::onWifiNetworkUpdated); connect(net.data(), &NetworkManager::WirelessNetwork::referenceAccessPointChanged, this, &NmModelPrivate::onWifiNetworkUpdated); connect(net.data(), &NetworkManager::WirelessNetwork::disappeared, this, &NmModelPrivate::onWifiNetworkUpdated); } void NmModelPrivate::insertWifiNetworks() { for (auto const & device : mDevices) { if (NetworkManager::Device::Wifi == device->type()) { NetworkManager::WirelessDevice::Ptr w_dev = device.objectCast<NetworkManager::WirelessDevice>(); for (auto const & net : w_dev->networks()) { if (!net.isNull()) { addWifiNetwork(net); } } } } } NetworkManager::ActiveConnection::Ptr NmModelPrivate::findActiveConnection(QString const & path) { auto i = std::find_if(mActiveConns.cbegin(), mActiveConns.cend(), [&path] (NetworkManager::ActiveConnection::Ptr const & conn) -> bool { return conn->path() == path; }); return mActiveConns.cend() == i ? NetworkManager::ActiveConnection::Ptr{} : *i; } template <typename Predicate> NetworkManager::Device::Ptr NmModelPrivate::findDevice(Predicate const & pred) { auto i = std::find_if(mDevices.cbegin(), mDevices.cend(), pred); return mDevices.cend() == i ? NetworkManager::Device::Ptr{} : *i; } NetworkManager::Device::Ptr NmModelPrivate::findDeviceUni(QString const & uni) { return findDevice([&uni] (NetworkManager::Device::Ptr const & dev) { return dev->uni() == uni; }); } NetworkManager::Device::Ptr NmModelPrivate::findDeviceInterface(QString const & interfaceName) { return findDevice([&interfaceName] (NetworkManager::Device::Ptr const & dev) { return dev->interfaceName() == interfaceName; }); } NetworkManager::WirelessNetwork::Ptr NmModelPrivate::findWifiNetwork(QString const & ssid, QString const & devUni) { auto i = std::find_if(mWifiNets.cbegin(), mWifiNets.cend(), [&ssid, &devUni] (NetworkManager::WirelessNetwork::Ptr const & net) -> bool { return net->ssid() == ssid && net->device() == devUni; }); return mWifiNets.cend() == i ? NetworkManager::WirelessNetwork::Ptr{} : *i; } void NmModelPrivate::onConnectionUpdated() { emit connectionUpdate(qobject_cast<NetworkManager::Connection *>(sender())); } void NmModelPrivate::onConnectionRemoved() { emit connectionRemove(qobject_cast<NetworkManager::Connection *>(sender())); } void NmModelPrivate::onActiveConnectionUpdated() { emit activeConnectionUpdate(qobject_cast<NetworkManager::ActiveConnection *>(sender())); } void NmModelPrivate::onDeviceUpdated() { emit deviceUpdate(qobject_cast<NetworkManager::Device *>(sender())); } void NmModelPrivate::onWifiNetworkAppeared(QString const & ssid) { NetworkManager::Device * dev = qobject_cast<NetworkManager::Device *>(sender()); emit wifiNetworkAdd(dev, ssid); emit deviceUpdate(dev); } void NmModelPrivate::onWifiNetworkDisappeared(QString const & ssid) { NetworkManager::Device * dev = qobject_cast<NetworkManager::Device *>(sender()); emit wifiNetworkRemove(dev, ssid); emit deviceUpdate(dev); } void NmModelPrivate::onWifiNetworkUpdated() { emit wifiNetworkUpdate(qobject_cast<NetworkManager::WirelessNetwork *>(sender())); } void NmModelPrivate::onDeviceAdded(QString const & uni) { NetworkManager::Device::Ptr dev = NetworkManager::findNetworkInterface(uni); if (!dev.isNull()) { if (dev->isValid()) qCWarning(NM_TRAY).noquote() << Q_FUNC_INFO << uni << " is currently invalid..."; emit deviceAdd(dev); } } void NmModelPrivate::onDeviceRemoved(QString const & uni) { NetworkManager::Device::Ptr dev = findDeviceUni(uni); if (!dev.isNull()) { if (dev->isValid()) qCWarning(NM_TRAY).noquote() << Q_FUNC_INFO << uni << " is currently invalid..."; emit deviceRemove(dev.data()); } } void NmModelPrivate::onActiveConnectionAdded(QString const & path) { NetworkManager::ActiveConnection::Ptr conn = NetworkManager::findActiveConnection(path);//XXX: const QString &uni if (!conn.isNull()) { if (conn->isValid()) qCWarning(NM_TRAY).noquote() << Q_FUNC_INFO << path << " is currently invalid..."; emit activeConnectionAdd(conn); } } void NmModelPrivate::onActiveConnectionRemoved(QString const & path) { NetworkManager::ActiveConnection::Ptr conn = findActiveConnection(path);//XXX: const QString &uni if (!conn.isNull()) { if (conn->isValid()) qCWarning(NM_TRAY).noquote() << Q_FUNC_INFO << path << " is currently invalid..."; emit activeConnectionRemove(conn.data()); } } void NmModelPrivate::onActiveConnectionsChanged() { emit activeConnectionsReset(); } void NmModelPrivate::onConnectionAdded(QString const & path) { NetworkManager::Connection::Ptr conn = NetworkManager::findConnection(path); if (!conn.isNull()) { if (conn->isValid()) qCWarning(NM_TRAY).noquote() << Q_FUNC_INFO << path << " is currently invalid..."; emit connectionAdd(conn); } } void NmModelPrivate::onConnectionRemoved(QString const & path) { NetworkManager::Connection::Ptr conn = NetworkManager::findConnection(path); if (!conn.isNull()) { if (conn->isValid()) qCWarning(NM_TRAY).noquote() << Q_FUNC_INFO << path << " is currently invalid..."; emit connectionRemove(conn.data()); } } NmModel::NmModel(QObject * parent) : QAbstractItemModel(parent) , d{new NmModelPrivate} { connect(d.data(), &NmModelPrivate::connectionAdd, [this] (NetworkManager::Connection::Ptr conn) { //qCDebug(NM_TRAY) << "connectionAdd" << conn->name(); if (0 > d->mConnections.indexOf(conn)) { const int cnt = d->mConnections.size(); beginInsertRows(createIndex(1, 0, ITEM_CONNECTION), cnt, cnt); d->addConnection(conn); endInsertRows(); } else { //TODO: onConnectionUpdate } }); connect(d.data(), &NmModelPrivate::connectionUpdate, [this] (NetworkManager::Connection * conn) { //qCDebug(NM_TRAY) << "connectionUpdate" << conn->name(); auto i = std::find(d->mConnections.cbegin(), d->mConnections.cend(), conn); if (d->mConnections.cend() != i) { QModelIndex index = createIndex(i - d->mConnections.cbegin(), 0, ITEM_CONNECTION_LEAF); emit dataChanged(index, index); } }); connect(d.data(), &NmModelPrivate::connectionRemove, [this] (NetworkManager::Connection * conn) { //qCDebug(NM_TRAY) << "connectionRemove" << conn->name(); auto i = std::find(d->mConnections.cbegin(), d->mConnections.cend(), conn); if (d->mConnections.cend() != i) { const int pos = i - d->mConnections.cbegin(); beginRemoveRows(createIndex(1, 0, ITEM_CONNECTION), pos, pos); d->removeConnection(pos); endRemoveRows(); } }); connect(d.data(), &NmModelPrivate::activeConnectionAdd, [this] (NetworkManager::ActiveConnection::Ptr conn) { //qCDebug(NM_TRAY) << "activecCnnectionAdd" << conn->connection()->name(); if (0 > d->mActiveConns.indexOf(conn)) { const int cnt = d->mActiveConns.size(); beginInsertRows(createIndex(0, 0, ITEM_ACTIVE), cnt, cnt); d->addActiveConnection(conn); endInsertRows(); } else { //TODO: onActiveConnectionUpdate } }); connect(d.data(), &NmModelPrivate::activeConnectionUpdate, [this] (NetworkManager::ActiveConnection * conn) { //qCDebug(NM_TRAY) << "activecCnnectionUpdate" << conn->connection()->name(); auto i = std::find(d->mActiveConns.cbegin(), d->mActiveConns.cend(), conn); if (d->mActiveConns.cend() != i) { QModelIndex index = createIndex(i - d->mActiveConns.cbegin(), 0, ITEM_ACTIVE_LEAF); emit dataChanged(index, index); } }); connect(d.data(), &NmModelPrivate::activeConnectionRemove, [this] (NetworkManager::ActiveConnection * conn) { //qCDebug(NM_TRAY) << "activecCnnectionRemove" << conn->connection()->name(); auto i = std::find(d->mActiveConns.cbegin(), d->mActiveConns.cend(), conn); if (d->mActiveConns.cend() != i) { const int pos = i - d->mActiveConns.cbegin(); beginRemoveRows(createIndex(0, 0, ITEM_ACTIVE), pos, pos); d->removeActiveConnection(pos); endRemoveRows(); } }); connect(d.data(), &NmModelPrivate::activeConnectionsReset, [this] () { //qCDebug(NM_TRAY) << "activecCnnectionReset"; const int cnt = d->mActiveConns.size(); if (0 < cnt) { beginRemoveRows(createIndex(0, 0, ITEM_ACTIVE), 0, d->mActiveConns.size() - 1); d->clearActiveConnections(); endRemoveRows(); } const int new_cnt = NetworkManager::activeConnections().size(); if (0 < new_cnt) { beginInsertRows(createIndex(0, 0, ITEM_ACTIVE), 0, new_cnt - 1); d->insertActiveConnections(); endInsertRows(); } }); connect(d.data(), &NmModelPrivate::deviceAdd, [this] (NetworkManager::Device::Ptr dev) { //qCDebug(NM_TRAY) << "deviceAdd" << dev->interfaceName(); if (0 > d->mDevices.indexOf(dev)) { const int cnt = d->mDevices.size(); beginInsertRows(createIndex(2, 0, ITEM_DEVICE), cnt, cnt); d->addDevice(dev); endInsertRows(); } else { //TODO: onDeviceUpdate } }); connect(d.data(), &NmModelPrivate::deviceUpdate, [this] (NetworkManager::Device * dev) { //qCDebug(NM_TRAY) << "deviceUpdate" << dev << dev->interfaceName(); auto i = std::find(d->mDevices.cbegin(), d->mDevices.cend(), dev); if (d->mDevices.cend() != i) { QModelIndex index = createIndex(i - d->mDevices.cbegin(), 0, ITEM_DEVICE_LEAF); emit dataChanged(index, index); } }); connect(d.data(), &NmModelPrivate::deviceRemove, [this] (NetworkManager::Device * dev) { //qCDebug(NM_TRAY) << "deviceRemove" << dev->interfaceName(); auto i = std::find(d->mDevices.cbegin(), d->mDevices.cend(), dev); if (d->mDevices.cend() != i) { const int pos = i - d->mDevices.cbegin(); beginRemoveRows(createIndex(2, 0, ITEM_DEVICE), pos, pos); d->removeDevice(pos); endRemoveRows(); } }); connect(d.data(), &NmModelPrivate::wifiNetworkAdd, [this] (NetworkManager::Device * dev, QString const & ssid) { //qCDebug(NM_TRAY) << "wifiNetworkAdd" << dev << dev->interfaceName() << ssid; NetworkManager::WirelessDevice * w_dev = qobject_cast<NetworkManager::WirelessDevice *>(dev); NetworkManager::WirelessNetwork::Ptr net = w_dev->findNetwork(ssid); if (!net.isNull()) { if (0 > d->mWifiNets.indexOf(net)) { const int cnt = d->mWifiNets.size(); beginInsertRows(createIndex(3, 0, ITEM_WIFINET), cnt, cnt); d->addWifiNetwork(net); endInsertRows(); } else { //TODO: onWifiNetworkUpdate } } }); connect(d.data(), &NmModelPrivate::wifiNetworkUpdate, [this] (NetworkManager::WirelessNetwork * net) { //qCDebug(NM_TRAY) << "wifiNetworkUpdate" << net << net->ssid(); auto i = std::find(d->mWifiNets.cbegin(), d->mWifiNets.cend(), net); if (d->mWifiNets.cend() != i) { if (net->accessPoints().isEmpty()) { //remove auto pos = i - d->mWifiNets.cbegin(); beginRemoveRows(createIndex(3, 0, ITEM_WIFINET), pos, pos); d->removeWifiNetwork(pos); endRemoveRows(); } else { //update QModelIndex index = createIndex(i - d->mWifiNets.cbegin(), 0, ITEM_WIFINET_LEAF); emit dataChanged(index, index); //XXX: active connection auto dev = d->findDeviceUni((*i)->device()); if (!dev.isNull()) { auto active = dev->activeConnection(); if (!active.isNull()) { QModelIndex index = createIndex(d->mActiveConns.indexOf(active), 0, ITEM_ACTIVE_LEAF); emit dataChanged(index, index); } } } } }); connect(d.data(), &NmModelPrivate::wifiNetworkRemove, [this] (NetworkManager::Device * dev, QString const & ssid) { //qCDebug(NM_TRAY) << "wifiNetworkRemove" << dev << dev->interfaceName() << ssid; NetworkManager::WirelessNetwork::Ptr net = d->findWifiNetwork(ssid, dev->uni()); if (!net.isNull()) { auto pos = d->mWifiNets.indexOf(net); if (0 <= pos) { beginRemoveRows(createIndex(3, 0, ITEM_WIFINET), pos, pos); d->removeWifiNetwork(pos); endRemoveRows(); } } }); //qCDebug(NM_TRAY) << __FUNCTION__ << "finished"; } NmModel::~NmModel() { } /* Model hierarchy * root * - mActiveConns * - mConnections * - mDevices */ int NmModel::rowCount(const QModelIndex &parent/* = QModelIndex()*/) const { int cnt = 0; if (!parent.isValid()) cnt = 1; else { const int id = parent.internalId(); if (ITEM_ROOT == id) cnt = 4; else if (ITEM_ACTIVE == id) cnt = d->mActiveConns.size(); else if (ITEM_CONNECTION == id) cnt = d->mConnections.size(); else if (ITEM_DEVICE == id) cnt = d->mDevices.size(); else if (ITEM_WIFINET == id) cnt = d->mWifiNets.size(); } //qCDebug(NM_TRAY) << __FUNCTION__ << parent << cnt; return cnt; } int NmModel::columnCount(const QModelIndex & /*parent = QModelIndex()*/) const { //qCDebug(NM_TRAY) << __FUNCTION__ << parent << 1; //XXX: more columns for wifi connections (for name && icons...)?? return 1; } bool NmModel::isValidDataIndex(const QModelIndex & index) const { switch (static_cast<ItemId>(index.internalId())) { case ITEM_ROOT: case ITEM_ACTIVE: case ITEM_CONNECTION: case ITEM_DEVICE: case ITEM_WIFINET: return true; case ITEM_ACTIVE_LEAF: return d->mActiveConns.size() > index.row() && 0 == index.column(); case ITEM_CONNECTION_LEAF: return d->mConnections.size() > index.row() && 0 == index.column(); case ITEM_DEVICE_LEAF: return d->mDevices.size() > index.row() && 0 == index.column(); case ITEM_WIFINET_LEAF: return d->mWifiNets.size() > index.row() && 0 == index.column(); } return false; } template <> QVariant NmModel::dataRole<NmModel::ItemTypeRole>(const QModelIndex & index) const { switch (static_cast<ItemId>(index.internalId())) { case ITEM_ROOT: case ITEM_ACTIVE: case ITEM_CONNECTION: case ITEM_WIFINET: case ITEM_DEVICE: return HelperType; case ITEM_ACTIVE_LEAF: return ActiveConnectionType; case ITEM_CONNECTION_LEAF: return ConnectionType; case ITEM_DEVICE_LEAF: return DeviceType; case ITEM_WIFINET_LEAF: return WifiNetworkType; } return QVariant{}; } template <> QVariant NmModel::dataRole<NmModel::NameRole>(const QModelIndex & index) const { switch (static_cast<ItemId>(index.internalId())) { case ITEM_ROOT: return NmModel::tr("root"); case ITEM_ACTIVE: return NmModel::tr("active connection(s)"); case ITEM_CONNECTION: return NmModel::tr("connection(s)"); case ITEM_DEVICE: return NmModel::tr("device(s)"); case ITEM_WIFINET: return NmModel::tr("wifi network(s)"); case ITEM_ACTIVE_LEAF: return d->mActiveConns[index.row()]->connection()->name(); case ITEM_CONNECTION_LEAF: return d->mConnections[index.row()]->name(); case ITEM_DEVICE_LEAF: return d->mDevices[index.row()]->interfaceName(); case ITEM_WIFINET_LEAF: return d->mWifiNets[index.row()]->referenceAccessPoint()->ssid(); } return QVariant{}; } template <> QVariant NmModel::dataRole<NmModel::ConnectionTypeRole>(const QModelIndex & index) const { switch (static_cast<ItemId>(index.internalId())) { case ITEM_ROOT: case ITEM_ACTIVE: case ITEM_CONNECTION: case ITEM_DEVICE: case ITEM_WIFINET: return QVariant{}; case ITEM_DEVICE_LEAF: //TODO: other types switch (d->mDevices[index.row()]->type()) { case NetworkManager::Device::Wifi: return NetworkManager::ConnectionSettings::Wireless; case NetworkManager::Device::Wimax: return NetworkManager::ConnectionSettings::Wimax; default: return NetworkManager::ConnectionSettings::Wired; } case ITEM_ACTIVE_LEAF: return d->mActiveConns[index.row()]->connection()->settings()->connectionType(); case ITEM_CONNECTION_LEAF: return d->mConnections[index.row()]->settings()->connectionType(); case ITEM_WIFINET_LEAF: return NetworkManager::ConnectionSettings::Wireless; } return QVariant{}; } template <> QVariant NmModel::dataRole<NmModel::ConnectionTypeStringRole>(const QModelIndex & index) const { const QVariant conn_type = dataRole<ConnectionTypeRole>(index); if (!conn_type.isValid()) { return QVariant{}; } return NetworkManager::ConnectionSettings::typeAsString(static_cast<NetworkManager::ConnectionSettings::ConnectionType>(conn_type.toInt())); } template <> QVariant NmModel::dataRole<NmModel::ActiveConnectionStateRole>(const QModelIndex & index) const { switch (static_cast<ItemId>(index.internalId())) { case ITEM_ROOT: case ITEM_ACTIVE: case ITEM_CONNECTION: case ITEM_DEVICE: case ITEM_CONNECTION_LEAF: case ITEM_DEVICE_LEAF: case ITEM_WIFINET: case ITEM_WIFINET_LEAF: return -1; case ITEM_ACTIVE_LEAF: return d->mActiveConns[index.row()]->state(); } return QVariant{}; } template <> QVariant NmModel::dataRole<NmModel::ActiveConnectionMasterRole>(const QModelIndex & index) const { switch (static_cast<ItemId>(index.internalId())) { case ITEM_ROOT: case ITEM_ACTIVE: case ITEM_CONNECTION: case ITEM_DEVICE: case ITEM_CONNECTION_LEAF: case ITEM_DEVICE_LEAF: case ITEM_WIFINET: case ITEM_WIFINET_LEAF: return QVariant{}; case ITEM_ACTIVE_LEAF: return d->mActiveConns[index.row()]->master(); } return QVariant{}; } template <> QVariant NmModel::dataRole<NmModel::ActiveConnectionDevicesRole>(const QModelIndex & index) const { switch (static_cast<ItemId>(index.internalId())) { case ITEM_ROOT: case ITEM_ACTIVE: case ITEM_CONNECTION: case ITEM_DEVICE: case ITEM_CONNECTION_LEAF: case ITEM_DEVICE_LEAF: case ITEM_WIFINET: case ITEM_WIFINET_LEAF: return QVariant{}; case ITEM_ACTIVE_LEAF: return d->mActiveConns[index.row()]->devices(); } return QVariant{}; } template <> QVariant NmModel::dataRole<NmModel::IconSecurityTypeRole>(const QModelIndex & index) const { auto const internal_id = static_cast<ItemId>(index.internalId()); switch (internal_id) { case ITEM_ROOT: case ITEM_ACTIVE: case ITEM_CONNECTION: case ITEM_DEVICE: case ITEM_WIFINET: case ITEM_DEVICE_LEAF: return -1; case ITEM_CONNECTION_LEAF: case ITEM_ACTIVE_LEAF: { NetworkManager::ConnectionSettings::Ptr settings = ITEM_CONNECTION_LEAF == internal_id ? d->mConnections[index.row()]->settings() : d->mActiveConns[index.row()]->connection()->settings(); if (NetworkManager::ConnectionSettings::Wireless == settings->connectionType()) { NetworkManager::WirelessSecuritySetting::Ptr w_sett = settings->setting(NetworkManager::Setting::WirelessSecurity).staticCast<NetworkManager::WirelessSecuritySetting>(); if (w_sett.isNull()) return icons::SECURITY_LOW; else if (NetworkManager::WirelessSecuritySetting::WpaNone != w_sett->keyMgmt()) return icons::SECURITY_HIGH; else return icons::SECURITY_LOW; } return -1; } case ITEM_WIFINET_LEAF: return d->mWifiNets[index.row()]->referenceAccessPoint()->capabilities().testFlag(NetworkManager::AccessPoint::Privacy) ? icons::SECURITY_HIGH : icons::SECURITY_LOW; } return QVariant{}; } template <> QVariant NmModel::dataRole<NmModel::IconSecurityRole>(const QModelIndex & index) const { const auto type = dataRole<IconSecurityTypeRole>(index).toInt(); if (0 <= type) return icons::getIcon(static_cast<icons::Icon>(type)); else return QVariant{}; } template <> QVariant NmModel::dataRole<NmModel::SignalRole>(const QModelIndex & index) const { switch (static_cast<ItemId>(index.internalId())) { case ITEM_ROOT: case ITEM_ACTIVE: case ITEM_CONNECTION: case ITEM_DEVICE: case ITEM_DEVICE_LEAF: case ITEM_WIFINET: return -1; case ITEM_ACTIVE_LEAF: { NetworkManager::ConnectionSettings::Ptr sett = d->mActiveConns[index.row()]->connection()->settings(); //TODO: other type with signals!?! if (NetworkManager::ConnectionSettings::Wireless == sett->connectionType()) { NetworkManager::WirelessSetting::Ptr w_sett = sett->setting(NetworkManager::Setting::Wireless).staticCast<NetworkManager::WirelessSetting>(); Q_ASSERT(!w_sett.isNull()); for (auto const & dev_uni : d->mActiveConns[index.row()]->devices()) { auto dev = NetworkManager::findNetworkInterface(dev_uni); if (!dev.isNull() && dev->isValid()) { auto w_dev = dev.objectCast<NetworkManager::WirelessDevice>(); if (!w_dev.isNull()) { auto wifi_net = w_dev->findNetwork(w_sett->ssid()); if (!wifi_net.isNull()) return wifi_net->signalStrength(); } } } } return -1; } case ITEM_CONNECTION_LEAF: //TODO: implement return -1; case ITEM_WIFINET_LEAF: return d->mWifiNets[index.row()]->signalStrength(); } return QVariant{}; } template <> QVariant NmModel::dataRole<NmModel::ConnectionUuidRole>(const QModelIndex & index) const { switch (static_cast<ItemId>(index.internalId())) { case ITEM_ROOT: case ITEM_ACTIVE: case ITEM_CONNECTION: case ITEM_DEVICE: case ITEM_DEVICE_LEAF: case ITEM_WIFINET: case ITEM_WIFINET_LEAF: return QVariant{}; case ITEM_ACTIVE_LEAF: return d->mActiveConns[index.row()]->uuid(); case ITEM_CONNECTION_LEAF: return d->mConnections[index.row()]->uuid(); } return QVariant{}; } template <> QVariant NmModel::dataRole<NmModel::ConnectionPathRole>(const QModelIndex & index) const { switch (static_cast<ItemId>(index.internalId())) { case ITEM_ROOT: case ITEM_ACTIVE: case ITEM_CONNECTION: case ITEM_DEVICE: case ITEM_DEVICE_LEAF: case ITEM_WIFINET: case ITEM_WIFINET_LEAF: return QVariant{}; case ITEM_ACTIVE_LEAF: return d->mActiveConns[index.row()]->path(); case ITEM_CONNECTION_LEAF: return d->mConnections[index.row()]->path(); } return QVariant{}; } template <> QVariant NmModel::dataRole<NmModel::ActiveConnectionInfoRole>(const QModelIndex & index) const { NetworkManager::Device::Ptr dev; NetworkManager::ConnectionSettings::Ptr settings; switch (static_cast<ItemId>(index.internalId())) { case ITEM_ROOT: case ITEM_ACTIVE: case ITEM_CONNECTION: case ITEM_DEVICE: case ITEM_DEVICE_LEAF: case ITEM_WIFINET: case ITEM_WIFINET_LEAF: case ITEM_CONNECTION_LEAF: return QVariant{}; break; case ITEM_ACTIVE_LEAF: { auto const a_conn = d->mActiveConns[index.row()]; auto const dev_list = a_conn->devices(); //TODO: work with all devices?!? if (!dev_list.isEmpty()) dev = d->findDeviceUni(dev_list.first()); Q_ASSERT(!a_conn->connection().isNull()); settings = a_conn->connection()->settings(); } break; } //TODO: we probably shouldn't assemble a string information (with styling) here and leave it to the consumer QString info; QDebug str{&info}; str.noquote(); str.nospace(); if (!dev.isNull()) { auto m_enum = NetworkManager::Device::staticMetaObject.enumerator(NetworkManager::Device::staticMetaObject.indexOfEnumerator("Type")); QString hw_address = NmModel::tr("unknown", "hardware address"); QString security; int bit_rate = -1; switch (dev->type()) { case NetworkManager::Device::Adsl: break; case NetworkManager::Device::Bond: { auto spec_dev = dev->as<NetworkManager::BondDevice>(); hw_address = spec_dev->hwAddress(); } break; case NetworkManager::Device::Bridge: { auto spec_dev = dev->as<NetworkManager::BridgeDevice>(); hw_address = spec_dev->hwAddress(); } break; case NetworkManager::Device::Gre: break; case NetworkManager::Device::Generic: { auto spec_dev = dev->as<NetworkManager::GenericDevice>(); hw_address = spec_dev->hardwareAddress(); } break; case NetworkManager::Device::InfiniBand: { auto spec_dev = dev->as<NetworkManager::InfinibandDevice>(); hw_address = spec_dev->hwAddress(); } break; case NetworkManager::Device::MacVlan: case NetworkManager::Device::Modem: break; case NetworkManager::Device::Bluetooth: { auto spec_dev = dev->as<NetworkManager::BluetoothDevice>(); hw_address = spec_dev->hardwareAddress(); } break; case NetworkManager::Device::OlpcMesh: { auto spec_dev = dev->as<NetworkManager::OlpcMeshDevice>(); hw_address = spec_dev->hardwareAddress(); } break; case NetworkManager::Device::Team: { auto spec_dev = dev->as<NetworkManager::TeamDevice>(); hw_address = spec_dev->hwAddress(); } break; case NetworkManager::Device::Tun: case NetworkManager::Device::Veth: break; case NetworkManager::Device::Vlan: { auto spec_dev = dev->as<NetworkManager::VlanDevice>(); hw_address = spec_dev->hwAddress(); } break; case NetworkManager::Device::Ethernet: { auto spec_dev = dev->as<NetworkManager::WiredDevice>(); Q_ASSERT(nullptr != spec_dev); hw_address = spec_dev->hardwareAddress(); bit_rate = spec_dev->bitRate(); } break; case NetworkManager::Device::Wifi: { auto spec_dev = dev->as<NetworkManager::WirelessDevice>(); Q_ASSERT(nullptr != spec_dev); hw_address = spec_dev->hardwareAddress(); bit_rate = spec_dev->bitRate(); NetworkManager::Setting::Ptr setting = settings->setting(NetworkManager::Setting::WirelessSecurity); if (!setting.isNull()) { QVariantMap const map = setting->toMap(); if (map.contains(QLatin1String(NM_SETTING_WIRELESS_SECURITY_KEY_MGMT))) security = map.value(QLatin1String(NM_SETTING_WIRELESS_SECURITY_KEY_MGMT)).toString(); } } break; case NetworkManager::Device::Wimax: //Wimax support was dropped in network manager 1.2.0 //we should never get here in runtime with nm >= 1.2.0 { auto spec_dev = dev->as<NetworkManager::WimaxDevice>(); Q_ASSERT(nullptr != spec_dev); hw_address = spec_dev->hardwareAddress(); //bit_rate = spec_dev->bitRate(); } break; case NetworkManager::Device::UnknownType: case NetworkManager::Device::Unused1: case NetworkManager::Device::Unused2: break; } str << QStringLiteral("<table>") << QStringLiteral("<tr><td colspan='2'><big><strong>") << NmModel::tr("General", "Active connection information") << QStringLiteral("</strong></big></td></tr>") << QStringLiteral("<tr><td><strong>") << NmModel::tr("Interface", "Active connection information") << QStringLiteral("</strong>: </td><td>") << m_enum.valueToKey(dev->type()) << QStringLiteral(" (") << dev->interfaceName() << QStringLiteral(")</td></tr>") << QStringLiteral("<tr><td><strong>") << NmModel::tr("Hardware Address", "Active connection information") << QStringLiteral("</strong>: </td><td>") << hw_address << QStringLiteral("</td></tr>") << QStringLiteral("<tr><td><strong>") << NmModel::tr("Driver", "Active connection information") << QStringLiteral("</strong>: </td><td>") << dev->driver() << QStringLiteral("</td></tr>") << QStringLiteral("<tr><td><strong>") << NmModel::tr("Speed", "Active connection information") << QStringLiteral("</strong>: </td><td>"); if (0 <= bit_rate) str << bit_rate << NmModel::tr(" Kb/s"); else str << NmModel::tr("unknown", "Speed"); str << QStringLiteral("</td></tr>"); if (!security.isEmpty()) { str << QStringLiteral("<tr><td><strong>") << NmModel::tr("Security", "Active connection information") << QStringLiteral("</strong>: </td><td>") << security << QStringLiteral("</td></tr>"); } //IP4/6 QString const ip4 = NmModel::tr("IPv4", "Active connection information"); QString const ip6 = NmModel::tr("IPv6", "Active connection information"); for (auto const & ip : { std::make_tuple(ip4, dev->ipV4Config()) , std::make_tuple(ip6, dev->ipV6Config()) }) { NetworkManager::IpConfig ip_config = std::get<1>(ip); if (ip_config.isValid()) { str << QStringLiteral("<tr/><tr><td colspan='2'><big><strong>") << std::get<0>(ip) << QStringLiteral("</strong></big></td></tr>"); int i = 1; for (QNetworkAddressEntry const & address : ip_config.addresses()) { QString suffix = (i > 1 ? QString{"(%1)"}.arg(i) : QString{}); str << QStringLiteral("<tr><td><strong>") << NmModel::tr("IP Address", "Active connection information") << suffix << QStringLiteral("</strong>: </td><td>") << address.ip().toString() << QStringLiteral("</td></tr>") << QStringLiteral("<tr><td><strong>") << NmModel::tr("Subnet Mask", "Active connection information") << suffix << QStringLiteral("</strong>: </td><td>") << address.netmask().toString() << QStringLiteral("</td></tr>") ; ++i; } QString const gtw = ip_config.gateway(); if (!gtw.isEmpty()) { str << QStringLiteral("<tr><td><strong>") << NmModel::tr("Default route", "Active connection information") << QStringLiteral("</strong>: </td><td>") << ip_config.gateway() << QStringLiteral("</td></tr>"); } i = 0; for (auto const & nameserver : ip_config.nameservers()) { str << QStringLiteral("<tr><td><strong>") << NmModel::tr("DNS(%1)", "Active connection information").arg(++i) << QStringLiteral("</strong>: </td><td>") << nameserver.toString() << QStringLiteral("</td></tr>"); } } } str << QStringLiteral("</table>"); } return info; } template <> QVariant NmModel::dataRole<NmModel::IconTypeRole>(const QModelIndex & index) const { switch (static_cast<ItemId>(index.internalId())) { case ITEM_ROOT: case ITEM_ACTIVE: case ITEM_CONNECTION: case ITEM_DEVICE: case ITEM_WIFINET: return -1; case ITEM_ACTIVE_LEAF: case ITEM_CONNECTION_LEAF: case ITEM_DEVICE_LEAF: { auto type = static_cast<NetworkManager::ConnectionSettings::ConnectionType>(dataRole<ConnectionTypeRole>(index).toInt()); auto state = static_cast<NetworkManager::ActiveConnection::State>(dataRole<ActiveConnectionStateRole>(index).toInt()); //TODO other types? switch (type) { case NetworkManager::ConnectionSettings::Wireless: case NetworkManager::ConnectionSettings::Wimax: if (0 > state) return icons::NETWORK_WIFI_DISCONNECTED; switch (state) { case NetworkManager::ActiveConnection::Activating: return icons::NETWORK_WIFI_ACQUIRING; case NetworkManager::ActiveConnection::Activated: return icons::wifiSignalIcon(dataRole<SignalRole>(index).toInt()); case NetworkManager::ActiveConnection::Unknown: case NetworkManager::ActiveConnection::Deactivating: case NetworkManager::ActiveConnection::Deactivated: return icons::NETWORK_WIFI_DISCONNECTED; } break; case NetworkManager::ConnectionSettings::Vpn: return icons::NETWORK_VPN; default: return NetworkManager::ActiveConnection::Activated == state ? icons::NETWORK_WIRED : icons::NETWORK_WIRED_DISCONNECTED; } } case ITEM_WIFINET_LEAF: return icons::wifiSignalIcon(d->mWifiNets[index.row()]->signalStrength()); } return QVariant{}; } template <> QVariant NmModel::dataRole<NmModel::IconRole>(const QModelIndex & index) const { return icons::getIcon(static_cast<icons::Icon>(dataRole<IconTypeRole>(index).toInt())); } QVariant NmModel::data(const QModelIndex &index, int role) const { //qCDebug(NM_TRAY) << __FUNCTION__ << index << role; Q_ASSERT(isValidDataIndex(index)); QVariant ret; if (index.isValid()) switch (role) { case ItemTypeRole: ret = dataRole<ItemTypeRole>(index); break; case Qt::DisplayRole: case NameRole: ret = dataRole<NameRole>(index); break; case ConnectionTypeRole: ret = dataRole<ConnectionTypeRole>(index); break; case ConnectionTypeStringRole: ret = dataRole<ConnectionTypeStringRole>(index); break; case ActiveConnectionStateRole: ret = dataRole<ActiveConnectionStateRole>(index); break; case ActiveConnectionMasterRole: ret = dataRole<ActiveConnectionMasterRole>(index); break; case ActiveConnectionDevicesRole: ret = dataRole<ActiveConnectionDevicesRole>(index); break; case SignalRole: ret = dataRole<SignalRole>(index); break; case ConnectionUuidRole: ret = dataRole<ConnectionUuidRole>(index); break; case ConnectionPathRole: ret = dataRole<ConnectionPathRole>(index); break; case ActiveConnectionInfoRole: ret = dataRole<ActiveConnectionInfoRole>(index); break; case IconTypeRole: ret = dataRole<IconTypeRole>(index); break; case Qt::DecorationRole: case IconRole: ret = dataRole<IconRole>(index); break; case IconSecurityTypeRole: ret = dataRole<IconSecurityTypeRole>(index); break; case IconSecurityRole: ret = dataRole<IconSecurityRole>(index); break; default: ret = QVariant{}; break; } //qCDebug(NM_TRAY) << __FUNCTION__ << "ret" << index << role << ret; return ret; } QModelIndex NmModel::index(int row, int column, const QModelIndex &parent/* = QModelIndex()*/) const { //qCDebug(NM_TRAY) << __FUNCTION__ << row << column << parent; if (!hasIndex(row, column, parent)) return QModelIndex{}; const int id = parent.internalId(); ItemId int_id; if (!parent.isValid()) { Q_ASSERT(0 == row && 0 == column); int_id = ITEM_ROOT; } else if (ITEM_ROOT == id) { Q_ASSERT(4 > row && 0 == column); switch (row) { case 0: int_id = ITEM_ACTIVE; break; case 1: int_id = ITEM_CONNECTION; break; case 2: int_id = ITEM_DEVICE; break; case 3: int_id = ITEM_WIFINET; break; } } else if (ITEM_ACTIVE == id) { Q_ASSERT(d->mActiveConns.size() > row); int_id = ITEM_ACTIVE_LEAF; } else if (ITEM_CONNECTION == id) { Q_ASSERT(d->mConnections.size() > row); int_id = ITEM_CONNECTION_LEAF; } else if (ITEM_DEVICE == id) { Q_ASSERT(d->mDevices.size() > row); int_id = ITEM_DEVICE_LEAF; } else if (ITEM_WIFINET == id) { Q_ASSERT(d->mWifiNets.size() > row); int_id = ITEM_WIFINET_LEAF; } else { Q_ASSERT(false); //should never get here return QModelIndex{}; } //qCDebug(NM_TRAY) << __FUNCTION__ << "ret: " << row << column << int_id; return createIndex(row, column, int_id); } QModelIndex NmModel::parent(const QModelIndex &index) const { QModelIndex parent_i; if (index.isValid()) { switch (static_cast<ItemId>(index.internalId())) { case ITEM_ROOT: break; case ITEM_ACTIVE: case ITEM_CONNECTION: case ITEM_DEVICE: case ITEM_WIFINET: parent_i = createIndex(0, 0, ITEM_ROOT); break; case ITEM_ACTIVE_LEAF: parent_i = createIndex(0, 0, ITEM_ACTIVE); break; case ITEM_CONNECTION_LEAF: parent_i = createIndex(1, 0, ITEM_CONNECTION); break; case ITEM_DEVICE_LEAF: parent_i = createIndex(2, 0, ITEM_DEVICE); break; case ITEM_WIFINET_LEAF: parent_i = createIndex(3, 0, ITEM_WIFINET); break; } } //qCDebug(NM_TRAY) << __FUNCTION__ << index << parent_i; return parent_i; } QModelIndex NmModel::indexTypeRoot(ItemType type) const { QModelIndex i; switch (type) { case HelperType: i = createIndex(0, 0, ITEM_ROOT); break; case ActiveConnectionType: i = createIndex(0, 0, ITEM_ACTIVE); break; case ConnectionType: i = createIndex(1, 0, ITEM_CONNECTION); break; case DeviceType: i = createIndex(2, 0, ITEM_DEVICE); break; case WifiNetworkType: i = createIndex(3, 0, ITEM_WIFINET); break; } return i; } void NmModel::activateConnection(QModelIndex const & index) { ItemId id = static_cast<ItemId>(index.internalId()); if (!isValidDataIndex(index) || (ITEM_CONNECTION_LEAF != id && ITEM_WIFINET_LEAF != id)) { //TODO: in what form should we output the warning messages qCWarning(NM_TRAY).noquote() << "got invalid index for connection activation" << index; return; } QString conn_uni, dev_uni; QString conn_name, dev_name; QString spec_object; NMVariantMapMap map_settings; bool add_connection = false; switch (id) { case ITEM_CONNECTION_LEAF: { auto const & conn = d->mConnections[index.row()]; conn_uni = conn->path(); conn_name = conn->name(); if (NetworkManager::ConnectionSettings::Vpn == conn->settings()->connectionType()) { spec_object = dev_uni = QStringLiteral("/"); /* // find first non-vpn active connection const auto act_i = std::find_if(d->mActiveConns.cbegin(), d->mActiveConns.cend(), [] (NetworkManager::ActiveConnection::Ptr const & conn) -> bool { return nullptr != dynamic_cast<NetworkManager::VpnConnection const *>(conn.data()); }); if (act_i != d->mActiveConns.cend() && !(*act_i)->devices().empty()) { dev_uni = (*act_i)->devices().front(); spec_object = (*act_i)->path(); } */ } else { dev_name = conn->settings()->interfaceName(); for (auto const & dev : d->mDevices) for (auto const & dev_conn : dev->availableConnections()) if (dev_conn == conn) { dev_uni = dev->uni(); dev_name = dev->interfaceName(); } if (dev_uni.isEmpty() && !dev_name.isEmpty()) { auto dev = d->findDeviceInterface(dev_name); if (!dev.isNull()) dev_uni = dev->uni(); } } if (dev_uni.isEmpty()) { //TODO: in what form should we output the warning messages qCWarning(NM_TRAY).noquote() << QStringLiteral("can't find device '%1' to activate connection '%2' on").arg(dev_name).arg(conn->name()); return; } } break; case ITEM_WIFINET_LEAF: { auto const & net = d->mWifiNets[index.row()]; auto access_point = net->referenceAccessPoint(); Q_ASSERT(!access_point.isNull()); dev_uni = net->device(); auto dev = d->findDeviceUni(dev_uni); Q_ASSERT(!dev.isNull()); auto spec_dev = dev->as<NetworkManager::WirelessDevice>(); Q_ASSERT(nullptr != spec_dev); conn_uni = access_point->uni(); conn_name = access_point->ssid(); //find the device name NetworkManager::Connection::Ptr conn; dev_name = dev->interfaceName(); for (auto const & dev_conn : dev->availableConnections()) if (dev_conn->settings()->id() == conn_name) { conn = dev_conn; } if (conn.isNull()) { //TODO: in what form should we output the warning messages qCWarning(NM_TRAY).noquote() << QStringLiteral("can't find connection for '%1' on device '%2', will create new...").arg(conn_name).arg(dev_name); add_connection = true; spec_object = conn_uni; NetworkManager::WirelessSecurityType sec_type = NetworkManager::findBestWirelessSecurity(spec_dev->wirelessCapabilities() , true, (spec_dev->mode() == NetworkManager::WirelessDevice::Adhoc) , access_point->capabilities(), access_point->wpaFlags(), access_point->rsnFlags()); switch (sec_type) { case NetworkManager::UnknownSecurity: qCWarning(NM_TRAY).noquote() << QStringLiteral("unknown security to use for '%1'").arg(conn_name); case NetworkManager::NoneSecurity: //nothing to do break; case NetworkManager::WpaPsk: case NetworkManager::Wpa2Psk: if (NetworkManager::ConnectionSettings::Ptr settings = assembleWpaXPskSettings(access_point)) { map_settings = settings->toMap(); } else { qCWarning(NM_TRAY).noquote() << QStringLiteral("connection settings assembly for '%1' failed, abandoning activation...") .arg(conn_name); return; } break; //TODO: other types... } } else { conn_uni = conn->path(); } } break; default: Q_ASSERT(false); } qCDebug(NM_TRAY) << __FUNCTION__ << conn_uni << dev_uni << conn_name << dev_name << spec_object; //TODO: check vpn type etc.. QDBusPendingCallWatcher * watcher; if (add_connection) watcher = new QDBusPendingCallWatcher{NetworkManager::addAndActivateConnection(map_settings, dev_uni, spec_object), this}; else watcher = new QDBusPendingCallWatcher{NetworkManager::activateConnection(conn_uni, dev_uni, spec_object), this}; connect(watcher, &QDBusPendingCallWatcher::finished, [conn_name, dev_name] (QDBusPendingCallWatcher * watcher) { if (watcher->isError() || !watcher->isValid()) { //TODO: in what form should we output the warning messages qCWarning(NM_TRAY).noquote() << QStringLiteral("activation of connection '%1' on interface '%2' failed: %3").arg(conn_name) .arg(dev_name).arg(watcher->error().message()); } watcher->deleteLater(); }); } void NmModel::deactivateConnection(QModelIndex const & index) { ItemId id = static_cast<ItemId>(index.internalId()); if (!isValidDataIndex(index) || ITEM_ACTIVE_LEAF != id) { //TODO: in what form should we output the warning messages qCWarning(NM_TRAY).noquote() << "got invalid index for connection deactivation" << index; return; } auto const & active = d->mActiveConns[index.row()]; qCDebug(NM_TRAY) << __FUNCTION__ << active->path(); QDBusPendingReply<> reply = NetworkManager::deactivateConnection(active->path()); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); connect(watcher, &QDBusPendingCallWatcher::finished, [active] (QDBusPendingCallWatcher * watcher) { if (watcher->isError() || !watcher->isValid()) { //TODO: in what form should we output the warning messages qCWarning(NM_TRAY).noquote() << QStringLiteral("deactivation of connection '%1' failed: %3").arg(active->connection()->name()) .arg(watcher->error().message()); } watcher->deleteLater(); }); } 07070117A6746B000081A40000000200000002000000015A3D9FC900000B68000000FD0000001000000000000000000000002B00000000nm-tray-0.3.0.19~git.29290df/src/nmmodel.h/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #if !defined(NMMODEL_H) #define NMMODEL_H #include <QAbstractItemModel> class NmModelPrivate; class NmModel : public QAbstractItemModel { Q_OBJECT public: enum ItemType { HelperType , ActiveConnectionType , ConnectionType , DeviceType , WifiNetworkType }; enum ItemRole { ItemTypeRole = Qt::UserRole + 1 , NameRole , IconTypeRole , IconRole , ConnectionTypeRole , ActiveConnectionTypeRole = ConnectionTypeRole , ConnectionTypeStringRole , ActiveConnectionTypeStringRole = ConnectionTypeStringRole , ConnectionUuidRole , ActiveConnectionUuidRole = ConnectionUuidRole , ConnectionPathRole , ActiveConnectionPathRole = ConnectionPathRole , ActiveConnectionInfoRole , ActiveConnectionStateRole , ActiveConnectionMasterRole , ActiveConnectionDevicesRole , IconSecurityTypeRole , IconSecurityRole , SignalRole }; public: explicit NmModel(QObject * parent = nullptr); ~NmModel(); //QAbstractItemModel methods virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override; virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; virtual QModelIndex parent(const QModelIndex &index) const override; virtual QVariant data(const QModelIndex &index, int role) const override; QModelIndex indexTypeRoot(ItemType type) const; public Q_SLOTS: //NetworkManager management methods void activateConnection(QModelIndex const & index); void deactivateConnection(QModelIndex const & index); private: bool isValidDataIndex(const QModelIndex & index) const; template <int role> QVariant dataRole(const QModelIndex & index) const; private: QScopedPointer<NmModelPrivate> d; }; #endif //NMMODEL_H 07070117A6746C000081A40000000200000002000000015A3D9FC9000010D2000000FD0000001000000000000000000000002D00000000nm-tray-0.3.0.19~git.29290df/src/nmmodel_p.h/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #if !defined(NMMODEL_P_H) #define NMMODEL_P_H #include <NetworkManagerQt/Manager> #include <NetworkManagerQt/Settings> #include <NetworkManagerQt/WirelessDevice> class NmModelPrivate : public QObject { Q_OBJECT public: NmModelPrivate(); ~NmModelPrivate(); void removeActiveConnection(int pos); void clearActiveConnections(); void insertActiveConnections(); void addActiveConnection(NetworkManager::ActiveConnection::Ptr conn); void removeConnection(int pos); void clearConnections(); void insertConnections(); void addConnection(NetworkManager::Connection::Ptr conn); void removeDevice(int pos); void clearDevices(); void insertDevices(); void addDevice(NetworkManager::Device::Ptr conn); void removeWifiNetwork(int pos); void clearWifiNetworks(); void insertWifiNetworks(); void addWifiNetwork(NetworkManager::WirelessNetwork::Ptr net); NetworkManager::ActiveConnection::Ptr findActiveConnection(QString const & path); template <typename Predicate> NetworkManager::Device::Ptr findDevice(Predicate const & pred); NetworkManager::Device::Ptr findDeviceUni(QString const & uni); NetworkManager::Device::Ptr findDeviceInterface(QString const & interfaceName); NetworkManager::WirelessNetwork::Ptr findWifiNetwork(QString const & ssid, QString const & devUni); Q_SIGNALS: void connectionAdd(NetworkManager::Connection::Ptr conn); void connectionUpdate(NetworkManager::Connection * conn); void connectionRemove(NetworkManager::Connection * conn); void activeConnectionAdd(NetworkManager::ActiveConnection::Ptr conn); void activeConnectionUpdate(NetworkManager::ActiveConnection * conn); void activeConnectionRemove(NetworkManager::ActiveConnection * conn); void activeConnectionsReset(); void deviceAdd(NetworkManager::Device::Ptr dev); void deviceUpdate(NetworkManager::Device * dev); void deviceRemove(NetworkManager::Device * dev); void wifiNetworkAdd(NetworkManager::Device * dev, QString const & ssid); void wifiNetworkUpdate(NetworkManager::WirelessNetwork * net); void wifiNetworkRemove(NetworkManager::Device * dev, QString const & ssid); private Q_SLOT: //connection void onConnectionUpdated(); void onConnectionRemoved(); //active connection void onActiveConnectionUpdated(); //device void onDeviceUpdated(); void onWifiNetworkAppeared(QString const & ssid); void onWifiNetworkDisappeared(QString const & ssid); //wifi network void onWifiNetworkUpdated(); //notifier void onDeviceAdded(QString const & uni); void onDeviceRemoved(QString const & uni); void onActiveConnectionAdded(QString const & path); void onActiveConnectionRemoved(QString const & path); void onActiveConnectionsChanged(); //settings notifier void onConnectionAdded(QString const & path); void onConnectionRemoved(QString const & path); public: NetworkManager::ActiveConnection::List mActiveConns; NetworkManager::Connection::List mConnections; NetworkManager::Device::List mDevices; NetworkManager::WirelessNetwork::List mWifiNets; }; enum ItemId { ITEM_ROOT = 0x0 , ITEM_ACTIVE = 0x01 , ITEM_ACTIVE_LEAF = 0x11 , ITEM_CONNECTION = 0x2 , ITEM_CONNECTION_LEAF = 0x21 , ITEM_DEVICE = 0x3 , ITEM_DEVICE_LEAF = 0x31 , ITEM_WIFINET = 0x4 , ITEM_WIFINET_LEAF = 0x41 }; #endif //NMMODEL_P_H 07070117A6746D000081A40000000200000002000000015A3D9FC900002984000000FD0000001000000000000000000000002D00000000nm-tray-0.3.0.19~git.29290df/src/nmproxy.cpp/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #include "nmproxy.h" #include "log.h" void NmProxy::setSourceModel(QAbstractItemModel * sourceModel) { //we operate only on our known model Q_ASSERT(sourceModel->metaObject() == &NmModel::staticMetaObject); Q_ASSERT(root.isValid()); beginResetModel(); if (nullptr != this->sourceModel()) { disconnect(this->sourceModel(), &QAbstractItemModel::dataChanged, this, &NmProxy::onSourceDataChanged); disconnect(this->sourceModel(), &QAbstractItemModel::headerDataChanged, this, &NmProxy::onSourceHeaderDataChanged); disconnect(this->sourceModel(), &QAbstractItemModel::rowsAboutToBeInserted, this, &NmProxy::onSourceRowsAboutToBeInserted); disconnect(this->sourceModel(), &QAbstractItemModel::rowsInserted, this, &NmProxy::onSourceRowsInserted); disconnect(this->sourceModel(), &QAbstractItemModel::rowsAboutToBeRemoved, this, &NmProxy::onSourceRowsAboutToBeRemoved); disconnect(this->sourceModel(), &QAbstractItemModel::rowsRemoved, this, &NmProxy::onSourceRowsRemoved); disconnect(this->sourceModel(), &QAbstractItemModel::columnsAboutToBeInserted, this, &NmProxy::onSourceColumnsAboutToBeInserted); disconnect(this->sourceModel(), &QAbstractItemModel::columnsInserted, this, &NmProxy::onSourceColumnsInserted); disconnect(this->sourceModel(), &QAbstractItemModel::columnsAboutToBeRemoved, this, &NmProxy::onSourceColumnsAboutToBeRemoved); disconnect(this->sourceModel(), &QAbstractItemModel::columnsRemoved, this, &NmProxy::onSourceColumnsRemoved); disconnect(this->sourceModel(), &QAbstractItemModel::modelAboutToBeReset, this, &NmProxy::onSourceModelAboutToBeReset); disconnect(this->sourceModel(), &QAbstractItemModel::modelReset, this, &NmProxy::onSourceModelReset); disconnect(this->sourceModel(), &QAbstractItemModel::rowsAboutToBeMoved, this, &NmProxy::onSourceRowsAboutToBeMoved); disconnect(this->sourceModel(), &QAbstractItemModel::rowsMoved, this, &NmProxy::onSourceRowsMoved); disconnect(this->sourceModel(), &QAbstractItemModel::columnsAboutToBeMoved, this, &NmProxy::onSourceColumnsAboutToBeMoved); disconnect(this->sourceModel(), &QAbstractItemModel::columnsMoved, this, &NmProxy::onSourceColumnsMoved); } QAbstractProxyModel::setSourceModel(sourceModel); connect(sourceModel, &QAbstractItemModel::dataChanged, this, &NmProxy::onSourceDataChanged); connect(sourceModel, &QAbstractItemModel::headerDataChanged, this, &NmProxy::onSourceHeaderDataChanged); connect(sourceModel, &QAbstractItemModel::rowsAboutToBeInserted, this, &NmProxy::onSourceRowsAboutToBeInserted); connect(sourceModel, &QAbstractItemModel::rowsInserted, this, &NmProxy::onSourceRowsInserted); connect(sourceModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, &NmProxy::onSourceRowsAboutToBeRemoved); connect(sourceModel, &QAbstractItemModel::rowsRemoved, this, &NmProxy::onSourceRowsRemoved); connect(sourceModel, &QAbstractItemModel::columnsAboutToBeInserted, this, &NmProxy::onSourceColumnsAboutToBeInserted); connect(sourceModel, &QAbstractItemModel::columnsInserted, this, &NmProxy::onSourceColumnsInserted); connect(sourceModel, &QAbstractItemModel::columnsAboutToBeRemoved, this, &NmProxy::onSourceColumnsAboutToBeRemoved); connect(sourceModel, &QAbstractItemModel::columnsRemoved, this, &NmProxy::onSourceColumnsRemoved); connect(sourceModel, &QAbstractItemModel::modelAboutToBeReset, this, &NmProxy::onSourceModelAboutToBeReset); connect(sourceModel, &QAbstractItemModel::modelReset, this, &NmProxy::onSourceModelReset); connect(sourceModel, &QAbstractItemModel::rowsAboutToBeMoved, this, &NmProxy::onSourceRowsAboutToBeMoved); connect(sourceModel, &QAbstractItemModel::rowsMoved, this, &NmProxy::onSourceRowsMoved); connect(sourceModel, &QAbstractItemModel::columnsAboutToBeMoved, this, &NmProxy::onSourceColumnsAboutToBeMoved); connect(sourceModel, &QAbstractItemModel::columnsMoved, this, &NmProxy::onSourceColumnsMoved); endResetModel(); } void NmProxy::setNmModel(NmModel * model, NmModel::ItemType shownType) { root = model->indexTypeRoot(shownType); setSourceModel(model); //qCDebug(NM_TRAY) << __FUNCTION__ << model->indexTypeRoot(shownType) << "->" << root; } QModelIndex NmProxy::index(int row, int column, const QModelIndex & proxyParent) const { QModelIndex i; if (hasIndex(row, column, proxyParent)) i = createIndex(row, column); //qCDebug(NM_TRAY) << __FUNCTION__ << row << column << proxyParent << "->" << i; return i; } QModelIndex NmProxy::parent(const QModelIndex &/*proxyIndex*/) const { //showing only one level/list: leaf -> invalid, root -> invalid QModelIndex i; //qCDebug(NM_TRAY) << __FUNCTION__ << proxyIndex << "->" << i; return i; } int NmProxy::rowCount(const QModelIndex &proxyParent) const { //showing only one level/list: leaf -> source root rowcount, root -> 0 if (proxyParent.isValid()) return 0; else return sourceModel()->rowCount(root); } int NmProxy::columnCount(const QModelIndex &proxyParent) const { return sourceModel()->columnCount(mapToSource(proxyParent)); } void NmProxy::activateConnection(QModelIndex const & index) const { qobject_cast<NmModel *>(sourceModel())->activateConnection(mapToSource(index)); } void NmProxy::deactivateConnection(QModelIndex const & index) const { qobject_cast<NmModel *>(sourceModel())->deactivateConnection(mapToSource(index)); } QModelIndex NmProxy::mapToSource(const QModelIndex & proxyIndex) const { QModelIndex i; if (proxyIndex.isValid()) i = sourceModel()->index(proxyIndex.row(), proxyIndex.column(), root); //qCDebug(NM_TRAY) << __FUNCTION__ << proxyIndex << "->" << i; return i; } QModelIndex NmProxy::mapFromSource(const QModelIndex & sourceIndex) const { QModelIndex i; if (sourceIndex.isValid() && root != sourceIndex) i = createIndex(sourceIndex.row(), sourceIndex.column()); //qCDebug(NM_TRAY) << __FUNCTION__ << sourceIndex << "->" << i; return i; } void NmProxy::onSourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) { if (root == topLeft.parent()) emit dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight), roles); } void NmProxy::onSourceHeaderDataChanged(Qt::Orientation orientation, int first, int last) { emit headerDataChanged(orientation, first, last); } void NmProxy::onSourceRowsAboutToBeInserted(const QModelIndex &parent, int first, int last) { if (root == parent) beginInsertRows(mapFromSource(parent), first, last); } void NmProxy::onSourceRowsInserted(const QModelIndex &parent, int, int) { if (root == parent) endInsertRows(); } void NmProxy::onSourceRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last) { if (root == parent) beginRemoveRows(mapFromSource(parent), first, last); } void NmProxy::onSourceRowsRemoved(const QModelIndex &parent, int, int) { if (root == parent) endRemoveRows(); } void NmProxy::onSourceColumnsAboutToBeInserted(const QModelIndex &parent, int first, int last) { if (root == parent) beginInsertColumns(mapFromSource(parent), first, last); } void NmProxy::onSourceColumnsInserted(const QModelIndex &parent, int, int) { if (root == parent) endInsertColumns(); } void NmProxy::onSourceColumnsAboutToBeRemoved(const QModelIndex &parent, int first, int last) { if (root == parent) beginRemoveColumns(mapFromSource(parent), first, last); } void NmProxy::onSourceColumnsRemoved(const QModelIndex &parent, int, int) { if (root == parent) endRemoveColumns(); } void NmProxy::onSourceModelAboutToBeReset() { beginResetModel(); } void NmProxy::onSourceModelReset() { endResetModel(); } void NmProxy::onSourceRowsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) { if (root == sourceParent) { if (root == destinationParent) beginMoveRows(mapFromSource(sourceParent), sourceStart, sourceEnd, destinationParent, destinationRow); else beginRemoveRows(mapFromSource(sourceParent), sourceStart, sourceEnd); } else if (root == destinationParent) beginInsertRows(mapFromSource(destinationParent), destinationRow, destinationRow + (sourceEnd - sourceStart)); } void NmProxy::onSourceRowsMoved( const QModelIndex &sourceParent, int, int, const QModelIndex &destinationParent, int) { if (root == sourceParent) { if (root == destinationParent) endMoveRows(); else endRemoveRows(); } else if (root == destinationParent) endInsertRows(); } void NmProxy::onSourceColumnsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn) { if (root == sourceParent) { if (root == destinationParent) beginMoveColumns(mapFromSource(sourceParent), sourceStart, sourceEnd, destinationParent, destinationColumn); else beginRemoveColumns(mapFromSource(sourceParent), sourceStart, sourceEnd); } else if (root == destinationParent) beginInsertColumns(mapFromSource(destinationParent), destinationColumn, destinationColumn + (sourceEnd - sourceStart)); } void NmProxy::onSourceColumnsMoved( const QModelIndex &sourceParent, int, int, const QModelIndex &destinationParent, int) { if (root == sourceParent) { if (root == destinationParent) endMoveColumns(); else endRemoveColumns(); } else if (root == destinationParent) endInsertColumns(); } 07070117A6746E000081A40000000200000002000000015A3D9FC900000D79000000FD0000001000000000000000000000002B00000000nm-tray-0.3.0.19~git.29290df/src/nmproxy.h/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #if !defined(NMPROXY_H) #define NMPROXY_H #include <QAbstractProxyModel> #include "nmmodel.h" class NmProxy : public QAbstractProxyModel { Q_OBJECT public: using QAbstractProxyModel::QAbstractProxyModel; virtual void setSourceModel(QAbstractItemModel * sourceModel) override; void setNmModel(NmModel * model, NmModel::ItemType shownType); virtual QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const override; virtual QModelIndex parent(const QModelIndex &index) const override; virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override; void activateConnection(QModelIndex const & index) const; void deactivateConnection(QModelIndex const & index) const; protected: virtual QModelIndex mapToSource(const QModelIndex & proxyIndex) const override; virtual QModelIndex mapFromSource(const QModelIndex & sourceIndex) const override; private Q_SLOTS: void onSourceDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>()); void onSourceHeaderDataChanged(Qt::Orientation orientation, int first, int last); void onSourceRowsAboutToBeInserted(const QModelIndex &parent, int first, int last); void onSourceRowsInserted(const QModelIndex &parent, int first, int last); void onSourceRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last); void onSourceRowsRemoved(const QModelIndex &parent, int first, int last); void onSourceColumnsAboutToBeInserted(const QModelIndex &parent, int first, int last); void onSourceColumnsInserted(const QModelIndex &parent, int first, int last); void onSourceColumnsAboutToBeRemoved(const QModelIndex &parent, int first, int last); void onSourceColumnsRemoved(const QModelIndex &parent, int first, int last); void onSourceModelAboutToBeReset(); void onSourceModelReset(); void onSourceRowsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow); void onSourceRowsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row); void onSourceColumnsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn); void onSourceColumnsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column); private: QModelIndex root; }; #endif //NMPROXY_H 07070117A6746F000081A40000000200000002000000015A3D9FC900000676000000FD0000001000000000000000000000002F00000000nm-tray-0.3.0.19~git.29290df/src/translate.cpp/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #include <QCoreApplication> #include <QLocale> #include <QTranslator> #include <QLibraryInfo> #if !defined(TRANSLATION_DIR) #define TRANSLATION_DIR "/usr/share/nm-tray" #endif void translate() { const QString locale = QLocale::system().name(); QTranslator * qt_trans = new QTranslator{qApp}; if (qt_trans->load(QLatin1String("qt_") + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) qApp->installTranslator(qt_trans); else delete qt_trans; QString trans_dir = qgetenv("NM_TRAY_TRANSLATION_DIR").constData(); QTranslator * my_trans = new QTranslator{qApp}; if (my_trans->load(QLatin1String("nm-tray_") + locale, trans_dir.isEmpty() ? TRANSLATION_DIR : trans_dir)) qApp->installTranslator(my_trans); else delete my_trans; } Q_COREAPP_STARTUP_FUNCTION(translate) 07070117A67470000081A40000000200000002000000015A3D9FC900004044000000FD0000001000000000000000000000002A00000000nm-tray-0.3.0.19~git.29290df/src/tray.cpp/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #include "tray.h" #include <QSystemTrayIcon> #include <QMenu> #include <QMessageBox> #include <QApplication> #include <QPersistentModelIndex> #include <NetworkManagerQt/Manager> #include <NetworkManagerQt/WirelessDevice> #include "icons.h" #include "nmmodel.h" #include "nmproxy.h" #include "log.h" #include "dbus/org.freedesktop.Notifications.h" #include "nmlist.h" #include "connectioninfo.h" #include "windowmenu.h" // config keys static const QString ENABLE_NOTIFICATIONS = QStringLiteral("enableNotifications"); static const QString CONNECTIONS_EDITOR = QStringLiteral("connectionsEditor"); class TrayPrivate { public: TrayPrivate(); void updateState(QModelIndex const & index, bool removing); void primaryConnectionUpdate(); void setShown(QPersistentModelIndex const & index); void updateIcon(); void refreshIcon(); void openCloseDialog(QDialog * dialog); void notify(QModelIndex const & index, bool removing); public: QSystemTrayIcon mTrayIcon; QMenu mContextMenu; QTimer mStateTimer; QAction * mActEnableNetwork; QAction * mActEnableWifi; QAction * mActConnInfo; QAction * mActDebugInfo; NmModel mNmModel; NmProxy mActiveConnections; QPersistentModelIndex mPrimaryConnection; QPersistentModelIndex mShownConnection; QList<QPersistentModelIndex> mConnectionsToNotify; //!< just "created" connections to which notification wasn't sent yet icons::Icon mIconCurrent; icons::Icon mIcon2Show; QTimer mIconTimer; QScopedPointer<QDialog> mConnDialog; QScopedPointer<QDialog> mInfoDialog; org::freedesktop::Notifications mNotification; // configuration bool mEnableNotifications; //!< should info about connection establishment etc. be sent by org.freedesktop.Notifications }; TrayPrivate::TrayPrivate() : mNotification{QStringLiteral("org.freedesktop.Notifications"), QStringLiteral("/org/freedesktop/Notifications"), QDBusConnection::sessionBus()} { mActiveConnections.setNmModel(&mNmModel, NmModel::ActiveConnectionType); } void TrayPrivate::updateState(QModelIndex const & index, bool removing) { notify(index, removing); const auto state = static_cast<NetworkManager::ActiveConnection::State>(mActiveConnections.data(index, NmModel::ActiveConnectionStateRole).toInt()); const bool is_primary = mPrimaryConnection == index; //qCDebug(NM_TRAY) << __FUNCTION__ << index << removing << mActiveConnections.data(index, NmModel::NameRole) << mActiveConnections.data(index, NmModel::ConnectionUuidRole).toString() << is_primary << mActiveConnections.data(index, NmModel::ConnectionTypeRole).toInt() << state; if (removing || NetworkManager::ActiveConnection::Deactivated == state || NetworkManager::ActiveConnection::Deactivating == state) { if (is_primary) { mPrimaryConnection = QModelIndex{}; setShown(mPrimaryConnection); } else if (mShownConnection == index) { setShown(mPrimaryConnection); } } else { if (is_primary || NetworkManager::ActiveConnection::Activating == state) { setShown(index); } else if (mShownConnection == index) { setShown(mPrimaryConnection); } } //TODO: optimize this text assembly (to not do it every time)? if (mPrimaryConnection.isValid()) { mTrayIcon.setToolTip(Tray::tr("<pre>Connection <strong>%1</strong>(%2) active</pre>") .arg(mPrimaryConnection.data(NmModel::NameRole).toString()) .arg(mPrimaryConnection.data(NmModel::ActiveConnectionTypeStringRole).toString()) ); } else { mTrayIcon.setToolTip(Tray::tr("<pre>No active connection</pre>")); } } void TrayPrivate::primaryConnectionUpdate() { NetworkManager::ActiveConnection::Ptr prim_conn = NetworkManager::primaryConnection(); if (!prim_conn || !prim_conn->isValid()) { mPrimaryConnection = QModelIndex{}; setShown(mPrimaryConnection); return; } //qCDebug(NM_TRAY) << __FUNCTION__ << prim_conn->uuid(); QModelIndexList l = mActiveConnections.match(mActiveConnections.index(0, 0, QModelIndex{}), NmModel::ActiveConnectionUuidRole, prim_conn->uuid(), -1, Qt::MatchExactly); //qCDebug(NM_TRAY) << __FUNCTION__ << l.size(); //nothing to do if the connection not populated in model yet if (0 >= l.size()) return; Q_ASSERT(1 == l.size()); mPrimaryConnection = l.first(); updateState(mPrimaryConnection, false); } void TrayPrivate::setShown(QPersistentModelIndex const & index) { mShownConnection = index; mIcon2Show = mShownConnection.isValid() ? static_cast<icons::Icon>(mActiveConnections.data(mShownConnection, NmModel::IconTypeRole).toInt()) : icons::NETWORK_OFFLINE; //postpone setting the icon (for case we change the icon in till our event is finished) mIconTimer.start(); } void TrayPrivate::updateIcon() { if (mIconCurrent == mIcon2Show) return; mIconCurrent = mIcon2Show; refreshIcon(); } void TrayPrivate::refreshIcon() { //Note: the icons::getIcon chooses the right icon from list of possible candidates // -> we need to refresh the icon in case of icon theme change mTrayIcon.setIcon(icons::getIcon(mIconCurrent)); } void TrayPrivate::openCloseDialog(QDialog * dialog) { if (dialog->isHidden() || dialog->isMinimized()) { dialog->showNormal(); dialog->activateWindow(); dialog->raise(); } else dialog->close(); } void TrayPrivate::notify(QModelIndex const & index, bool removing) { if (!mEnableNotifications) { return; } QString summary, body; if (removing) { mConnectionsToNotify.removeOne(index); summary = Tray::tr("Connection lost"); body = Tray::tr("No longer connected to %1 '%2'."); } else { const int notif_i = mConnectionsToNotify.indexOf(index); // do nothing if not just added or the connection is not activated yet if (-1 == notif_i || NetworkManager::ActiveConnection::Activated != static_cast<NetworkManager::ActiveConnection::State>(mActiveConnections.data(index, NmModel::ActiveConnectionStateRole).toInt()) ) { return; } mConnectionsToNotify.removeAt(notif_i); // fire the notification only once summary = Tray::tr("Connection established"); body = Tray::tr("Now connected to %1 '%2'."); } // TODO: do somehow check the result? mNotification.Notify(Tray::tr("NetworkManager(nm-tray)") , 0 , icons::getIcon(static_cast<icons::Icon>(mActiveConnections.data(index, NmModel::IconTypeRole).toInt())).name() , summary , body.arg(mActiveConnections.data(index, NmModel::ConnectionTypeStringRole).toString()).arg(mActiveConnections.data(index, NmModel::NameRole).toString()) , {} , {} , -1); } Tray::Tray(QObject *parent/* = nullptr*/) : QObject{parent} , d{new TrayPrivate} { d->mEnableNotifications = QSettings{}.value(ENABLE_NOTIFICATIONS, true).toBool(); connect(&d->mTrayIcon, &QSystemTrayIcon::activated, this, &Tray::onActivated); //postpone the update in case of signals flood connect(&d->mStateTimer, &QTimer::timeout, this, &Tray::setActionsStates); d->mStateTimer.setSingleShot(true); d->mStateTimer.setInterval(200); d->mIconCurrent = static_cast<icons::Icon>(-1); d->setShown(QModelIndex{}); d->refreshIcon(); //force setting the icon instantly //postpone updating of the icon connect(&d->mIconTimer, &QTimer::timeout, [this] { d->updateIcon(); }); d->mIconTimer.setSingleShot(true); d->mIconTimer.setInterval(0); d->mActEnableNetwork = d->mContextMenu.addAction(Tray::tr("Enable Networking")); d->mActEnableWifi = d->mContextMenu.addAction(Tray::tr("Enable Wi-Fi")); d->mContextMenu.addSeparator(); QAction * enable_notifications = d->mContextMenu.addAction(Tray::tr("Enable notifications")); d->mContextMenu.addSeparator(); d->mActConnInfo = d->mContextMenu.addAction(QIcon::fromTheme(QStringLiteral("dialog-information")), Tray::tr("Connection information")); d->mActDebugInfo = d->mContextMenu.addAction(QIcon::fromTheme(QStringLiteral("dialog-information")), Tray::tr("Debug information")); connect(d->mContextMenu.addAction(QIcon::fromTheme(QStringLiteral("document-edit")), Tray::tr("Edit connections...")), &QAction::triggered , this, &Tray::onEditConnectionsTriggered); d->mContextMenu.addSeparator(); connect(d->mContextMenu.addAction(QIcon::fromTheme(QStringLiteral("help-about")), Tray::tr("About")), &QAction::triggered , this, &Tray::onAboutTriggered); connect(d->mContextMenu.addAction(QIcon::fromTheme(QStringLiteral("application-exit")), Tray::tr("Quit")), &QAction::triggered , this, &Tray::onQuitTriggered); //for listening on the QEvent::ThemeChange (is delivered only to QWidget objects) d->mContextMenu.installEventFilter(this); d->mActEnableNetwork->setCheckable(true); d->mActEnableWifi->setCheckable(true); enable_notifications->setCheckable(true); enable_notifications->setChecked(d->mEnableNotifications); connect(d->mActEnableNetwork, &QAction::triggered, [this] (bool checked) { NetworkManager::setNetworkingEnabled(checked); }); connect(d->mActEnableWifi, &QAction::triggered, [this] (bool checked) { NetworkManager::setWirelessEnabled(checked); }); connect(enable_notifications, &QAction::triggered, [this] (bool checked) { d->mEnableNotifications = checked; QSettings{}.setValue(ENABLE_NOTIFICATIONS, checked); }); connect(d->mActConnInfo, &QAction::triggered, [this] (bool ) { if (d->mInfoDialog.isNull()) { d->mInfoDialog.reset(new ConnectionInfo{&d->mNmModel}); connect(d->mInfoDialog.data(), &QDialog::finished, [this] { d->mInfoDialog.reset(nullptr); }); } d->openCloseDialog(d->mInfoDialog.data()); }); connect(d->mActDebugInfo, &QAction::triggered, [this] (bool ) { if (d->mConnDialog.isNull()) { d->mConnDialog.reset(new NmList{Tray::tr("nm-tray info"), &d->mNmModel}); connect(d->mConnDialog.data(), &QDialog::finished, [this] { d->mConnDialog.reset(nullptr); }); } d->openCloseDialog(d->mConnDialog.data()); }); // Note: Force all the updates as the NetworkManager::Notifier signals aren't // emitted at application startup. d->primaryConnectionUpdate(); setActionsStates(); connect(NetworkManager::notifier(), &NetworkManager::Notifier::networkingEnabledChanged, &d->mStateTimer, static_cast<void (QTimer::*)()>(&QTimer::start)); connect(NetworkManager::notifier(), &NetworkManager::Notifier::wirelessEnabledChanged, &d->mStateTimer, static_cast<void (QTimer::*)()>(&QTimer::start)); connect(NetworkManager::notifier(), &NetworkManager::Notifier::wirelessHardwareEnabledChanged, &d->mStateTimer, static_cast<void (QTimer::*)()>(&QTimer::start)); connect(NetworkManager::notifier(), &NetworkManager::Notifier::primaryConnectionChanged, this, &Tray::onPrimaryConnectionChanged); connect(&d->mActiveConnections, &QAbstractItemModel::rowsInserted, [this] (QModelIndex const & parent, int first, int last) { for (int i = first; i <= last; ++i) { const QModelIndex index = d->mActiveConnections.index(i, 0, parent); //qCDebug(NM_TRAY) << "rowsInserted" << index; if (d->mEnableNotifications) { d->mConnectionsToNotify.append(index); } d->updateState(index, false); } }); connect(&d->mActiveConnections, &QAbstractItemModel::rowsAboutToBeRemoved, [this] (QModelIndex const & parent, int first, int last) { //qCDebug(NM_TRAY) << "rowsAboutToBeRemoved"; for (int i = first; i <= last; ++i) d->updateState(d->mActiveConnections.index(i, 0, parent), true); }); connect(&d->mActiveConnections, &QAbstractItemModel::dataChanged, [this] (const QModelIndex & topLeft, const QModelIndex & bottomRight, const QVector<int> & /*roles*/) { //qCDebug(NM_TRAY) << "dataChanged"; for (auto const & i : QItemSelection{topLeft, bottomRight}.indexes()) d->updateState(i, false); }); d->mTrayIcon.setContextMenu(&d->mContextMenu); QTimer::singleShot(0, [this] { d->mTrayIcon.show(); }); } Tray::~Tray() { } bool Tray::eventFilter(QObject * object, QEvent * event) { Q_ASSERT(&d->mContextMenu == object); if (QEvent::ThemeChange == event->type()) d->refreshIcon(); return false; } void Tray::onEditConnectionsTriggered() { const QStringList connections_editor = QSettings{}.value(CONNECTIONS_EDITOR, QStringList{{"xterm", "-e", "nmtui-edit"}}).toStringList(); if (connections_editor.empty() || connections_editor.front().isEmpty()) { qCCritical(NM_TRAY) << "Can't start connection editor, because of misconfiguration. Value of" << CONNECTIONS_EDITOR << "invalid key," << connections_editor; return; } // Note: let this object dangle, if the process isn't finished until our application is closed QProcess * editor = new QProcess; editor->setProcessChannelMode(QProcess::ForwardedChannels); connect(editor, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished) , [connections_editor, editor] (int exitCode, QProcess::ExitStatus exitStatus) { qCInfo(NM_TRAY) << "connection editor " << connections_editor << " finished, exitCode=" << exitCode << ", exitStatus=" << exitStatus; editor->deleteLater(); }); connect(editor, &QProcess::errorOccurred , [connections_editor, editor] (QProcess::ProcessError error) { qCInfo(NM_TRAY) << "connection editor " << connections_editor << " failed, error=" << error; editor->deleteLater(); }); qCInfo(NM_TRAY) << "starting connection editor " << connections_editor; QString program = connections_editor.front(); QStringList args; std::copy(connections_editor.cbegin() + 1, connections_editor.cend(), std::back_inserter(args)); editor->start(program, args); editor->closeWriteChannel(); } void Tray::onAboutTriggered() { QMessageBox::about(nullptr, Tray::tr("%1 about").arg(QStringLiteral("nm-tray")) , Tray::tr("<strong><a href=\"https://github.com/palinek/nm-tray\">nm-tray</a></strong> is a simple Qt based" " frontend for <a href=\"https://wiki.gnome.org/Projects/NetworkManager\">NetworkManager</a>.<br/><br/>" "Version: %1").arg(NM_TRAY_VERSION)); } void Tray::onQuitTriggered() { QApplication::instance()->quit(); } void Tray::onActivated() { QMenu * menu = new WindowMenu(&d->mNmModel); menu->setAttribute(Qt::WA_DeleteOnClose); menu->popup(QCursor::pos()); } void Tray::setActionsStates() { const bool net_enabled = NetworkManager::isNetworkingEnabled(); d->mActEnableNetwork->setChecked(net_enabled); d->mActEnableWifi->setChecked(NetworkManager::isWirelessEnabled()); d->mActEnableWifi->setEnabled(NetworkManager::isNetworkingEnabled() && NetworkManager::isWirelessHardwareEnabled()); d->mActConnInfo->setEnabled(net_enabled); } void Tray::onPrimaryConnectionChanged(QString const & /*uni*/) { d->primaryConnectionUpdate(); } 07070117A67471000081A40000000200000002000000015A3D9FC90000058F000000FD0000001000000000000000000000002800000000nm-tray-0.3.0.19~git.29290df/src/tray.h/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2015~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #if !defined(TRAY_H) #define TRAY_H #include <QObject> #include <QScopedPointer> class TrayPrivate; class Tray : public QObject { Q_OBJECT public: Tray(QObject *parent = nullptr); ~Tray(); protected: virtual bool eventFilter(QObject * object, QEvent * event) override; private Q_SLOTS: //menu void onEditConnectionsTriggered(); void onAboutTriggered(); void onQuitTriggered(); void onActivated(); //NetworkManager void setActionsStates(); void onPrimaryConnectionChanged(QString const & uni); private: QScopedPointer<TrayPrivate> d; }; #endif //TRAY_H 07070117A67472000081A40000000200000002000000015A3D9FC900001B88000000FD0000001000000000000000000000003000000000nm-tray-0.3.0.19~git.29290df/src/windowmenu.cpp/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2016~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #include "windowmenu.h" #include "nmmodel.h" #include "nmproxy.h" #include "menuview.h" #include <QWidgetAction> #include <functional> #include <QTimer> class WindowMenuPrivate { public: NmModel * mNmModel; QScopedPointer<NmProxy> mWirelessModel; QWidgetAction * mWirelessAction; QScopedPointer<NmProxy> mActiveModel; QWidgetAction * mActiveAction; QScopedPointer<NmProxy> mConnectionModel; QWidgetAction * mConnectionAction; QAction * mMakeDirtyAction; QTimer mDelaySizeRefreshTimer; WindowMenuPrivate(WindowMenu * q); template <typename F> void onActivated(QModelIndex const & index , QAbstractItemModel const * topParent , F const & functor); void forceSizeRefresh(); void onViewRowChange(QAction * viewAction, QAbstractItemModel const * model); private: WindowMenu * q_ptr; Q_DECLARE_PUBLIC(WindowMenu); }; WindowMenuPrivate::WindowMenuPrivate(WindowMenu * q) : q_ptr{q} { } template <typename F> void WindowMenuPrivate::onActivated(QModelIndex const & index , QAbstractItemModel const * topParent , F const & functor) { QModelIndex i = index; for (QAbstractProxyModel const * proxy = qobject_cast<QAbstractProxyModel const *>(index.model()) ; nullptr != proxy && topParent != proxy ; proxy = qobject_cast<QAbstractProxyModel const *>(proxy->sourceModel()) ) { i = proxy->mapToSource(i); } functor(i); } void WindowMenuPrivate::forceSizeRefresh() { Q_Q(WindowMenu); if (!q->isVisible()) { return; } const QSize old_size = q->size(); //TODO: how to force the menu to recalculate it's size in a more elegant way? q->addAction(mMakeDirtyAction); q->removeAction(mMakeDirtyAction); // ensure to be visible (should the resize make it out of screen) if (old_size != q->size()) { q->popup(q->geometry().topLeft()); } } void WindowMenuPrivate::onViewRowChange(QAction * viewAction, QAbstractItemModel const * model) { viewAction->setVisible(model->rowCount(QModelIndex{}) > 0); mDelaySizeRefreshTimer.start(); } WindowMenu::WindowMenu(NmModel * nmModel, QWidget * parent /*= nullptr*/) : QMenu{parent} , d_ptr{new WindowMenuPrivate{this}} { Q_D(WindowMenu); d->mNmModel = nmModel; //active proxy & widgets d->mActiveModel.reset(new NmProxy); d->mActiveModel->setNmModel(d->mNmModel, NmModel::ActiveConnectionType); MenuView * active_view = new MenuView{d->mActiveModel.data()}; connect(active_view, &QAbstractItemView::activated, [this, d] (const QModelIndex & index) { d->onActivated(index, d->mActiveModel.data(), std::bind(&NmProxy::deactivateConnection, d->mActiveModel.data(), std::placeholders::_1)); close(); }); d->mActiveAction = new QWidgetAction{this}; d->mActiveAction->setDefaultWidget(active_view); connect(d->mActiveModel.data(), &QAbstractItemModel::modelReset, [d] { d->onViewRowChange(d->mActiveAction, d->mActiveModel.data()); }); connect(d->mActiveModel.data(), &QAbstractItemModel::rowsInserted, [d] { d->onViewRowChange(d->mActiveAction, d->mActiveModel.data()); }); connect(d->mActiveModel.data(), &QAbstractItemModel::rowsRemoved, [d] { d->onViewRowChange(d->mActiveAction, d->mActiveModel.data()); }); //wireless proxy & widgets d->mWirelessModel.reset(new NmProxy); d->mWirelessModel->setNmModel(d->mNmModel, NmModel::WifiNetworkType); MenuView * wifi_view = new MenuView{d->mWirelessModel.data()}; connect(wifi_view, &QAbstractItemView::activated, [this, d] (const QModelIndex & index) { d->onActivated(index, d->mWirelessModel.data(), std::bind(&NmProxy::activateConnection, d->mWirelessModel.data(), std::placeholders::_1)); close(); }); d->mWirelessAction = new QWidgetAction{this}; d->mWirelessAction->setDefaultWidget(wifi_view); connect(d->mWirelessModel.data(), &QAbstractItemModel::modelReset, [d] { d->onViewRowChange(d->mWirelessAction, d->mWirelessModel.data()); }); connect(d->mWirelessModel.data(), &QAbstractItemModel::rowsInserted, [d] { d->onViewRowChange(d->mWirelessAction, d->mWirelessModel.data()); }); connect(d->mWirelessModel.data(), &QAbstractItemModel::rowsRemoved, [d] { d->onViewRowChange(d->mWirelessAction, d->mWirelessModel.data()); }); //connection proxy & widgets d->mConnectionModel.reset(new NmProxy); d->mConnectionModel->setNmModel(d->mNmModel, NmModel::ConnectionType); MenuView * connection_view = new MenuView{d->mConnectionModel.data()}; connect(connection_view, &QAbstractItemView::activated, [this, d] (const QModelIndex & index) { d->onActivated(index, d->mConnectionModel.data(), std::bind(&NmProxy::activateConnection, d->mConnectionModel.data(), std::placeholders::_1)); close(); }); d->mConnectionAction = new QWidgetAction{this}; d->mConnectionAction->setDefaultWidget(connection_view); connect(d->mConnectionModel.data(), &QAbstractItemModel::modelReset, [d] { d->onViewRowChange(d->mConnectionAction, d->mConnectionModel.data()); }); connect(d->mConnectionModel.data(), &QAbstractItemModel::rowsInserted, [d] { d->onViewRowChange(d->mConnectionAction, d->mConnectionModel.data()); }); connect(d->mConnectionModel.data(), &QAbstractItemModel::rowsRemoved, [d] { d->onViewRowChange(d->mConnectionAction, d->mConnectionModel.data()); }); addAction(tr("Active connection(s)"))->setEnabled(false); addAction(d->mActiveAction); addAction(tr("Wi-Fi network(s)"))->setEnabled(false); addAction(d->mWirelessAction); addAction(tr("Known connection(s)"))->setEnabled(false); addAction(d->mConnectionAction); d->mMakeDirtyAction = new QAction{this}; d->mDelaySizeRefreshTimer.setInterval(200); d->mDelaySizeRefreshTimer.setSingleShot(true); connect(&d->mDelaySizeRefreshTimer, &QTimer::timeout, [d] { d->forceSizeRefresh(); }); d->onViewRowChange(d->mActiveAction, d->mActiveModel.data()); d->onViewRowChange(d->mWirelessAction, d->mWirelessModel.data()); d->onViewRowChange(d->mConnectionAction, d->mConnectionModel.data()); } WindowMenu::~WindowMenu() { } 07070117A67473000081A40000000200000002000000015A3D9FC900000499000000FD0000001000000000000000000000002E00000000nm-tray-0.3.0.19~git.29290df/src/windowmenu.h/*COPYRIGHT_HEADER This file is a part of nm-tray. Copyright (c) 2016~now Palo Kisa <palo.kisa@gmail.com> nm-tray is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. COPYRIGHT_HEADER*/ #if !defined(WINDOW_MENU_H) #define WINDOW_MENU_H #include <QMenu> class WindowMenuPrivate; class NmModel; class WindowMenu : public QMenu { Q_OBJECT public: WindowMenu(NmModel * nmModel, QWidget * parent = nullptr); ~WindowMenu(); private: QScopedPointer<WindowMenuPrivate> d_ptr; Q_DECLARE_PRIVATE(WindowMenu); }; #endif //WINDOW_MENU_H 07070117A67474000041ED0000000200000002000000025A3D9FC900000000000000FD0000001000000000000000000000002A00000000nm-tray-0.3.0.19~git.29290df/translations07070117A67475000081A40000000200000002000000015A3D9FC90000280D000000FD0000001000000000000000000000003500000000nm-tray-0.3.0.19~git.29290df/translations/nm-tray.ts<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.1"> <context> <name>ConnectionInfo</name> <message> <location filename="../src/connectioninfo.ui" line="14"/> <source>Connection information</source> <translation type="unfinished"></translation> </message> </context> <context> <name>NmList</name> <message> <location filename="../src/nmlist.ui" line="14"/> <source>Dialog</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmlist.ui" line="20"/> <source>All information</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmlist.ui" line="30"/> <source>Active connections</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmlist.ui" line="40"/> <source>Available wireless</source> <translation type="unfinished"></translation> </message> </context> <context> <name>NmModel</name> <message> <location filename="../src/nmmodel.cpp" line="55"/> <source>nm-tray - wireless password</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="56"/> <source>Password is needed for connection to '%1':</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="728"/> <source>root</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="730"/> <source>active connection(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="732"/> <source>connection(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="734"/> <source>device(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="736"/> <source>wifi network(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1027"/> <source>unknown</source> <comment>hardware address</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1130"/> <source>General</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1131"/> <source>Interface</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1133"/> <source>Hardware Address</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1135"/> <source>Driver</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1137"/> <source>Speed</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1139"/> <source> Kb/s</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1141"/> <source>unknown</source> <comment>Speed</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1145"/> <source>Security</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1149"/> <source>IPv4</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1150"/> <source>IPv6</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1161"/> <source>IP Address</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1163"/> <source>Subnet Mask</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1172"/> <source>Default route</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1178"/> <source>DNS(%1)</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> </context> <context> <name>Tray</name> <message> <location filename="../src/tray.cpp" line="123"/> <source><pre>Connection <strong>%1</strong>(%2) active</pre></source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="129"/> <source><pre>No active connection</pre></source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="202"/> <source>Connection lost</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="203"/> <source>No longer connected to %1 '%2'.</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="215"/> <source>Connection established</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="216"/> <source>Now connected to %1 '%2'.</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="220"/> <source>NetworkManager(nm-tray)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="253"/> <source>Enable Networking</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="254"/> <source>Enable Wi-Fi</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="256"/> <source>Enable notifications</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="258"/> <source>Connection information</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="259"/> <source>Debug information</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="260"/> <source>Edit connections...</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="263"/> <source>About</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="265"/> <source>Quit</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="290"/> <source>nm-tray info</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="382"/> <source>%1 about</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="383"/> <source><strong><a href="https://github.com/palinek/nm-tray">nm-tray</a></strong> is a simple Qt based frontend for <a href="https://wiki.gnome.org/Projects/NetworkManager">NetworkManager</a>.<br/><br/>Version: %1</source> <translation type="unfinished"></translation> </message> </context> <context> <name>WindowMenu</name> <message> <location filename="../src/windowmenu.cpp" line="163"/> <source>Active connection(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/windowmenu.cpp" line="165"/> <source>Wi-Fi network(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/windowmenu.cpp" line="167"/> <source>Known connection(s)</source> <translation type="unfinished"></translation> </message> </context> </TS> 07070117A67476000081A40000000200000002000000015A3D9FC9000028D7000000FD0000001000000000000000000000003800000000nm-tray-0.3.0.19~git.29290df/translations/nm-tray_cs.ts<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.1" language="cs"> <context> <name>ConnectionInfo</name> <message> <location filename="../src/connectioninfo.ui" line="14"/> <source>Connection information</source> <translation>Informace o spojení</translation> </message> </context> <context> <name>NmList</name> <message> <location filename="../src/nmlist.ui" line="14"/> <source>Dialog</source> <translation></translation> </message> <message> <location filename="../src/nmlist.ui" line="20"/> <source>All information</source> <translation>Všechny informace</translation> </message> <message> <location filename="../src/nmlist.ui" line="30"/> <source>Active connections</source> <translation>Aktivní připojení</translation> </message> <message> <location filename="../src/nmlist.ui" line="40"/> <source>Available wireless</source> <translation>Bezdrátové sítě k dispozici</translation> </message> </context> <context> <name>NmModel</name> <message> <location filename="../src/nmmodel.cpp" line="55"/> <source>nm-tray - wireless password</source> <translation>nm-tray – heslo k bezdrátové síti</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="56"/> <source>Password is needed for connection to '%1':</source> <translation>Pro připojení k „%1“ je třeba heslo:</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="728"/> <source>root</source> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="730"/> <source>active connection(s)</source> <translation>aktivní spojení</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="732"/> <source>connection(s)</source> <translation>spojení</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="734"/> <source>device(s)</source> <translation>zařízení</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="736"/> <source>wifi network(s)</source> <translation>WiFi sítě</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1027"/> <source>unknown</source> <comment>hardware address</comment> <translation>neznámé</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1130"/> <source>General</source> <comment>Active connection information</comment> <translation>Obecné</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1131"/> <source>Interface</source> <comment>Active connection information</comment> <translation>Rozhraní</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1133"/> <source>Hardware Address</source> <comment>Active connection information</comment> <translation>Hardwarová (MAC) adresa</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1135"/> <source>Driver</source> <comment>Active connection information</comment> <translation>Ovladač</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1137"/> <source>Speed</source> <comment>Active connection information</comment> <translation>Rychlost</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1139"/> <source> Kb/s</source> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1141"/> <source>unknown</source> <comment>Speed</comment> <translation>neznámá</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1145"/> <source>Security</source> <comment>Active connection information</comment> <translation>Zabezpečení</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1149"/> <source>IPv4</source> <comment>Active connection information</comment> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1150"/> <source>IPv6</source> <comment>Active connection information</comment> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1161"/> <source>IP Address</source> <comment>Active connection information</comment> <translation>IP Adresa</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1163"/> <source>Subnet Mask</source> <comment>Active connection information</comment> <translation>Maska sítě</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1172"/> <source>Default route</source> <comment>Active connection information</comment> <translation>Výchozí trasa</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1178"/> <source>DNS(%1)</source> <comment>Active connection information</comment> <translation></translation> </message> </context> <context> <name>Tray</name> <message> <location filename="../src/tray.cpp" line="123"/> <source><pre>Connection <strong>%1</strong>(%2) active</pre></source> <translation><pre>Spojení <strong>%1</strong>(%2) aktivní</pre></translation> </message> <message> <location filename="../src/tray.cpp" line="129"/> <source><pre>No active connection</pre></source> <translation><pre>Žádné aktivní spojení</pre></translation> </message> <message> <location filename="../src/tray.cpp" line="202"/> <source>Connection lost</source> <translation>Spojení ztraceno</translation> </message> <message> <location filename="../src/tray.cpp" line="203"/> <source>No longer connected to %1 '%2'.</source> <translation>Nadále už nepřipojeno k %1 „%2“.</translation> </message> <message> <location filename="../src/tray.cpp" line="215"/> <source>Connection established</source> <translation>Spojení navázáno</translation> </message> <message> <location filename="../src/tray.cpp" line="216"/> <source>Now connected to %1 '%2'.</source> <translation>Nyní připojeno k %1 „%2“.</translation> </message> <message> <location filename="../src/tray.cpp" line="220"/> <source>NetworkManager(nm-tray)</source> <translation></translation> </message> <message> <location filename="../src/tray.cpp" line="253"/> <source>Enable Networking</source> <translation>Zapnout síť</translation> </message> <message> <location filename="../src/tray.cpp" line="254"/> <source>Enable Wi-Fi</source> <translation>Zapnout WiFi</translation> </message> <message> <location filename="../src/tray.cpp" line="256"/> <source>Enable notifications</source> <translation>Zapnout oznamování</translation> </message> <message> <location filename="../src/tray.cpp" line="258"/> <source>Connection information</source> <translation>Informace o připojení</translation> </message> <message> <location filename="../src/tray.cpp" line="259"/> <source>Debug information</source> <translation>Ladící informace</translation> </message> <message> <location filename="../src/tray.cpp" line="260"/> <source>Edit connections...</source> <translation>Upravit připojení…</translation> </message> <message> <location filename="../src/tray.cpp" line="263"/> <source>About</source> <translation>O aplikaci</translation> </message> <message> <location filename="../src/tray.cpp" line="265"/> <source>Quit</source> <translation>Ukončit</translation> </message> <message> <location filename="../src/tray.cpp" line="290"/> <source>nm-tray info</source> <translation>nm-tray informace</translation> </message> <message> <location filename="../src/tray.cpp" line="382"/> <source>%1 about</source> <translation>o %1</translation> </message> <message> <location filename="../src/tray.cpp" line="383"/> <source><strong><a href="https://github.com/palinek/nm-tray">nm-tray</a></strong> is a simple Qt based frontend for <a href="https://wiki.gnome.org/Projects/NetworkManager">NetworkManager</a>.<br/><br/>Version: %1</source> <translation><strong><a href="https://github.com/palinek/nm-tray">nm-tray</a></strong> je jednoduchá nadstavba pro <a href="https://wiki.gnome.org/Projects/NetworkManager">NetworkManager</a>, založená na Qt.<br/><br/>Verze: %1</translation> </message> </context> <context> <name>WindowMenu</name> <message> <location filename="../src/windowmenu.cpp" line="163"/> <source>Active connection(s)</source> <translation>Aktivní připojení</translation> </message> <message> <location filename="../src/windowmenu.cpp" line="165"/> <source>Wi-Fi network(s)</source> <translation>WiFi sítě</translation> </message> <message> <location filename="../src/windowmenu.cpp" line="167"/> <source>Known connection(s)</source> <translation>Známá připojení</translation> </message> </context> </TS> 07070117A67477000081A40000000200000002000000015A3D9FC90000281E000000FD0000001000000000000000000000003800000000nm-tray-0.3.0.19~git.29290df/translations/nm-tray_de.ts<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.1" language="de_DE"> <context> <name>ConnectionInfo</name> <message> <location filename="../src/connectioninfo.ui" line="14"/> <source>Connection information</source> <translation type="unfinished"></translation> </message> </context> <context> <name>NmList</name> <message> <location filename="../src/nmlist.ui" line="14"/> <source>Dialog</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmlist.ui" line="20"/> <source>All information</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmlist.ui" line="30"/> <source>Active connections</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmlist.ui" line="40"/> <source>Available wireless</source> <translation type="unfinished"></translation> </message> </context> <context> <name>NmModel</name> <message> <location filename="../src/nmmodel.cpp" line="55"/> <source>nm-tray - wireless password</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="56"/> <source>Password is needed for connection to '%1':</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="728"/> <source>root</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="730"/> <source>active connection(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="732"/> <source>connection(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="734"/> <source>device(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="736"/> <source>wifi network(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1027"/> <source>unknown</source> <comment>hardware address</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1130"/> <source>General</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1131"/> <source>Interface</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1133"/> <source>Hardware Address</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1135"/> <source>Driver</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1137"/> <source>Speed</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1139"/> <source> Kb/s</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1141"/> <source>unknown</source> <comment>Speed</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1145"/> <source>Security</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1149"/> <source>IPv4</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1150"/> <source>IPv6</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1161"/> <source>IP Address</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1163"/> <source>Subnet Mask</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1172"/> <source>Default route</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1178"/> <source>DNS(%1)</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> </context> <context> <name>Tray</name> <message> <location filename="../src/tray.cpp" line="123"/> <source><pre>Connection <strong>%1</strong>(%2) active</pre></source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="129"/> <source><pre>No active connection</pre></source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="202"/> <source>Connection lost</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="203"/> <source>No longer connected to %1 '%2'.</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="215"/> <source>Connection established</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="216"/> <source>Now connected to %1 '%2'.</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="220"/> <source>NetworkManager(nm-tray)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="253"/> <source>Enable Networking</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="254"/> <source>Enable Wi-Fi</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="256"/> <source>Enable notifications</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="258"/> <source>Connection information</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="259"/> <source>Debug information</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="260"/> <source>Edit connections...</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="263"/> <source>About</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="265"/> <source>Quit</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="290"/> <source>nm-tray info</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="382"/> <source>%1 about</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="383"/> <source><strong><a href="https://github.com/palinek/nm-tray">nm-tray</a></strong> is a simple Qt based frontend for <a href="https://wiki.gnome.org/Projects/NetworkManager">NetworkManager</a>.<br/><br/>Version: %1</source> <translation type="unfinished"></translation> </message> </context> <context> <name>WindowMenu</name> <message> <location filename="../src/windowmenu.cpp" line="163"/> <source>Active connection(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/windowmenu.cpp" line="165"/> <source>Wi-Fi network(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/windowmenu.cpp" line="167"/> <source>Known connection(s)</source> <translation type="unfinished"></translation> </message> </context> </TS> 07070117A67478000081A40000000200000002000000015A3D9FC9000029E1000000FD0000001000000000000000000000003800000000nm-tray-0.3.0.19~git.29290df/translations/nm-tray_he.ts<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.1" language="he"> <context> <name>ConnectionInfo</name> <message> <location filename="../src/connectioninfo.ui" line="14"/> <source>Connection information</source> <translation>פרטי החיבור</translation> </message> </context> <context> <name>NmList</name> <message> <location filename="../src/nmlist.ui" line="14"/> <source>Dialog</source> <translation>תיבת דו־שיח</translation> </message> <message> <location filename="../src/nmlist.ui" line="20"/> <source>All information</source> <translation>כל הפרטים</translation> </message> <message> <location filename="../src/nmlist.ui" line="30"/> <source>Active connections</source> <translation>חיבורים פעילים</translation> </message> <message> <location filename="../src/nmlist.ui" line="40"/> <source>Available wireless</source> <translation>אלחוטיות זמינות</translation> </message> </context> <context> <name>NmModel</name> <message> <location filename="../src/nmmodel.cpp" line="728"/> <source>root</source> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="730"/> <source>active connection(s)</source> <translation>חיבורים פעילים</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="732"/> <source>connection(s)</source> <translation>חיבורים</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="734"/> <source>device(s)</source> <translation>התקנים</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="736"/> <source>wifi network(s)</source> <translation>רשתות אלחוטיות</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1027"/> <source>unknown</source> <comment>hardware address</comment> <translation>לא ידוע</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="55"/> <source>nm-tray - wireless password</source> <translation>nm-tray - ססמה לרשת אלחוטית</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="56"/> <source>Password is needed for connection to '%1':</source> <translation>נדרשת ססמה כדי להתחבר אל ‚%1’:</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1130"/> <source>General</source> <comment>Active connection information</comment> <translation>כללי</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1131"/> <source>Interface</source> <comment>Active connection information</comment> <translation>מנשק</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1133"/> <source>Hardware Address</source> <comment>Active connection information</comment> <translation>כתובת חומרה</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1135"/> <source>Driver</source> <comment>Active connection information</comment> <translation>מנהל התקן</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1137"/> <source>Speed</source> <comment>Active connection information</comment> <translation>מהירות</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1139"/> <source> Kb/s</source> <translation> קסל״ש</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1141"/> <source>unknown</source> <comment>Speed</comment> <translation>לא ידועה</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1145"/> <source>Security</source> <comment>Active connection information</comment> <translation>אבטחה</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1149"/> <source>IPv4</source> <comment>Active connection information</comment> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1150"/> <source>IPv6</source> <comment>Active connection information</comment> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1161"/> <source>IP Address</source> <comment>Active connection information</comment> <translation>כתובת IP</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1163"/> <source>Subnet Mask</source> <comment>Active connection information</comment> <translation>מסכת רשת</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1172"/> <source>Default route</source> <comment>Active connection information</comment> <translation>נתיב בררת מחדל</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1178"/> <source>DNS(%1)</source> <comment>Active connection information</comment> <translation></translation> </message> </context> <context> <name>Tray</name> <message> <location filename="../src/tray.cpp" line="202"/> <source>Connection lost</source> <translation>החיבור נותק</translation> </message> <message> <location filename="../src/tray.cpp" line="215"/> <source>Connection established</source> <translation>החיבור הצליח</translation> </message> <message> <location filename="../src/tray.cpp" line="220"/> <source>NetworkManager(nm-tray)</source> <translation></translation> </message> <message> <location filename="../src/tray.cpp" line="253"/> <source>Enable Networking</source> <translation>הפעלת קישוריות רשת</translation> </message> <message> <location filename="../src/tray.cpp" line="123"/> <source><pre>Connection <strong>%1</strong>(%2) active</pre></source> <translation><pre>החיבור <strong>%1</strong>(%2) פעיל</pre></translation> </message> <message> <location filename="../src/tray.cpp" line="129"/> <source><pre>No active connection</pre></source> <translation><pre>אין חיבורים פעילים</pre></translation> </message> <message> <location filename="../src/tray.cpp" line="203"/> <source>No longer connected to %1 '%2'.</source> <translation>החיבור אל %1 נותק ‚%2’.</translation> </message> <message> <location filename="../src/tray.cpp" line="216"/> <source>Now connected to %1 '%2'.</source> <translation>הצלחנו להתחבר אל %1 ‚%2’.</translation> </message> <message> <location filename="../src/tray.cpp" line="254"/> <source>Enable Wi-Fi</source> <translation>הפעלת חיבור אלחוטי</translation> </message> <message> <location filename="../src/tray.cpp" line="256"/> <source>Enable notifications</source> <translation>הפעלת התרעות</translation> </message> <message> <location filename="../src/tray.cpp" line="258"/> <source>Connection information</source> <translation>פרטי החיבור</translation> </message> <message> <location filename="../src/tray.cpp" line="259"/> <source>Debug information</source> <translation>פרטים לניפוי שגיאות</translation> </message> <message> <location filename="../src/tray.cpp" line="260"/> <source>Edit connections...</source> <translation>עריכת חיבורים…</translation> </message> <message> <location filename="../src/tray.cpp" line="263"/> <source>About</source> <translation>על אודות</translation> </message> <message> <location filename="../src/tray.cpp" line="265"/> <source>Quit</source> <translation>יציאה</translation> </message> <message> <location filename="../src/tray.cpp" line="382"/> <source>%1 about</source> <translation>על אודות %1</translation> </message> <message> <location filename="../src/tray.cpp" line="383"/> <source><strong><a href="https://github.com/palinek/nm-tray">nm-tray</a></strong> is a simple Qt based frontend for <a href="https://wiki.gnome.org/Projects/NetworkManager">NetworkManager</a>.<br/><br/>Version: %1</source> <translation><strong><a href="https://github.com/palinek/nm-tray">nm-tray</a></strong> הוא מנשק מבוסס Qt עבור <a href="https://wiki.gnome.org/Projects/NetworkManager">NetworkManager</a>.<br/><br/>גרסה: %1</translation> </message> <message> <location filename="../src/tray.cpp" line="290"/> <source>nm-tray info</source> <translation>פרטי nm-tray</translation> </message> </context> <context> <name>WindowMenu</name> <message> <location filename="../src/windowmenu.cpp" line="163"/> <source>Active connection(s)</source> <translation>חיבורים פעילים</translation> </message> <message> <location filename="../src/windowmenu.cpp" line="165"/> <source>Wi-Fi network(s)</source> <translation>רשתות אלחוטיות</translation> </message> <message> <location filename="../src/windowmenu.cpp" line="167"/> <source>Known connection(s)</source> <translation>חיבורים מוכרים</translation> </message> </context> </TS> 07070117A67479000081A40000000200000002000000015A3D9FC9000029FF000000FD0000001000000000000000000000003B00000000nm-tray-0.3.0.19~git.29290df/translations/nm-tray_nb_NO.ts<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.1" language="nb_NO"> <context> <name>ConnectionInfo</name> <message> <location filename="../src/connectioninfo.ui" line="14"/> <source>Connection information</source> <translation>Tilkoblingsinformasjon</translation> </message> </context> <context> <name>NmList</name> <message> <location filename="../src/nmlist.ui" line="14"/> <source>Dialog</source> <translation></translation> </message> <message> <location filename="../src/nmlist.ui" line="20"/> <source>All information</source> <translation>All informasjon</translation> </message> <message> <location filename="../src/nmlist.ui" line="30"/> <source>Active connections</source> <translation>Aktive tilkoblinger</translation> </message> <message> <location filename="../src/nmlist.ui" line="40"/> <source>Available wireless</source> <translation>Tilgjengelige trådløsnettverk</translation> </message> </context> <context> <name>NmModel</name> <message> <location filename="../src/nmmodel.cpp" line="728"/> <source>root</source> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="730"/> <source>active connection(s)</source> <translation>aktiv(e) tilkobling(er)</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="732"/> <source>connection(s)</source> <translation>tilkobling(er)</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="734"/> <source>device(s)</source> <translation>enhet(er)</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="736"/> <source>wifi network(s)</source> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1027"/> <source>unknown</source> <comment>hardware address</comment> <translation>ukjent</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="55"/> <source>nm-tray - wireless password</source> <translation>nm-tray - trådløspassord</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="56"/> <source>Password is needed for connection to '%1':</source> <translation>Passord kreves for tilkobling til '%1':</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1130"/> <source>General</source> <comment>Active connection information</comment> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1131"/> <source>Interface</source> <comment>Active connection information</comment> <translation>Grensesnitt</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1133"/> <source>Hardware Address</source> <comment>Active connection information</comment> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1135"/> <source>Driver</source> <comment>Active connection information</comment> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1137"/> <source>Speed</source> <comment>Active connection information</comment> <translation>Hastighet</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1139"/> <source> Kb/s</source> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1141"/> <source>unknown</source> <comment>Speed</comment> <translation>ukjent</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1145"/> <source>Security</source> <comment>Active connection information</comment> <translation>Sikkerhet</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1149"/> <source>IPv4</source> <comment>Active connection information</comment> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1150"/> <source>IPv6</source> <comment>Active connection information</comment> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1161"/> <source>IP Address</source> <comment>Active connection information</comment> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1163"/> <source>Subnet Mask</source> <comment>Active connection information</comment> <translation>Nettmaske</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1172"/> <source>Default route</source> <comment>Active connection information</comment> <translation></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1178"/> <source>DNS(%1)</source> <comment>Active connection information</comment> <translation></translation> </message> </context> <context> <name>Tray</name> <message> <location filename="../src/tray.cpp" line="202"/> <source>Connection lost</source> <translation>Tilknytningen gitt tapt</translation> </message> <message> <source>We have just lost the connection to %1 '%2'.</source> <translation type="vanished">Mistet tilknytningen til %1 '%2'.</translation> </message> <message> <location filename="../src/tray.cpp" line="215"/> <source>Connection established</source> <translation>Tilkobling opprettet</translation> </message> <message> <source>We have just established the connection to %1 '%2'.</source> <translation type="vanished">Tilkobling etablert til %1 '%2'.</translation> </message> <message> <location filename="../src/tray.cpp" line="220"/> <source>NetworkManager(nm-tray)</source> <translation></translation> </message> <message> <location filename="../src/tray.cpp" line="253"/> <source>Enable Networking</source> <translation>Skru på nettverk</translation> </message> <message> <source>Enable Wi-fi</source> <translation type="vanished">Skru på Wi-Fi</translation> </message> <message> <location filename="../src/tray.cpp" line="123"/> <source><pre>Connection <strong>%1</strong>(%2) active</pre></source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="129"/> <source><pre>No active connection</pre></source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="203"/> <source>No longer connected to %1 '%2'.</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="216"/> <source>Now connected to %1 '%2'.</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="254"/> <source>Enable Wi-Fi</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="256"/> <source>Enable notifications</source> <translation>Skru på merknader</translation> </message> <message> <location filename="../src/tray.cpp" line="258"/> <source>Connection information</source> <translation>Tilkoblingsinformasjon</translation> </message> <message> <location filename="../src/tray.cpp" line="259"/> <source>Debug information</source> <translation></translation> </message> <message> <location filename="../src/tray.cpp" line="260"/> <source>Edit connections...</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="263"/> <source>About</source> <translation>Om</translation> </message> <message> <location filename="../src/tray.cpp" line="265"/> <source>Quit</source> <translation>Avslutt</translation> </message> <message> <location filename="../src/tray.cpp" line="382"/> <source>%1 about</source> <translation>%1 om</translation> </message> <message> <location filename="../src/tray.cpp" line="383"/> <source><strong><a href="https://github.com/palinek/nm-tray">nm-tray</a></strong> is a simple Qt based frontend for <a href="https://wiki.gnome.org/Projects/NetworkManager">NetworkManager</a>.<br/><br/>Version: %1</source> <translation><strong><a href="https://github.com/palinek/nm-tray">nm-tray</a></strong> er en enkel Qt-basert grenseflate for <a href="https://wiki.gnome.org/Projects/NetworkManager">NetworkManager</a>.<br/><br/>Version: %1</translation> </message> <message> <location filename="../src/tray.cpp" line="290"/> <source>nm-tray info</source> <translation></translation> </message> </context> <context> <name>WindowMenu</name> <message> <location filename="../src/windowmenu.cpp" line="163"/> <source>Active connection(s)</source> <translation>Aktiv(e) tilkobling(er)</translation> </message> <message> <location filename="../src/windowmenu.cpp" line="165"/> <source>Wi-Fi network(s)</source> <translation></translation> </message> <message> <location filename="../src/windowmenu.cpp" line="167"/> <source>Known connection(s)</source> <translation type="unfinished"></translation> </message> </context> </TS> 07070117A6747A000081A40000000200000002000000015A3D9FC90000281E000000FD0000001000000000000000000000003800000000nm-tray-0.3.0.19~git.29290df/translations/nm-tray_pl.ts<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.1" language="pl_PL"> <context> <name>ConnectionInfo</name> <message> <location filename="../src/connectioninfo.ui" line="14"/> <source>Connection information</source> <translation type="unfinished"></translation> </message> </context> <context> <name>NmList</name> <message> <location filename="../src/nmlist.ui" line="14"/> <source>Dialog</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmlist.ui" line="20"/> <source>All information</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmlist.ui" line="30"/> <source>Active connections</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmlist.ui" line="40"/> <source>Available wireless</source> <translation type="unfinished"></translation> </message> </context> <context> <name>NmModel</name> <message> <location filename="../src/nmmodel.cpp" line="55"/> <source>nm-tray - wireless password</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="56"/> <source>Password is needed for connection to '%1':</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="728"/> <source>root</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="730"/> <source>active connection(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="732"/> <source>connection(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="734"/> <source>device(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="736"/> <source>wifi network(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1027"/> <source>unknown</source> <comment>hardware address</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1130"/> <source>General</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1131"/> <source>Interface</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1133"/> <source>Hardware Address</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1135"/> <source>Driver</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1137"/> <source>Speed</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1139"/> <source> Kb/s</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1141"/> <source>unknown</source> <comment>Speed</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1145"/> <source>Security</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1149"/> <source>IPv4</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1150"/> <source>IPv6</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1161"/> <source>IP Address</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1163"/> <source>Subnet Mask</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1172"/> <source>Default route</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1178"/> <source>DNS(%1)</source> <comment>Active connection information</comment> <translation type="unfinished"></translation> </message> </context> <context> <name>Tray</name> <message> <location filename="../src/tray.cpp" line="123"/> <source><pre>Connection <strong>%1</strong>(%2) active</pre></source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="129"/> <source><pre>No active connection</pre></source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="202"/> <source>Connection lost</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="203"/> <source>No longer connected to %1 '%2'.</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="215"/> <source>Connection established</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="216"/> <source>Now connected to %1 '%2'.</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="220"/> <source>NetworkManager(nm-tray)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="253"/> <source>Enable Networking</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="254"/> <source>Enable Wi-Fi</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="256"/> <source>Enable notifications</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="258"/> <source>Connection information</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="259"/> <source>Debug information</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="260"/> <source>Edit connections...</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="263"/> <source>About</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="265"/> <source>Quit</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="290"/> <source>nm-tray info</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="382"/> <source>%1 about</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/tray.cpp" line="383"/> <source><strong><a href="https://github.com/palinek/nm-tray">nm-tray</a></strong> is a simple Qt based frontend for <a href="https://wiki.gnome.org/Projects/NetworkManager">NetworkManager</a>.<br/><br/>Version: %1</source> <translation type="unfinished"></translation> </message> </context> <context> <name>WindowMenu</name> <message> <location filename="../src/windowmenu.cpp" line="163"/> <source>Active connection(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/windowmenu.cpp" line="165"/> <source>Wi-Fi network(s)</source> <translation type="unfinished"></translation> </message> <message> <location filename="../src/windowmenu.cpp" line="167"/> <source>Known connection(s)</source> <translation type="unfinished"></translation> </message> </context> </TS> 07070117A6747B000081A40000000200000002000000015A3D9FC90000290C000000FD0000001000000000000000000000003800000000nm-tray-0.3.0.19~git.29290df/translations/nm-tray_sk.ts<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.1" language="sk_SK"> <context> <name>ConnectionInfo</name> <message> <location filename="../src/connectioninfo.ui" line="14"/> <source>Connection information</source> <translation>Informácie o spojení</translation> </message> </context> <context> <name>NmList</name> <message> <location filename="../src/nmlist.ui" line="14"/> <source>Dialog</source> <translation>Dialóg</translation> </message> <message> <location filename="../src/nmlist.ui" line="20"/> <source>All information</source> <translation>Všetky informácie</translation> </message> <message> <location filename="../src/nmlist.ui" line="30"/> <source>Active connections</source> <translation>Aktívne spojenia</translation> </message> <message> <location filename="../src/nmlist.ui" line="40"/> <source>Available wireless</source> <translation>Dostupné bezdrôtové</translation> </message> </context> <context> <name>NmModel</name> <message> <location filename="../src/nmmodel.cpp" line="55"/> <source>nm-tray - wireless password</source> <translation>nm-tray - Wi-Fi heslo</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="56"/> <source>Password is needed for connection to '%1':</source> <translation>Pre pripojenie k '%1' je potrebné heslo:</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="728"/> <source>root</source> <translation>koreň</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="730"/> <source>active connection(s)</source> <translation>aktívne spojenie/a</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="732"/> <source>connection(s)</source> <translation>spojenie/a</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="734"/> <source>device(s)</source> <translation>zariadenie/a</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="736"/> <source>wifi network(s)</source> <translation>wifi sieť/te</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1027"/> <source>unknown</source> <comment>hardware address</comment> <translation>neznáma</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1130"/> <source>General</source> <comment>Active connection information</comment> <translation>Všeobecné</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1131"/> <source>Interface</source> <comment>Active connection information</comment> <translation>Rozhranie</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1133"/> <source>Hardware Address</source> <comment>Active connection information</comment> <translation>Hardvérová adresa</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1135"/> <source>Driver</source> <comment>Active connection information</comment> <translation>Driver</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1137"/> <source>Speed</source> <comment>Active connection information</comment> <translation>Rýchlosť</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1139"/> <source> Kb/s</source> <translation> Kb/s</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1141"/> <source>unknown</source> <comment>Speed</comment> <translation>neznáma</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1145"/> <source>Security</source> <comment>Active connection information</comment> <translation>Bezpečnosť</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1149"/> <source>IPv4</source> <comment>Active connection information</comment> <translation>IPv4</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1150"/> <source>IPv6</source> <comment>Active connection information</comment> <translation>IPv6</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1161"/> <source>IP Address</source> <comment>Active connection information</comment> <translation>IP adresa</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1163"/> <source>Subnet Mask</source> <comment>Active connection information</comment> <translation>Maska podsiete</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1172"/> <source>Default route</source> <comment>Active connection information</comment> <translation>Predvolená cesta</translation> </message> <message> <location filename="../src/nmmodel.cpp" line="1178"/> <source>DNS(%1)</source> <comment>Active connection information</comment> <translation>DNS(%1)</translation> </message> </context> <context> <name>Tray</name> <message> <location filename="../src/tray.cpp" line="123"/> <source><pre>Connection <strong>%1</strong>(%2) active</pre></source> <translation><pre>Spojenie <strong>%1</strong>(%2) aktívne</pre></translation> </message> <message> <location filename="../src/tray.cpp" line="129"/> <source><pre>No active connection</pre></source> <translation><pre>Žiadne aktívne spojenie</pre></translation> </message> <message> <location filename="../src/tray.cpp" line="202"/> <source>Connection lost</source> <translation>Spojenie stratené</translation> </message> <message> <location filename="../src/tray.cpp" line="203"/> <source>No longer connected to %1 '%2'.</source> <translation>Už nie je spojenie k %1 '%2'.</translation> </message> <message> <location filename="../src/tray.cpp" line="215"/> <source>Connection established</source> <translation>Spojenie naviazané</translation> </message> <message> <location filename="../src/tray.cpp" line="216"/> <source>Now connected to %1 '%2'.</source> <translation>Aktuálne pripojený k %1 '%2'.</translation> </message> <message> <location filename="../src/tray.cpp" line="220"/> <source>NetworkManager(nm-tray)</source> <translation>NetworkManager(nm-tray)</translation> </message> <message> <location filename="../src/tray.cpp" line="253"/> <source>Enable Networking</source> <translation>Zapnúť sieť</translation> </message> <message> <location filename="../src/tray.cpp" line="254"/> <source>Enable Wi-Fi</source> <translation>Zapnúť Wi-Fi</translation> </message> <message> <location filename="../src/tray.cpp" line="256"/> <source>Enable notifications</source> <translation>Zapnúť notifikácie</translation> </message> <message> <location filename="../src/tray.cpp" line="258"/> <source>Connection information</source> <translation>Informácie o spojení</translation> </message> <message> <location filename="../src/tray.cpp" line="259"/> <source>Debug information</source> <translation>Debug informácie</translation> </message> <message> <location filename="../src/tray.cpp" line="260"/> <source>Edit connections...</source> <translation>Editovať spojenia...</translation> </message> <message> <location filename="../src/tray.cpp" line="263"/> <source>About</source> <translation>O aplikácii</translation> </message> <message> <location filename="../src/tray.cpp" line="265"/> <source>Quit</source> <translation>Vypnúť</translation> </message> <message> <location filename="../src/tray.cpp" line="290"/> <source>nm-tray info</source> <translation>nm-tray info</translation> </message> <message> <location filename="../src/tray.cpp" line="382"/> <source>%1 about</source> <translation>%1 o aplikácii</translation> </message> <message> <location filename="../src/tray.cpp" line="383"/> <source><strong><a href="https://github.com/palinek/nm-tray">nm-tray</a></strong> is a simple Qt based frontend for <a href="https://wiki.gnome.org/Projects/NetworkManager">NetworkManager</a>.<br/><br/>Version: %1</source> <translation><strong><a href="https://github.com/palinek/nm-tray">nm-tray</a></strong> je jednoduchý Qt frontend pre <a href="https://wiki.gnome.org/Projects/NetworkManager">NetworkManager</a>.<br/><br/>Verzia: %1</translation> </message> </context> <context> <name>WindowMenu</name> <message> <location filename="../src/windowmenu.cpp" line="163"/> <source>Active connection(s)</source> <translation>Aktívne spojenie/a</translation> </message> <message> <location filename="../src/windowmenu.cpp" line="165"/> <source>Wi-Fi network(s)</source> <translation>Wi-Fi sieť/te</translation> </message> <message> <location filename="../src/windowmenu.cpp" line="167"/> <source>Known connection(s)</source> <translation>Známe spojenie/a</translation> </message> </context> </TS> 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!483 blocks
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor