From e995685ecd3a755339d1ed2a71476d05be9bc65d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sat, 11 Apr 2015 22:43:34 +0200 Subject: [PATCH 001/104] Update singleapplication (use of a qt5 alternative) --- 3rdparty/qtsingleapplication/CMakeLists.txt | 27 - 3rdparty/qtsingleapplication/LICENSE.LGPL | 504 ------------------ 3rdparty/qtsingleapplication/QtLockedFile | 1 - .../qtsingleapplication/QtSingleApplication | 1 - 3rdparty/qtsingleapplication/qtlocalpeer.cpp | 218 -------- 3rdparty/qtsingleapplication/qtlocalpeer.h | 85 --- 3rdparty/qtsingleapplication/qtlockedfile.cpp | 199 ------- 3rdparty/qtsingleapplication/qtlockedfile.h | 101 ---- .../qtsingleapplication/qtlockedfile_unix.cpp | 121 ----- .../qtsingleapplication/qtlockedfile_win.cpp | 213 -------- .../qtsingleapplication.cpp | 369 ------------- .../qtsingleapplication/qtsingleapplication.h | 109 ---- .../qtsingleapplication.patch | 231 -------- .../qtsinglecoreapplication.cpp | 169 ------ .../qtsinglecoreapplication.h | 77 --- 3rdparty/singleapplication/CMakeLists.txt | 20 + 3rdparty/singleapplication/LICENSE | 21 + .../singleapplication/singleapplication.cpp | 48 ++ .../singleapplication/singleapplication.h | 32 ++ .../singlecoreapplication.cpp | 48 ++ .../singleapplication/singlecoreapplication.h | 32 ++ 21 files changed, 201 insertions(+), 2425 deletions(-) delete mode 100644 3rdparty/qtsingleapplication/CMakeLists.txt delete mode 100644 3rdparty/qtsingleapplication/LICENSE.LGPL delete mode 100644 3rdparty/qtsingleapplication/QtLockedFile delete mode 100644 3rdparty/qtsingleapplication/QtSingleApplication delete mode 100644 3rdparty/qtsingleapplication/qtlocalpeer.cpp delete mode 100644 3rdparty/qtsingleapplication/qtlocalpeer.h delete mode 100644 3rdparty/qtsingleapplication/qtlockedfile.cpp delete mode 100644 3rdparty/qtsingleapplication/qtlockedfile.h delete mode 100644 3rdparty/qtsingleapplication/qtlockedfile_unix.cpp delete mode 100644 3rdparty/qtsingleapplication/qtlockedfile_win.cpp delete mode 100644 3rdparty/qtsingleapplication/qtsingleapplication.cpp delete mode 100644 3rdparty/qtsingleapplication/qtsingleapplication.h delete mode 100644 3rdparty/qtsingleapplication/qtsingleapplication.patch delete mode 100644 3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp delete mode 100644 3rdparty/qtsingleapplication/qtsinglecoreapplication.h create mode 100644 3rdparty/singleapplication/CMakeLists.txt create mode 100644 3rdparty/singleapplication/LICENSE create mode 100644 3rdparty/singleapplication/singleapplication.cpp create mode 100644 3rdparty/singleapplication/singleapplication.h create mode 100644 3rdparty/singleapplication/singlecoreapplication.cpp create mode 100644 3rdparty/singleapplication/singlecoreapplication.h diff --git a/3rdparty/qtsingleapplication/CMakeLists.txt b/3rdparty/qtsingleapplication/CMakeLists.txt deleted file mode 100644 index 1d78baba4..000000000 --- a/3rdparty/qtsingleapplication/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -cmake_minimum_required(VERSION 2.6) - -set(SINGLEAPP-SOURCES - qtlocalpeer.cpp - qtlockedfile.cpp - qtsingleapplication.cpp - qtsinglecoreapplication.cpp -) - -set(SINGLEAPP-MOC-HEADERS - qtlocalpeer.h - qtsingleapplication.h - qtsinglecoreapplication.h -) - -if(WIN32) - set(SINGLEAPP-SOURCES ${SINGLEAPP-SOURCES} qtlockedfile_win.cpp) -elseif(WIN32) - set(SINGLEAPP-SOURCES ${SINGLEAPP-SOURCES} qtlockedfile_unix.cpp) -endif(WIN32) - -QT4_WRAP_CPP(SINGLEAPP-SOURCES-MOC ${SINGLEAPP-MOC-HEADERS}) - -ADD_LIBRARY(qtsingleapplication STATIC - ${SINGLEAPP-SOURCES} - ${SINGLEAPP-SOURCES-MOC} -) diff --git a/3rdparty/qtsingleapplication/LICENSE.LGPL b/3rdparty/qtsingleapplication/LICENSE.LGPL deleted file mode 100644 index 5ab7695ab..000000000 --- a/3rdparty/qtsingleapplication/LICENSE.LGPL +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 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. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -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 and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, 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 library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete 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 distribute a copy of this License along with the -Library. - - 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 Library or any portion -of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -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 Library, 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 Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you 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. - - If distribution of 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 satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be 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. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library 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. - - 9. 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 Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -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 with -this License. - - 11. 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 Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library 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 Library. - -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. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library 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. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser 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 Library -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 Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -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 - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "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 -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. 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 LIBRARY 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 -LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. 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. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; 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. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/3rdparty/qtsingleapplication/QtLockedFile b/3rdparty/qtsingleapplication/QtLockedFile deleted file mode 100644 index 16b48ba9d..000000000 --- a/3rdparty/qtsingleapplication/QtLockedFile +++ /dev/null @@ -1 +0,0 @@ -#include "qtlockedfile.h" diff --git a/3rdparty/qtsingleapplication/QtSingleApplication b/3rdparty/qtsingleapplication/QtSingleApplication deleted file mode 100644 index d111bf72d..000000000 --- a/3rdparty/qtsingleapplication/QtSingleApplication +++ /dev/null @@ -1 +0,0 @@ -#include "qtsingleapplication.h" diff --git a/3rdparty/qtsingleapplication/qtlocalpeer.cpp b/3rdparty/qtsingleapplication/qtlocalpeer.cpp deleted file mode 100644 index c0b6b81b6..000000000 --- a/3rdparty/qtsingleapplication/qtlocalpeer.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/**************************************************************************** -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact Nokia at qt-info@nokia.com. -** -****************************************************************************/ - - -#include "qtlocalpeer.h" -#include -#include -#include - -#if defined(Q_OS_WIN) -#include -#include -typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); -static PProcessIdToSessionId pProcessIdToSessionId = 0; -#endif -#if defined(Q_OS_UNIX) -#include -#endif - -#include "qtlockedfile.cpp" -#if defined(Q_OS_WIN) -#include "qtlockedfile_win.cpp" -#else -#include "qtlockedfile_unix.cpp" -#endif - -const char* QtLocalPeer::ack = "ack"; - -QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId) - : QObject(parent), id(appId) -{ - QString prefix = id; - if (id.isEmpty()) { - id = QCoreApplication::applicationFilePath(); -#if defined(Q_OS_WIN) - id = id.toLower(); -#endif - prefix = id.section(QLatin1Char('/'), -1); - } - prefix.remove(QRegExp("[^a-zA-Z]")); - prefix.truncate(6); - - QByteArray idc = id.toUtf8(); - quint16 idNum = qChecksum(idc.constData(), idc.size()); - socketName = QLatin1String("qtsingleapp-") + prefix - + QLatin1Char('-') + QString::number(idNum, 16); - -#if defined(Q_OS_WIN) - if (!pProcessIdToSessionId) { - QLibrary lib("kernel32"); - pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); - } - if (pProcessIdToSessionId) { - DWORD sessionId = 0; - pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); - socketName += QLatin1Char('-') + QString::number(sessionId, 16); - } -#else - socketName += QLatin1Char('-') + QString::number(::getuid(), 16); -#endif - - server = new QLocalServer(this); - QString lockName = QDir(QDir::tempPath()).absolutePath() - + QLatin1Char('/') + socketName - + QLatin1String("-lockfile"); - lockFile.setFileName(lockName); - lockFileCreated = !lockFile.exists(); - lockFile.open(QIODevice::ReadWrite); -} - - - -bool QtLocalPeer::isClient() -{ - if (lockFile.isLocked()) - return false; - - if (!lockFile.lock(QtLockedFile::WriteLock, false)) - return true; - - bool res = server->listen(socketName); -#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0)) - // ### Workaround - if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { - QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); - res = server->listen(socketName); - } -#endif - if (!res) - qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); - QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection())); - return false; -} - - -bool QtLocalPeer::sendMessage(const QString &message, int timeout) -{ - return sendMessage(message.toUtf8(), timeout); -} - -bool QtLocalPeer::sendMessage(const char* message, int timeout) -{ - return sendMessage(QByteArray(message), timeout); -} - -bool QtLocalPeer::sendMessage(const QByteArray &message, int timeout) -{ - if (!isClient()) - return false; - - QLocalSocket socket; - bool connOk = false; - for(int i = 0; i < 2; i++) { - // Try twice, in case the other instance is just starting up - socket.connectToServer(socketName); - connOk = socket.waitForConnected(timeout/2); - if (connOk || i) - break; - int ms = 250; -#if defined(Q_OS_WIN) - Sleep(DWORD(ms)); -#else - struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; - nanosleep(&ts, NULL); -#endif - } - if (!connOk) - return false; - - QDataStream ds(&socket); - ds.writeBytes(message.constData(), message.size()); - bool res = socket.waitForBytesWritten(timeout); - res &= socket.waitForReadyRead(timeout); // wait for ack - res &= (socket.read(qstrlen(ack)) == ack); - return res; -} - - -void QtLocalPeer::receiveConnection() -{ - QLocalSocket* socket = server->nextPendingConnection(); - if (!socket) - return; - - while (socket->bytesAvailable() < (int)sizeof(quint32)) - socket->waitForReadyRead(); - QDataStream ds(socket); - QByteArray uMsg; - quint32 remaining; - ds >> remaining; - uMsg.resize(remaining); - int got = 0; - char* uMsgBuf = uMsg.data(); - do { - got = ds.readRawData(uMsgBuf, remaining); - remaining -= got; - uMsgBuf += got; - } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); - if (got < 0) { - qWarning() << "QtLocalPeer: Message reception failed" << socket->errorString(); - delete socket; - return; - } - socket->write(ack, qstrlen(ack)); - socket->waitForBytesWritten(1000); - delete socket; - emit messageReceived(uMsg); //### (might take a long time to return) - emit messageReceived(QString::fromUtf8(uMsg)); -} - -QtLocalPeer::~QtLocalPeer () -{ - if (lockFileCreated) - lockFile.remove(); -} diff --git a/3rdparty/qtsingleapplication/qtlocalpeer.h b/3rdparty/qtsingleapplication/qtlocalpeer.h deleted file mode 100644 index 82b894633..000000000 --- a/3rdparty/qtsingleapplication/qtlocalpeer.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact Nokia at qt-info@nokia.com. -** -****************************************************************************/ - - -#include -#include -#include - -#include "qtlockedfile.h" - -class QtLocalPeer : public QObject -{ - Q_OBJECT - -public: - QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); - ~QtLocalPeer (); - bool isClient(); - bool sendMessage(const QString &message, int timeout); - bool sendMessage(const QByteArray &message, int timeout); - bool sendMessage(const char* message, int timeout); - QString applicationId() const - { return id; } - -Q_SIGNALS: - void messageReceived(const QString &message); - void messageReceived(const QByteArray &message); - void messageReceived(const char* message); - -protected Q_SLOTS: - void receiveConnection(); - -protected: - QString id; - QString socketName; - QLocalServer* server; - QtLockedFile lockFile; - -private: - static const char* ack; - bool lockFileCreated; -}; diff --git a/3rdparty/qtsingleapplication/qtlockedfile.cpp b/3rdparty/qtsingleapplication/qtlockedfile.cpp deleted file mode 100644 index 2cf080584..000000000 --- a/3rdparty/qtsingleapplication/qtlockedfile.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/**************************************************************************** -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact Nokia at qt-info@nokia.com. -** -****************************************************************************/ - -#include "qtlockedfile.h" - -/*! - \class QtLockedFile - - \brief The QtLockedFile class extends QFile with advisory locking - functions. - - A file may be locked in read or write mode. Multiple instances of - \e QtLockedFile, created in multiple processes running on the same - machine, may have a file locked in read mode. Exactly one instance - may have it locked in write mode. A read and a write lock cannot - exist simultaneously on the same file. - - The file locks are advisory. This means that nothing prevents - another process from manipulating a locked file using QFile or - file system functions offered by the OS. Serialization is only - guaranteed if all processes that access the file use - QLockedFile. Also, while holding a lock on a file, a process - must not open the same file again (through any API), or locks - can be unexpectedly lost. - - The lock provided by an instance of \e QtLockedFile is released - whenever the program terminates. This is true even when the - program crashes and no destructors are called. -*/ - -/*! \enum QtLockedFile::LockMode - - This enum describes the available lock modes. - - \value ReadLock A read lock. - \value WriteLock A write lock. - \value NoLock Neither a read lock nor a write lock. -*/ - -/*! - Constructs an unlocked \e QtLockedFile object. This constructor - behaves in the same way as \e QFile::QFile(). - - \sa QFile::QFile() -*/ -QtLockedFile::QtLockedFile() - : QFile() -{ -#ifdef Q_OS_WIN - wmutex = 0; - rmutex = 0; -#endif - m_lock_mode = NoLock; -} - -/*! - Constructs an unlocked QtLockedFile object with file \a name. This - constructor behaves in the same way as \e QFile::QFile(const - QString&). - - \sa QFile::QFile() -*/ -QtLockedFile::QtLockedFile(const QString &name) - : QFile(name) -{ -#ifdef Q_OS_WIN - wmutex = 0; - rmutex = 0; -#endif - m_lock_mode = NoLock; -} - -/*! - Opens the file in OpenMode \a mode. - - This is identical to QFile::open(), with the one exception that the - Truncate mode flag is disallowed. Truncation would conflict with the - advisory file locking, since the file would be modified before the - write lock is obtained. If truncation is required, use resize(0) - after obtaining the write lock. - - Returns true if successful; otherwise false. - - \sa QFile::open(), QFile::resize() -*/ -bool QtLockedFile::open(OpenMode mode) -{ - if (mode & QIODevice::Truncate) { - qWarning("QtLockedFile::open(): Truncate mode not allowed."); - return false; - } - return QFile::open(mode); -} - -/*! - Returns \e true if this object has a in read or write lock; - otherwise returns \e false. - - \sa lockMode() -*/ -bool QtLockedFile::isLocked() const -{ - return m_lock_mode != NoLock; -} - -/*! - Returns the type of lock currently held by this object, or \e - QtLockedFile::NoLock. - - \sa isLocked() -*/ -QtLockedFile::LockMode QtLockedFile::lockMode() const -{ - return m_lock_mode; -} - -/*! - \fn bool QtLockedFile::lock(LockMode mode, bool block = true) - - Obtains a lock of type \a mode. The file must be opened before it - can be locked. - - If \a block is true, this function will block until the lock is - aquired. If \a block is false, this function returns \e false - immediately if the lock cannot be aquired. - - If this object already has a lock of type \a mode, this function - returns \e true immediately. If this object has a lock of a - different type than \a mode, the lock is first released and then a - new lock is obtained. - - This function returns \e true if, after it executes, the file is - locked by this object, and \e false otherwise. - - \sa unlock(), isLocked(), lockMode() -*/ - -/*! - \fn bool QtLockedFile::unlock() - - Releases a lock. - - If the object has no lock, this function returns immediately. - - This function returns \e true if, after it executes, the file is - not locked by this object, and \e false otherwise. - - \sa lock(), isLocked(), lockMode() -*/ - -/*! - \fn QtLockedFile::~QtLockedFile() - - Destroys the \e QtLockedFile object. If any locks were held, they - are released. -*/ diff --git a/3rdparty/qtsingleapplication/qtlockedfile.h b/3rdparty/qtsingleapplication/qtlockedfile.h deleted file mode 100644 index 1d3b918ec..000000000 --- a/3rdparty/qtsingleapplication/qtlockedfile.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact Nokia at qt-info@nokia.com. -** -****************************************************************************/ - -#ifndef QTLOCKEDFILE_H -#define QTLOCKEDFILE_H - -#include -#ifdef Q_OS_WIN -#include -#endif - -#if defined(Q_WS_WIN) -# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) -# define QT_QTLOCKEDFILE_EXPORT -# elif defined(QT_QTLOCKEDFILE_IMPORT) -# if defined(QT_QTLOCKEDFILE_EXPORT) -# undef QT_QTLOCKEDFILE_EXPORT -# endif -# define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) -# elif defined(QT_QTLOCKEDFILE_EXPORT) -# undef QT_QTLOCKEDFILE_EXPORT -# define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) -# endif -#else -# define QT_QTLOCKEDFILE_EXPORT -#endif - -class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile -{ -public: - enum LockMode { NoLock = 0, ReadLock, WriteLock }; - - QtLockedFile(); - QtLockedFile(const QString &name); - ~QtLockedFile(); - - bool open(OpenMode mode); - - bool lock(LockMode mode, bool block = true); - bool unlock(); - bool isLocked() const; - LockMode lockMode() const; - -private: -#ifdef Q_OS_WIN - Qt::HANDLE wmutex; - Qt::HANDLE rmutex; - QVector rmutexes; - QString mutexname; - - Qt::HANDLE getMutexHandle(int idx, bool doCreate); - bool waitMutex(Qt::HANDLE mutex, bool doBlock); - -#endif - LockMode m_lock_mode; -}; - -#endif diff --git a/3rdparty/qtsingleapplication/qtlockedfile_unix.cpp b/3rdparty/qtsingleapplication/qtlockedfile_unix.cpp deleted file mode 100644 index 2881bdd2c..000000000 --- a/3rdparty/qtsingleapplication/qtlockedfile_unix.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact Nokia at qt-info@nokia.com. -** -****************************************************************************/ - -#include -#include -#include -#include - -#include "qtlockedfile.h" - -bool QtLockedFile::lock(LockMode mode, bool block) -{ - if (!isOpen()) { - qWarning("QtLockedFile::lock(): file is not opened"); - return false; - } - - if (mode == NoLock) - return unlock(); - - if (mode == m_lock_mode) - return true; - - if (m_lock_mode != NoLock) - unlock(); - - struct flock fl; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; - int cmd = block ? F_SETLKW : F_SETLK; - int ret = fcntl(handle(), cmd, &fl); - - if (ret == -1) { - if (errno != EINTR && errno != EAGAIN) - qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); - return false; - } - - - m_lock_mode = mode; - return true; -} - - -bool QtLockedFile::unlock() -{ - if (!isOpen()) { - qWarning("QtLockedFile::unlock(): file is not opened"); - return false; - } - - if (!isLocked()) - return true; - - struct flock fl; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_UNLCK; - int ret = fcntl(handle(), F_SETLKW, &fl); - - if (ret == -1) { - qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); - return false; - } - - m_lock_mode = NoLock; - return true; -} - -QtLockedFile::~QtLockedFile() -{ - if (isOpen()) - unlock(); -} - diff --git a/3rdparty/qtsingleapplication/qtlockedfile_win.cpp b/3rdparty/qtsingleapplication/qtlockedfile_win.cpp deleted file mode 100644 index f41bb67d8..000000000 --- a/3rdparty/qtsingleapplication/qtlockedfile_win.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/**************************************************************************** -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact Nokia at qt-info@nokia.com. -** -****************************************************************************/ - -#include "qtlockedfile.h" -#include -#include - -#define MUTEX_PREFIX "QtLockedFile mutex " -// Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS -#define MAX_READERS MAXIMUM_WAIT_OBJECTS - -Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) -{ - if (mutexname.isEmpty()) { - QFileInfo fi(*this); - mutexname = QString::fromLatin1(MUTEX_PREFIX) - + fi.absoluteFilePath().toLower(); - } - QString mname(mutexname); - if (idx >= 0) - mname += QString::number(idx); - - Qt::HANDLE mutex; - if (doCreate) { - QT_WA( { mutex = CreateMutexW(NULL, FALSE, (WCHAR*)mname.utf16()); }, - { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } ); - if (!mutex) { - qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); - return 0; - } - } - else { - QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (WCHAR*)mname.utf16()); }, - { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } ); - if (!mutex) { - if (GetLastError() != ERROR_FILE_NOT_FOUND) - qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); - return 0; - } - } - return mutex; -} - -bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock) -{ - Q_ASSERT(mutex); - DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); - switch (res) { - case WAIT_OBJECT_0: - case WAIT_ABANDONED: - return true; - break; - case WAIT_TIMEOUT: - break; - default: - qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); - } - return false; -} - - - -bool QtLockedFile::lock(LockMode mode, bool block) -{ - if (!isOpen()) { - qWarning("QtLockedFile::lock(): file is not opened"); - return false; - } - - if (mode == NoLock) - return unlock(); - - if (mode == m_lock_mode) - return true; - - if (m_lock_mode != NoLock) - unlock(); - - if (!wmutex && !(wmutex = getMutexHandle(-1, true))) - return false; - - if (!waitMutex(wmutex, block)) - return false; - - if (mode == ReadLock) { - int idx = 0; - for (; idx < MAX_READERS; idx++) { - rmutex = getMutexHandle(idx, false); - if (!rmutex || waitMutex(rmutex, false)) - break; - CloseHandle(rmutex); - } - bool ok = true; - if (idx >= MAX_READERS) { - qWarning("QtLockedFile::lock(): too many readers"); - rmutex = 0; - ok = false; - } - else if (!rmutex) { - rmutex = getMutexHandle(idx, true); - if (!rmutex || !waitMutex(rmutex, false)) - ok = false; - } - if (!ok && rmutex) { - CloseHandle(rmutex); - rmutex = 0; - } - ReleaseMutex(wmutex); - if (!ok) - return false; - } - else { - Q_ASSERT(rmutexes.isEmpty()); - for (int i = 0; i < MAX_READERS; i++) { - Qt::HANDLE mutex = getMutexHandle(i, false); - if (mutex) - rmutexes.append(mutex); - } - if (rmutexes.size()) { - DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), - TRUE, block ? INFINITE : 0); - if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { - if (res != WAIT_TIMEOUT) - qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); - m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky - unlock(); - return false; - } - } - } - - m_lock_mode = mode; - return true; -} - -bool QtLockedFile::unlock() -{ - if (!isOpen()) { - qWarning("QtLockedFile::unlock(): file is not opened"); - return false; - } - - if (!isLocked()) - return true; - - if (m_lock_mode == ReadLock) { - ReleaseMutex(rmutex); - CloseHandle(rmutex); - rmutex = 0; - } - else { - foreach(Qt::HANDLE mutex, rmutexes) { - ReleaseMutex(mutex); - CloseHandle(mutex); - } - rmutexes.clear(); - ReleaseMutex(wmutex); - } - - m_lock_mode = QtLockedFile::NoLock; - return true; -} - -QtLockedFile::~QtLockedFile() -{ - if (isOpen()) - unlock(); - if (wmutex) - CloseHandle(wmutex); -} diff --git a/3rdparty/qtsingleapplication/qtsingleapplication.cpp b/3rdparty/qtsingleapplication/qtsingleapplication.cpp deleted file mode 100644 index a7e19eed1..000000000 --- a/3rdparty/qtsingleapplication/qtsingleapplication.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/**************************************************************************** -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact Nokia at qt-info@nokia.com. -** -****************************************************************************/ - - -#include "qtsingleapplication.h" -#include "qtlocalpeer.h" -#include - - -/*! - \class QtSingleApplication qtsingleapplication.h - \brief The QtSingleApplication class provides an API to detect and - communicate with running instances of an application. - - This class allows you to create applications where only one - instance should be running at a time. I.e., if the user tries to - launch another instance, the already running instance will be - activated instead. Another usecase is a client-server system, - where the first started instance will assume the role of server, - and the later instances will act as clients of that server. - - By default, the full path of the executable file is used to - determine whether two processes are instances of the same - application. You can also provide an explicit identifier string - that will be compared instead. - - The application should create the QtSingleApplication object early - in the startup phase, and call isRunning() or sendMessage() to - find out if another instance of this application is already - running. Startup parameters (e.g. the name of the file the user - wanted this new instance to open) can be passed to the running - instance in the sendMessage() function. - - If isRunning() or sendMessage() returns false, it means that no - other instance is running, and this instance has assumed the role - as the running instance. The application should continue with the - initialization of the application user interface before entering - the event loop with exec(), as normal. The messageReceived() - signal will be emitted when the application receives messages from - another instance of the same application. - - If isRunning() or sendMessage() returns true, another instance is - already running, and the application should terminate or enter - client mode. - - If a message is received it might be helpful to the user to raise - the application so that it becomes visible. To facilitate this, - QtSingleApplication provides the setActivationWindow() function - and the activateWindow() slot. - - Here's an example that shows how to convert an existing - application to use QtSingleApplication. It is very simple and does - not make use of all QtSingleApplication's functionality (see the - examples for that). - - \code - // Original - int main(int argc, char **argv) - { - QApplication app(argc, argv); - - MyMainWidget mmw; - - mmw.show(); - return app.exec(); - } - - // Single instance - int main(int argc, char **argv) - { - QtSingleApplication app(argc, argv); - - if (app.isRunning()) - return 0; - - MyMainWidget mmw; - - app.setActivationWindow(&mmw); - - mmw.show(); - return app.exec(); - } - \endcode - - Once this QtSingleApplication instance is destroyed(for example, - when the user quits), when the user next attempts to run the - application this instance will not, of course, be encountered. The - next instance to call isRunning() or sendMessage() will assume the - role as the new running instance. - - For console (non-GUI) applications, QtSingleCoreApplication may be - used instead of this class, to avoid the dependency on the QtGui - library. - - \sa QtSingleCoreApplication -*/ - - -void QtSingleApplication::sysInit(const QString &appId) -{ - actWin = 0; - peer = new QtLocalPeer(this, appId); - connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); - connect(peer, SIGNAL(messageReceived(const QByteArray&)), SIGNAL(messageReceived(const QByteArray&))); - connect(peer, SIGNAL(messageReceived(const char*)), SIGNAL(messageReceived(const char*))); -} - - -/*! - Creates a QtSingleApplication object. The application identifier - will be QCoreApplication::applicationFilePath(). \a argc, \a - argv, and \a GUIenabled are passed on to the QAppliation constructor. - - If you are creating a console application (i.e. setting \a - GUIenabled to false), you may consider using - QtSingleCoreApplication instead. -*/ - -QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled) - : QApplication(argc, argv, GUIenabled) -{ - sysInit(); -} - - -/*! - Creates a QtSingleApplication object with the application - identifier \a appId. \a argc and \a argv are passed on to the - QAppliation constructor. -*/ - -QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv) - : QApplication(argc, argv) -{ - sysInit(appId); -} - - -/*! - Creates a QtSingleApplication object. The application identifier - will be QCoreApplication::applicationFilePath(). \a argc, \a - argv, and \a type are passed on to the QAppliation constructor. -*/ -QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type) - : QApplication(argc, argv, type) -{ - sysInit(); -} - - -#if defined(Q_WS_X11) -/*! - Special constructor for X11, ref. the documentation of - QApplication's corresponding constructor. The application identifier - will be QCoreApplication::applicationFilePath(). \a dpy, \a visual, - and \a cmap are passed on to the QApplication constructor. -*/ -QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, visual, cmap) -{ - sysInit(); -} - -/*! - Special constructor for X11, ref. the documentation of - QApplication's corresponding constructor. The application identifier - will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a - argv, \a visual, and \a cmap are passed on to the QApplication - constructor. -*/ -QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, argc, argv, visual, cmap) -{ - sysInit(); -} - -/*! - Special constructor for X11, ref. the documentation of - QApplication's corresponding constructor. The application identifier - will be \a appId. \a dpy, \a argc, \a - argv, \a visual, and \a cmap are passed on to the QApplication - constructor. -*/ -QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, argc, argv, visual, cmap) -{ - sysInit(appId); -} -#endif - - -/*! - Returns true if another instance of this application is running; - otherwise false. - - This function does not find instances of this application that are - being run by a different user (on Windows: that are running in - another session). - - \sa sendMessage() -*/ - -bool QtSingleApplication::isRunning() -{ - return peer->isClient(); -} - - -/*! - Tries to send the text \a message to the currently running - instance. The QtSingleApplication object in the running instance - will emit the messageReceived() signal when it receives the - message. - - This function returns true if the message has been sent to, and - processed by, the current instance. If there is no instance - currently running, or if the running instance fails to process the - message within \a timeout milliseconds, this function return false. - - \sa isRunning(), messageReceived() -*/ -bool QtSingleApplication::sendMessage(const QString &message, int timeout) -{ - return peer->sendMessage(message, timeout); -} - -bool QtSingleApplication::sendMessage(const QByteArray &message, int timeout) -{ - return peer->sendMessage(message, timeout); -} - -bool QtSingleApplication::sendMessage(const char* message, int timeout) -{ - return peer->sendMessage(message, timeout); -} - - -/*! - Returns the application identifier. Two processes with the same - identifier will be regarded as instances of the same application. -*/ -QString QtSingleApplication::id() const -{ - return peer->applicationId(); -} - - -/*! - Sets the activation window of this application to \a aw. The - activation window is the widget that will be activated by - activateWindow(). This is typically the application's main window. - - If \a activateOnMessage is true (the default), the window will be - activated automatically every time a message is received, just prior - to the messageReceived() signal being emitted. - - \sa activateWindow(), messageReceived() -*/ - -void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage) -{ - actWin = aw; - if (activateOnMessage) { - connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); - connect(peer, SIGNAL(messageReceived(const QByteArray&)), this, SLOT(activateWindow())); - connect(peer, SIGNAL(messageReceived(const char*)), this, SLOT(activateWindow())); - } - else { - disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); - disconnect(peer, SIGNAL(messageReceived(const QByteArray&)), this, SLOT(activateWindow())); - disconnect(peer, SIGNAL(messageReceived(const char*)), this, SLOT(activateWindow())); - } -} - - -/*! - Returns the applications activation window if one has been set by - calling setActivationWindow(), otherwise returns 0. - - \sa setActivationWindow() -*/ -QWidget* QtSingleApplication::activationWindow() const -{ - return actWin; -} - - -/*! - De-minimizes, raises, and activates this application's activation window. - This function does nothing if no activation window has been set. - - This is a convenience function to show the user that this - application instance has been activated when he has tried to start - another instance. - - This function should typically be called in response to the - messageReceived() signal. By default, that will happen - automatically, if an activation window has been set. - - \sa setActivationWindow(), messageReceived(), initialize() -*/ -void QtSingleApplication::activateWindow() -{ - if (actWin) { - actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); - actWin->raise(); - actWin->activateWindow(); - } -} - - -/*! - \fn void QtSingleApplication::messageReceived(const QString& message) - - This signal is emitted when the current instance receives a \a - message from another instance of this application. - - \sa sendMessage(), setActivationWindow(), activateWindow() -*/ - - -/*! - \fn void QtSingleApplication::initialize(bool dummy = true) - - \obsolete -*/ diff --git a/3rdparty/qtsingleapplication/qtsingleapplication.h b/3rdparty/qtsingleapplication/qtsingleapplication.h deleted file mode 100644 index ba0507cb8..000000000 --- a/3rdparty/qtsingleapplication/qtsingleapplication.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact Nokia at qt-info@nokia.com. -** -****************************************************************************/ - - -#include - -class QtLocalPeer; - -#if defined(Q_WS_WIN) -# if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) -# define QT_QTSINGLEAPPLICATION_EXPORT -# elif defined(QT_QTSINGLEAPPLICATION_IMPORT) -# if defined(QT_QTSINGLEAPPLICATION_EXPORT) -# undef QT_QTSINGLEAPPLICATION_EXPORT -# endif -# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport) -# elif defined(QT_QTSINGLEAPPLICATION_EXPORT) -# undef QT_QTSINGLEAPPLICATION_EXPORT -# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport) -# endif -#else -# define QT_QTSINGLEAPPLICATION_EXPORT -#endif - -class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication -{ - Q_OBJECT - -public: - QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); - QtSingleApplication(const QString &id, int &argc, char **argv); - QtSingleApplication(int &argc, char **argv, Type type); -#if defined(Q_WS_X11) - QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); - QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); - QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); -#endif - - bool isRunning(); - QString id() const; - - void setActivationWindow(QWidget* aw, bool activateOnMessage = true); - QWidget* activationWindow() const; - - // Obsolete: - void initialize(bool dummy = true) - { isRunning(); Q_UNUSED(dummy) } - -public Q_SLOTS: - bool sendMessage(const QString &message, int timeout = 5000); - bool sendMessage(const QByteArray &message, int timeout = 5000); - bool sendMessage(const char* message, int timeout = 5000); - void activateWindow(); - - -Q_SIGNALS: - void messageReceived(const QString &message); - void messageReceived(const QByteArray &message); - void messageReceived(const char* message); - - -private: - void sysInit(const QString &appId = QString()); - QtLocalPeer *peer; - QWidget *actWin; -}; diff --git a/3rdparty/qtsingleapplication/qtsingleapplication.patch b/3rdparty/qtsingleapplication/qtsingleapplication.patch deleted file mode 100644 index a65e64ac7..000000000 --- a/3rdparty/qtsingleapplication/qtsingleapplication.patch +++ /dev/null @@ -1,231 +0,0 @@ -diff -ur /home/david/qtsingleapplication-2.6_1-opensource/src/qtlocalpeer.cpp qtsingleapplication/qtlocalpeer.cpp ---- /home/david/qtsingleapplication-2.6_1-opensource/src/qtlocalpeer.cpp 2009-12-16 10:43:33.000000000 +0000 -+++ qtsingleapplication/qtlocalpeer.cpp 2010-07-10 16:26:50.000000000 +0100 -@@ -48,6 +48,7 @@ - #include "qtlocalpeer.h" - #include - #include -+#include - - #if defined(Q_OS_WIN) - #include -@@ -59,14 +60,12 @@ - #include - #endif - --namespace QtLP_Private { - #include "qtlockedfile.cpp" - #if defined(Q_OS_WIN) - #include "qtlockedfile_win.cpp" - #else - #include "qtlockedfile_unix.cpp" - #endif --} - - const char* QtLocalPeer::ack = "ack"; - -@@ -118,7 +117,7 @@ - if (lockFile.isLocked()) - return false; - -- if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) -+ if (!lockFile.lock(QtLockedFile::WriteLock, false)) - return true; - - bool res = server->listen(socketName); -@@ -138,6 +137,11 @@ - - bool QtLocalPeer::sendMessage(const QString &message, int timeout) - { -+ return sendMessage(message.toUtf8(), timeout); -+} -+ -+bool QtLocalPeer::sendMessage(const QByteArray &message, int timeout) -+{ - if (!isClient()) - return false; - -@@ -160,9 +164,8 @@ - if (!connOk) - return false; - -- QByteArray uMsg(message.toUtf8()); - QDataStream ds(&socket); -- ds.writeBytes(uMsg.constData(), uMsg.size()); -+ ds.writeBytes(message.constData(), message.size()); - bool res = socket.waitForBytesWritten(timeout); - res &= socket.waitForReadyRead(timeout); // wait for ack - res &= (socket.read(qstrlen(ack)) == ack); -@@ -195,9 +198,9 @@ - delete socket; - return; - } -- QString message(QString::fromUtf8(uMsg)); - socket->write(ack, qstrlen(ack)); - socket->waitForBytesWritten(1000); - delete socket; -- emit messageReceived(message); //### (might take a long time to return) -+ emit messageReceived(uMsg); //### (might take a long time to return) -+ emit messageReceived(QString::fromUtf8(uMsg)); - } -diff -ur /home/david/qtsingleapplication-2.6_1-opensource/src/qtlocalpeer.h qtsingleapplication/qtlocalpeer.h ---- /home/david/qtsingleapplication-2.6_1-opensource/src/qtlocalpeer.h 2009-12-16 10:43:33.000000000 +0000 -+++ qtsingleapplication/qtlocalpeer.h 2010-07-10 16:26:16.000000000 +0100 -@@ -49,9 +49,7 @@ - #include - #include - --namespace QtLP_Private { - #include "qtlockedfile.h" --} - - class QtLocalPeer : public QObject - { -@@ -61,11 +59,13 @@ - QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); - bool isClient(); - bool sendMessage(const QString &message, int timeout); -+ bool sendMessage(const QByteArray &message, int timeout); - QString applicationId() const - { return id; } - - Q_SIGNALS: - void messageReceived(const QString &message); -+ void messageReceived(const QByteArray &message); - - protected Q_SLOTS: - void receiveConnection(); -@@ -74,7 +74,7 @@ - QString id; - QString socketName; - QLocalServer* server; -- QtLP_Private::QtLockedFile lockFile; -+ QtLockedFile lockFile; - - private: - static const char* ack; -diff -ur /home/david/qtsingleapplication-2.6_1-opensource/src/qtlockedfile_win.cpp qtsingleapplication/qtlockedfile_win.cpp ---- /home/david/qtsingleapplication-2.6_1-opensource/src/qtlockedfile_win.cpp 2009-12-16 10:43:33.000000000 +0000 -+++ qtsingleapplication/qtlockedfile_win.cpp 2010-07-10 16:26:33.000000000 +0100 -@@ -65,7 +65,7 @@ - - Qt::HANDLE mutex; - if (doCreate) { -- QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); }, -+ QT_WA( { mutex = CreateMutexW(NULL, FALSE, (WCHAR*)mname.utf16()); }, - { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } ); - if (!mutex) { - qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); -@@ -73,7 +73,7 @@ - } - } - else { -- QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); }, -+ QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (WCHAR*)mname.utf16()); }, - { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } ); - if (!mutex) { - if (GetLastError() != ERROR_FILE_NOT_FOUND) -diff -ur /home/david/qtsingleapplication-2.6_1-opensource/src/qtsingleapplication.cpp qtsingleapplication/qtsingleapplication.cpp ---- /home/david/qtsingleapplication-2.6_1-opensource/src/qtsingleapplication.cpp 2009-12-16 10:43:33.000000000 +0000 -+++ qtsingleapplication/qtsingleapplication.cpp 2010-07-10 16:23:53.000000000 +0100 -@@ -144,6 +144,7 @@ - actWin = 0; - peer = new QtLocalPeer(this, appId); - connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); -+ connect(peer, SIGNAL(messageReceived(const QByteArray&)), SIGNAL(messageReceived(const QByteArray&))); - } - - -@@ -265,6 +266,11 @@ - return peer->sendMessage(message, timeout); - } - -+bool QtSingleApplication::sendMessage(const QByteArray &message, int timeout) -+{ -+ return peer->sendMessage(message, timeout); -+} -+ - - /*! - Returns the application identifier. Two processes with the same -@@ -291,10 +297,14 @@ - void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage) - { - actWin = aw; -- if (activateOnMessage) -+ if (activateOnMessage) { - connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); -- else -+ connect(peer, SIGNAL(messageReceived(const QByteArray&)), this, SLOT(activateWindow())); -+ } -+ else { - disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); -+ disconnect(peer, SIGNAL(messageReceived(const QByteArray&)), this, SLOT(activateWindow())); -+ } - } - - -diff -ur /home/david/qtsingleapplication-2.6_1-opensource/src/qtsingleapplication.h qtsingleapplication/qtsingleapplication.h ---- /home/david/qtsingleapplication-2.6_1-opensource/src/qtsingleapplication.h 2009-12-16 10:43:33.000000000 +0000 -+++ qtsingleapplication/qtsingleapplication.h 2010-07-10 16:23:53.000000000 +0100 -@@ -91,11 +91,13 @@ - - public Q_SLOTS: - bool sendMessage(const QString &message, int timeout = 5000); -+ bool sendMessage(const QByteArray &message, int timeout = 5000); - void activateWindow(); - - - Q_SIGNALS: - void messageReceived(const QString &message); -+ void messageReceived(const QByteArray &message); - - - private: -diff -ur /home/david/qtsingleapplication-2.6_1-opensource/src/qtsinglecoreapplication.cpp qtsingleapplication/qtsinglecoreapplication.cpp ---- /home/david/qtsingleapplication-2.6_1-opensource/src/qtsinglecoreapplication.cpp 2009-12-16 10:43:33.000000000 +0000 -+++ qtsingleapplication/qtsinglecoreapplication.cpp 2010-07-10 16:32:33.000000000 +0100 -@@ -81,6 +81,7 @@ - { - peer = new QtLocalPeer(this); - connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); -+ connect(peer, SIGNAL(messageReceived(const QByteArray&)), SIGNAL(messageReceived(const QByteArray&))); - } - - -@@ -94,6 +95,7 @@ - { - peer = new QtLocalPeer(this, appId); - connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); -+ connect(peer, SIGNAL(messageReceived(const QByteArray&)), SIGNAL(messageReceived(const QByteArray&))); - } - - -@@ -133,6 +135,11 @@ - return peer->sendMessage(message, timeout); - } - -+bool QtSingleCoreApplication::sendMessage(const QByteArray &message, int timeout) -+{ -+ return peer->sendMessage(message, timeout); -+} -+ - - /*! - Returns the application identifier. Two processes with the same -diff -ur /home/david/qtsingleapplication-2.6_1-opensource/src/qtsinglecoreapplication.h qtsingleapplication/qtsinglecoreapplication.h ---- /home/david/qtsingleapplication-2.6_1-opensource/src/qtsinglecoreapplication.h 2009-12-16 10:43:33.000000000 +0000 -+++ qtsingleapplication/qtsinglecoreapplication.h 2010-07-10 16:32:33.000000000 +0100 -@@ -62,10 +62,12 @@ - - public Q_SLOTS: - bool sendMessage(const QString &message, int timeout = 5000); -+ bool sendMessage(const QByteArray &message, int timeout = 5000); - - - Q_SIGNALS: - void messageReceived(const QString &message); -+ void messageReceived(const QByteArray &message); - - - private: diff --git a/3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp b/3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp deleted file mode 100644 index 38e16584a..000000000 --- a/3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/**************************************************************************** -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact Nokia at qt-info@nokia.com. -** -****************************************************************************/ - - -#include "qtsinglecoreapplication.h" -#include "qtlocalpeer.h" - -/*! - \class QtSingleCoreApplication qtsinglecoreapplication.h - \brief A variant of the QtSingleApplication class for non-GUI applications. - - This class is a variant of QtSingleApplication suited for use in - console (non-GUI) applications. It is an extension of - QCoreApplication (instead of QApplication). It does not require - the QtGui library. - - The API and usage is identical to QtSingleApplication, except that - functions relating to the "activation window" are not present, for - obvious reasons. Please refer to the QtSingleApplication - documentation for explanation of the usage. - - A QtSingleCoreApplication instance can communicate to a - QtSingleApplication instance if they share the same application - id. Hence, this class can be used to create a light-weight - command-line tool that sends commands to a GUI application. - - \sa QtSingleApplication -*/ - -/*! - Creates a QtSingleCoreApplication object. The application identifier - will be QCoreApplication::applicationFilePath(). \a argc and \a - argv are passed on to the QCoreAppliation constructor. -*/ - -QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv) - : QCoreApplication(argc, argv) -{ - peer = new QtLocalPeer(this); - connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); - connect(peer, SIGNAL(messageReceived(const QByteArray&)), SIGNAL(messageReceived(const QByteArray&))); - connect(peer, SIGNAL(messageReceived(const char*)), SIGNAL(messageReceived(const char*))); -} - - -/*! - Creates a QtSingleCoreApplication object with the application - identifier \a appId. \a argc and \a argv are passed on to the - QCoreAppliation constructor. -*/ -QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv) - : QCoreApplication(argc, argv) -{ - peer = new QtLocalPeer(this, appId); - connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); - connect(peer, SIGNAL(messageReceived(const QByteArray&)), SIGNAL(messageReceived(const QByteArray&))); - connect(peer, SIGNAL(messageReceived(const char*)), SIGNAL(messageReceived(const char*))); -} - - -/*! - Returns true if another instance of this application is running; - otherwise false. - - This function does not find instances of this application that are - being run by a different user (on Windows: that are running in - another session). - - \sa sendMessage() -*/ - -bool QtSingleCoreApplication::isRunning() -{ - return peer->isClient(); -} - - -/*! - Tries to send the text \a message to the currently running - instance. The QtSingleCoreApplication object in the running instance - will emit the messageReceived() signal when it receives the - message. - - This function returns true if the message has been sent to, and - processed by, the current instance. If there is no instance - currently running, or if the running instance fails to process the - message within \a timeout milliseconds, this function return false. - - \sa isRunning(), messageReceived() -*/ - -bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout) -{ - return peer->sendMessage(message, timeout); -} - -bool QtSingleCoreApplication::sendMessage(const QByteArray &message, int timeout) -{ - return peer->sendMessage(message, timeout); -} - -bool QtSingleCoreApplication::sendMessage(const char* message, int timeout) -{ - return peer->sendMessage(message, timeout); -} - - -/*! - Returns the application identifier. Two processes with the same - identifier will be regarded as instances of the same application. -*/ - -QString QtSingleCoreApplication::id() const -{ - return peer->applicationId(); -} - - -/*! - \fn void QtSingleCoreApplication::messageReceived(const QString& message) - - This signal is emitted when the current instance receives a \a - message from another instance of this application. - - \sa sendMessage() -*/ diff --git a/3rdparty/qtsingleapplication/qtsinglecoreapplication.h b/3rdparty/qtsingleapplication/qtsinglecoreapplication.h deleted file mode 100644 index f80946da5..000000000 --- a/3rdparty/qtsingleapplication/qtsinglecoreapplication.h +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of a Qt Solutions component. -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.1, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact Nokia at qt-info@nokia.com. -** -****************************************************************************/ - - -#include - -class QtLocalPeer; - -class QtSingleCoreApplication : public QCoreApplication -{ - Q_OBJECT - -public: - QtSingleCoreApplication(int &argc, char **argv); - QtSingleCoreApplication(const QString &id, int &argc, char **argv); - - bool isRunning(); - QString id() const; - -public Q_SLOTS: - bool sendMessage(const QString &message, int timeout = 5000); - bool sendMessage(const QByteArray &message, int timeout = 5000); - bool sendMessage(const char* message, int timeout = 5000); - - -Q_SIGNALS: - void messageReceived(const QString &message); - void messageReceived(const QByteArray &message); - void messageReceived(const char* message); - - -private: - QtLocalPeer* peer; -}; diff --git a/3rdparty/singleapplication/CMakeLists.txt b/3rdparty/singleapplication/CMakeLists.txt new file mode 100644 index 000000000..f4711c0f5 --- /dev/null +++ b/3rdparty/singleapplication/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 2.6) + +set(SINGLEAPP-SOURCES + singleapplication.cpp + singlecoreapplication.cpp +) + +set(SINGLEAPP-MOC-HEADERS + singleapplication.h + singlecoreapplication.h +) + +QT5_WRAP_CPP(SINGLEAPP-SOURCES-MOC ${SINGLEAPP-MOC-HEADERS}) + +ADD_LIBRARY(singleapplication STATIC + ${SINGLEAPP-SOURCES} + ${SINGLEAPP-SOURCES-MOC} +) + +QT5_USE_MODULES(singleapplication Core Network Widgets) diff --git a/3rdparty/singleapplication/LICENSE b/3rdparty/singleapplication/LICENSE new file mode 100644 index 000000000..5c0006b9a --- /dev/null +++ b/3rdparty/singleapplication/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Itay Grudev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/3rdparty/singleapplication/singleapplication.cpp b/3rdparty/singleapplication/singleapplication.cpp new file mode 100644 index 000000000..9f71a62cb --- /dev/null +++ b/3rdparty/singleapplication/singleapplication.cpp @@ -0,0 +1,48 @@ +#include "singleapplication.h" +#include + +/** + * @brief Constructor. Checks and fires up LocalServer or closes the program + * if another instance already exists + * @param argc + * @param argv + */ +SingleApplication::SingleApplication(int &argc, char **argv) + : QApplication(argc, argv) +{ + QString serverName = QApplication::organizationName() + QApplication::applicationName(); + serverName.replace(QRegExp("[^\\w\\-. ]"), ""); + + // Attempt to connect to the LocalServer + socket = new QLocalSocket(); + socket->connectToServer(serverName); + if(socket->waitForConnected(1000)){ + socket->close(); + ::exit(EXIT_SUCCESS); // Terminate the program using STDLib's exit function + } else { + // If the connection is insuccessful, this is the main process + // So we create a Local Server + server = new QLocalServer(); + server->removeServer(serverName); + server->listen(serverName); + QObject::connect(server, SIGNAL(newConnection()), this, SLOT(slotConnectionEstablished())); + } +} + +/** + * @brief Destructor + */ +SingleApplication::~SingleApplication() +{ + server->close(); +} + +/** + * @brief Executed when the showUp command is sent to LocalServer + */ +void SingleApplication::slotConnectionEstablished() +{ + server->nextPendingConnection(); + emit showUp(); +} + diff --git a/3rdparty/singleapplication/singleapplication.h b/3rdparty/singleapplication/singleapplication.h new file mode 100644 index 000000000..3550eace0 --- /dev/null +++ b/3rdparty/singleapplication/singleapplication.h @@ -0,0 +1,32 @@ +#ifndef SINGLE_APPLICATION_H +#define SINGLE_APPLICATION_H + +#include +#include +#include + +/** + * @brief The SingleApplication class handles multipe instances of the same Application + * @see QApplication + */ +class SingleApplication : public QApplication +{ + Q_OBJECT +public: + explicit SingleApplication(int &, char **); + ~SingleApplication(); + +signals: + void showUp(); + +private slots: + void slotConnectionEstablished(); + +private: + QLocalSocket *socket; + QLocalServer *server; + +}; + +#endif // SINGLE_APPLICATION_H + diff --git a/3rdparty/singleapplication/singlecoreapplication.cpp b/3rdparty/singleapplication/singlecoreapplication.cpp new file mode 100644 index 000000000..587b3fa53 --- /dev/null +++ b/3rdparty/singleapplication/singlecoreapplication.cpp @@ -0,0 +1,48 @@ +#include "singlecoreapplication.h" +#include + +/** + * @brief Constructor. Checks and fires up LocalServer or closes the program + * if another instance already exists + * @param argc + * @param argv + */ +SingleCoreApplication::SingleCoreApplication(int &argc, char **argv) + : QCoreApplication(argc, argv) +{ + QString serverName = QCoreApplication::organizationName() + QCoreApplication::applicationName(); + serverName.replace(QRegExp("[^\\w\\-. ]"), ""); + + // Attempt to connect to the LocalServer + socket = new QLocalSocket(); + socket->connectToServer(serverName); + if(socket->waitForConnected(1000)){ + socket->close(); + ::exit(EXIT_SUCCESS); // Terminate the program using STDLib's exit function + } else { + // If the connection is insuccessful, this is the main process + // So we create a Local Server + server = new QLocalServer(); + server->removeServer(serverName); + server->listen(serverName); + QObject::connect(server, SIGNAL(newConnection()), this, SLOT(slotConnectionEstablished())); + } +} + +/** + * @brief Destructor + */ +SingleCoreApplication::~SingleCoreApplication() +{ + server->close(); +} + +/** + * @brief Executed when the showUp command is sent to LocalServer + */ +void SingleCoreApplication::slotConnectionEstablished() +{ + server->nextPendingConnection(); + emit showUp(); +} + diff --git a/3rdparty/singleapplication/singlecoreapplication.h b/3rdparty/singleapplication/singlecoreapplication.h new file mode 100644 index 000000000..b3a404d03 --- /dev/null +++ b/3rdparty/singleapplication/singlecoreapplication.h @@ -0,0 +1,32 @@ +#ifndef SINGLE_CORE_APPLICATION_H +#define SINGLE_CORE_APPLICATION_H + +#include +#include +#include + +/** + * @brief The SingleCoreApplication class handles multipe instances of the same Application + * @see QApplication + */ +class SingleCoreApplication : public QCoreApplication +{ + Q_OBJECT +public: + explicit SingleCoreApplication(int &, char **); + ~SingleCoreApplication(); + +signals: + void showUp(); + +private slots: + void slotConnectionEstablished(); + +private: + QLocalSocket *socket; + QLocalServer *server; + +}; + +#endif // SINGLE_CORE_APPLICATION_H + From 2495c6cc617ee2c7260cba7d873f41699f635397 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sat, 11 Apr 2015 22:44:11 +0200 Subject: [PATCH 002/104] Update of libmygpo for qt5 --- 3rdparty/libmygpo-qt5/AUTHORS | 3 + 3rdparty/libmygpo-qt5/CMakeLists.txt | 50 ++ 3rdparty/libmygpo-qt5/LICENSE | 502 ++++++++++++++++++ 3rdparty/libmygpo-qt5/Mygpo-qtConfig.cmake.in | 18 + .../Mygpo-qtConfigVersion.cmake.in | 10 + 3rdparty/libmygpo-qt5/README | 52 ++ .../cmake/modules/FindQJSON.cmake | 50 ++ .../src}/AddRemoveResult.cpp | 8 +- .../src}/AddRemoveResult.h | 0 .../src}/AddRemoveResult_p.h | 0 .../src}/ApiRequest.cpp | 2 +- .../src}/ApiRequest.h | 12 +- .../src}/ApiRequest_p.h | 0 .../src}/CMakeLists.txt | 17 +- .../src}/Config.cpp | 0 .../src}/Config.h | 0 .../src}/Config_p.h | 0 .../src}/Device.cpp | 0 .../src}/Device.h | 0 .../src}/DeviceList.cpp | 5 +- .../src}/DeviceList.h | 0 .../src}/DeviceList_p.h | 0 .../src}/DeviceSyncResult.cpp | 7 +- .../src}/DeviceSyncResult.h | 0 .../src}/DeviceSyncResult_p.h | 0 .../src}/DeviceUpdates.cpp | 5 +- .../src}/DeviceUpdates.h | 0 .../src}/DeviceUpdates_p.h | 0 .../src}/Device_p.h | 0 .../src}/Episode.cpp | 5 +- .../src}/Episode.h | 0 .../src}/EpisodeAction.cpp | 5 +- .../src}/EpisodeAction.h | 0 .../src}/EpisodeActionList.cpp | 5 +- .../src}/EpisodeActionList.h | 0 .../src}/EpisodeActionList_p.h | 0 .../src}/EpisodeAction_p.h | 0 .../src}/EpisodeList.cpp | 5 +- .../src}/EpisodeList.h | 0 .../src}/EpisodeList_p.h | 0 .../src}/Episode_p.h | 0 .../src}/JsonCreator.cpp | 20 +- .../src}/JsonCreator.h | 0 .../src}/Podcast.cpp | 7 +- .../src}/Podcast.h | 0 .../src}/PodcastList.cpp | 5 +- .../src}/PodcastList.h | 0 .../src}/PodcastList_p.h | 0 .../src}/Podcast_p.h | 0 .../src}/RequestHandler.cpp | 2 +- .../src}/RequestHandler.h | 0 .../src}/Settings.cpp | 6 +- .../src}/Settings.h | 0 .../src}/Settings_p.h | 0 .../{libmygpo-qt => libmygpo-qt5/src}/Tag.cpp | 0 .../{libmygpo-qt => libmygpo-qt5/src}/Tag.h | 0 .../src}/TagList.cpp | 5 +- .../src}/TagList.h | 0 .../src}/TagList_p.h | 0 .../{libmygpo-qt => libmygpo-qt5/src}/Tag_p.h | 0 .../src}/UrlBuilder.cpp | 3 +- .../src}/UrlBuilder.h | 0 .../src}/Version.h.in | 0 .../src}/mygpo_export.h | 0 .../libmygpo-qt5/src/qjsonwrapper/Json.cpp | 123 +++++ 3rdparty/libmygpo-qt5/src/qjsonwrapper/Json.h | 36 ++ 66 files changed, 894 insertions(+), 74 deletions(-) create mode 100644 3rdparty/libmygpo-qt5/AUTHORS create mode 100644 3rdparty/libmygpo-qt5/CMakeLists.txt create mode 100644 3rdparty/libmygpo-qt5/LICENSE create mode 100644 3rdparty/libmygpo-qt5/Mygpo-qtConfig.cmake.in create mode 100644 3rdparty/libmygpo-qt5/Mygpo-qtConfigVersion.cmake.in create mode 100644 3rdparty/libmygpo-qt5/README create mode 100644 3rdparty/libmygpo-qt5/cmake/modules/FindQJSON.cmake rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/AddRemoveResult.cpp (97%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/AddRemoveResult.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/AddRemoveResult_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/ApiRequest.cpp (99%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/ApiRequest.h (98%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/ApiRequest_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/CMakeLists.txt (67%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Config.cpp (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Config.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Config_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Device.cpp (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Device.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/DeviceList.cpp (97%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/DeviceList.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/DeviceList_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/DeviceSyncResult.cpp (97%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/DeviceSyncResult.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/DeviceSyncResult_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/DeviceUpdates.cpp (98%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/DeviceUpdates.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/DeviceUpdates_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Device_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Episode.cpp (98%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Episode.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/EpisodeAction.cpp (98%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/EpisodeAction.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/EpisodeActionList.cpp (98%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/EpisodeActionList.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/EpisodeActionList_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/EpisodeAction_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/EpisodeList.cpp (97%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/EpisodeList.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/EpisodeList_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Episode_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/JsonCreator.cpp (94%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/JsonCreator.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Podcast.cpp (97%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Podcast.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/PodcastList.cpp (97%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/PodcastList.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/PodcastList_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Podcast_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/RequestHandler.cpp (99%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/RequestHandler.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Settings.cpp (96%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Settings.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Settings_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Tag.cpp (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Tag.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/TagList.cpp (97%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/TagList.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/TagList_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Tag_p.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/UrlBuilder.cpp (98%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/UrlBuilder.h (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/Version.h.in (100%) rename 3rdparty/{libmygpo-qt => libmygpo-qt5/src}/mygpo_export.h (100%) create mode 100644 3rdparty/libmygpo-qt5/src/qjsonwrapper/Json.cpp create mode 100644 3rdparty/libmygpo-qt5/src/qjsonwrapper/Json.h diff --git a/3rdparty/libmygpo-qt5/AUTHORS b/3rdparty/libmygpo-qt5/AUTHORS new file mode 100644 index 000000000..9080afb9e --- /dev/null +++ b/3rdparty/libmygpo-qt5/AUTHORS @@ -0,0 +1,3 @@ +Stefan Derkits +Christian Wagner +Felix Winter diff --git a/3rdparty/libmygpo-qt5/CMakeLists.txt b/3rdparty/libmygpo-qt5/CMakeLists.txt new file mode 100644 index 000000000..dd47ad1ac --- /dev/null +++ b/3rdparty/libmygpo-qt5/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required( VERSION 2.6 FATAL_ERROR ) + +set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) +set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII" ) + +set(MYGPO_QT_VERSION_SUFFIX 5) + +macro(qt_wrap_cpp) + qt5_wrap_cpp(${ARGN}) +endmacro() + +# pkg-config names of QtCore and QtNetwork are Qt5Core and Qt5Network for +# Qt5 +set(MYGPO_QT_MAJOR_VERSION "5") +set(MYGPO_QT4_QJSON_DEP "") + +# Don't use absolute path in Mygpo-qtTargets-$buildType.cmake +# (This will have no effect with CMake < 2.8) +# set(QT_USE_IMPORTED_TARGETS TRUE) + +set( MYGPO_QT_VERSION_MAJOR "1" ) +set( MYGPO_QT_VERSION_MINOR "0" ) +set( MYGPO_QT_VERSION_PATCH "8" ) +set( MYGPO_QT_VERSION "${MYGPO_QT_VERSION_MAJOR}.${MYGPO_QT_VERSION_MINOR}.${MYGPO_QT_VERSION_PATCH}" ) + +#Configure Version.h.in with the actual version number +configure_file( src/Version.h.in ${CMAKE_CURRENT_BINARY_DIR}/src/Version.h ) + +include(CheckCXXCompilerFlag) + +if (CMAKE_COMPILER_IS_GNUCXX) + ADD_DEFINITIONS( -Wcast-align -Wchar-subscripts -Wpointer-arith + -Wwrite-strings -Wpacked -Wformat-security -Wmissing-format-attribute + -Wold-style-cast -Woverloaded-virtual -Wnon-virtual-dtor -Wall -Wextra + -Wformat=2 -Wundef -Wstack-protector -Wmissing-include-dirs + -Winit-self -Wunsafe-loop-optimizations -ggdb3 -fno-inline -DQT_STRICT_ITERATORS ) + if ( NOT WIN32 ) + add_definitions( -fvisibility=hidden ) + endif() + + check_cxx_compiler_flag( -Wlogical-op GNUCXX_HAS_WLOGICAL_OP ) + if ( GNUCXX_HAS_WLOGICAL_OP ) + add_definitions( -Wlogical-op ) + endif() +endif(CMAKE_COMPILER_IS_GNUCXX) + + +set(MYGPO_QT_TARGET_NAME mygpo-qt${MYGPO_QT_VERSION_SUFFIX} CACHE INTERNAL "" FORCE ) + +add_subdirectory( src ) diff --git a/3rdparty/libmygpo-qt5/LICENSE b/3rdparty/libmygpo-qt5/LICENSE new file mode 100644 index 000000000..4362b4915 --- /dev/null +++ b/3rdparty/libmygpo-qt5/LICENSE @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 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. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + + 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 Library or any portion +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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 with +this License. + + 11. 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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +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. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser 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 Library +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. 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. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; 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. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/3rdparty/libmygpo-qt5/Mygpo-qtConfig.cmake.in b/3rdparty/libmygpo-qt5/Mygpo-qtConfig.cmake.in new file mode 100644 index 000000000..17873a74c --- /dev/null +++ b/3rdparty/libmygpo-qt5/Mygpo-qtConfig.cmake.in @@ -0,0 +1,18 @@ +get_filename_component(myDir ${CMAKE_CURRENT_LIST_FILE} PATH) # get the directory where I myself am +get_filename_component(rootDir ${myDir}/@relInstallDir@ ABSOLUTE) # get the chosen install prefix + +# set the version of myself +set(MYGPO_QT_VERSION_MAJOR @MYGPO_QT_VERSION_MAJOR@) +set(MYGPO_QT_VERSION_MINOR @MYGPO_QT_VERSION_MINOR@) +set(MYGPO_QT_VERSION_PATCH @MYGPO_QT_VERSION_PATCH@) +set(MYGPO_QT_VERSION ${MYGPO_QT_VERSION_MAJOR}.${MYGPO_QT_VERSION_MINOR}.${MYGPO_QT_VERSION_PATCH} ) + +# what is my include directory +set(LIBMYGPO_QT_INCLUDE_DIRS "@INCLUDE_INSTALL_DIR@") + +# import the exported targets +include(${myDir}/Mygpo-qtTargets.cmake) + +# set the expected library variable +set(LIBMYGPO_QT_LIBRARIES mygpo-qt ) +set(LIBMYGPO_QT_FOUND "True") diff --git a/3rdparty/libmygpo-qt5/Mygpo-qtConfigVersion.cmake.in b/3rdparty/libmygpo-qt5/Mygpo-qtConfigVersion.cmake.in new file mode 100644 index 000000000..1126fdfc3 --- /dev/null +++ b/3rdparty/libmygpo-qt5/Mygpo-qtConfigVersion.cmake.in @@ -0,0 +1,10 @@ +set(PACKAGE_VERSION @MYGPO_QT_VERSION_MAJOR@.@MYGPO_QT_VERSION_MINOR@.@MYGPO_QT_VERSION_PATCH@) + +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") +endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) diff --git a/3rdparty/libmygpo-qt5/README b/3rdparty/libmygpo-qt5/README new file mode 100644 index 000000000..656949d9f --- /dev/null +++ b/3rdparty/libmygpo-qt5/README @@ -0,0 +1,52 @@ +========== README ========== + +=== What is libmygpo-qt === + +libmygpo-qt is a Qt Library that wraps the gpodder.net Web API (http://wiki.gpodder.org/wiki/Web_Services/API_2) + +=== Copyright & License === + +Copyright 2010 - 2014 Stefan Derkits (stefan@derkits.at) , Christian Wagner (christian.wagner86@gmx.at) & Felix Winter (ixos01@gmail.com) + +See COPYING File for License + +=== Maintainer === + +Current Maintainer: Stefan Derkits (HorusHorrendus @ irc.freenode.net) + +=== Requirements === + +-) Qt 4.6 or higher +-) Cmake 2.6 or higher +-) QJson + +=== Qt5 Support === + +libmygpo-qt version 1.0.8 supports also building the library with Qt5. The API is the same as in the Qt4 library. To build the library with Qt5 add "-DBUILD_WITH_QT4=OFF" to your CMake +command line. Please note that Qt5 support is still experimental. If you find anything to not work with Qt5, please report a bug. + +==== Qt5 Requirements === + +-) CMake 2.8.9 or higher +-) Qt 5.2 or higher + +=== Links === + +Homepage: http://wiki.gpodder.org/wiki/Libmygpo-qt +Git Repo: https://github.com/gpodder/libmygpo-qt +Doxygen Documentation: http://stefan.derkits.at/libmygpo-doc/ +Bugreports: http://bugs.gpodder.org +Contact: gpodder@freelists.org +IRC Channel: #gpodder on FreeNode (irc.freenode.net) + +=== How to Install === + +-) Create Directory "build" +-) change into build and run "cmake .. -DCMAKE_BUILD_TYPE=Debug" +-) make +-) make install (might need root) + +To use libmygpo-qt include the Header "ApiRequest.h" into your Code. You can find the cflags & linker flags for libmygpo-qt either via pkg-config (.pc file will be installed to your System) +or via cmake (Mygpo-qtConfig.cmake will be installed to your system). + +You can check the Example Application to see how you can use libmygpo-qt in your Application diff --git a/3rdparty/libmygpo-qt5/cmake/modules/FindQJSON.cmake b/3rdparty/libmygpo-qt5/cmake/modules/FindQJSON.cmake new file mode 100644 index 000000000..936d93b3c --- /dev/null +++ b/3rdparty/libmygpo-qt5/cmake/modules/FindQJSON.cmake @@ -0,0 +1,50 @@ +# Find QJSON - JSON handling library for Qt +# +# This module defines +# QJSON_FOUND - whether the qsjon library was found +# QJSON_LIBRARIES - the qjson library +# QJSON_INCLUDE_DIR - the include path of the qjson library +# + +if (QJSON_INCLUDE_DIR AND QJSON_LIBRARIES) + + # Already in cache + set (QJSON_FOUND TRUE) + +else (QJSON_INCLUDE_DIR AND QJSON_LIBRARIES) + + if (NOT WIN32) + # use pkg-config to get the values of QJSON_INCLUDE_DIRS + # and QJSON_LIBRARY_DIRS to add as hints to the find commands. + include (FindPkgConfig) + pkg_check_modules (QJSON REQUIRED QJson>=0.5) + endif (NOT WIN32) + + find_library (QJSON_LIBRARIES + NAMES + qjson + PATHS + ${QJSON_LIBRARY_DIRS} + ${LIB_INSTALL_DIR} + ${KDE4_LIB_DIR} + ) + + find_path (QJSON_INCLUDE_DIR + NAMES + parser.h + PATH_SUFFIXES + qjson + PATHS + ${QJSON_INCLUDE_DIRS} + ${INCLUDE_INSTALL_DIR} + ${KDE4_INCLUDE_DIR} + ) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(QJSON DEFAULT_MSG QJSON_LIBRARIES QJSON_INCLUDE_DIR) + + if ( UNIX AND NOT APPLE ) + set ( QJSON_LIBRARIES "${QJSON_LIBRARIES} ${QJSON_LDFLAGS}" CACHE INTERNAL "") + endif () + +endif (QJSON_INCLUDE_DIR AND QJSON_LIBRARIES) diff --git a/3rdparty/libmygpo-qt/AddRemoveResult.cpp b/3rdparty/libmygpo-qt5/src/AddRemoveResult.cpp similarity index 97% rename from 3rdparty/libmygpo-qt/AddRemoveResult.cpp rename to 3rdparty/libmygpo-qt5/src/AddRemoveResult.cpp index 1127b0391..83c0c60db 100644 --- a/3rdparty/libmygpo-qt/AddRemoveResult.cpp +++ b/3rdparty/libmygpo-qt5/src/AddRemoveResult.cpp @@ -20,11 +20,11 @@ * USA * ***************************************************************************/ -#include - #include "AddRemoveResult.h" #include "AddRemoveResult_p.h" +#include "qjsonwrapper/Json.h" + using namespace mygpo; AddRemoveResultPrivate::AddRemoveResultPrivate( AddRemoveResult* qq, QNetworkReply* reply ) : q( qq ), m_reply( reply ), m_error( QNetworkReply::NoError ) @@ -64,7 +64,6 @@ QList< QPair< QUrl, QUrl > > AddRemoveResultPrivate::updateUrlsList() const bool AddRemoveResultPrivate::parse( const QVariant& data ) { - QJson::Parser parser; if( !data.canConvert( QVariant::Map ) ) return false; QVariantMap resultMap = data.toMap(); @@ -78,9 +77,8 @@ bool AddRemoveResultPrivate::parse( const QVariant& data ) bool AddRemoveResultPrivate::parse( const QByteArray& data ) { - QJson::Parser parser; bool ok; - QVariant variant = parser.parse( data, &ok ); + QVariant variant = QJsonWrapper::parseJson( data, &ok ); if( ok ) { ok = ( parse( variant ) ); diff --git a/3rdparty/libmygpo-qt/AddRemoveResult.h b/3rdparty/libmygpo-qt5/src/AddRemoveResult.h similarity index 100% rename from 3rdparty/libmygpo-qt/AddRemoveResult.h rename to 3rdparty/libmygpo-qt5/src/AddRemoveResult.h diff --git a/3rdparty/libmygpo-qt/AddRemoveResult_p.h b/3rdparty/libmygpo-qt5/src/AddRemoveResult_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/AddRemoveResult_p.h rename to 3rdparty/libmygpo-qt5/src/AddRemoveResult_p.h diff --git a/3rdparty/libmygpo-qt/ApiRequest.cpp b/3rdparty/libmygpo-qt5/src/ApiRequest.cpp similarity index 99% rename from 3rdparty/libmygpo-qt/ApiRequest.cpp rename to 3rdparty/libmygpo-qt5/src/ApiRequest.cpp index b3c533f2a..469a7a1ff 100644 --- a/3rdparty/libmygpo-qt/ApiRequest.cpp +++ b/3rdparty/libmygpo-qt5/src/ApiRequest.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * This file is part of libmygpo-qt * -* Copyright (c) 2010 - 2013 Stefan Derkits * +* Copyright (c) 2010 - 2014 Stefan Derkits * * Copyright (c) 2010 - 2011 Christian Wagner * * Copyright (c) 2010 - 2011 Felix Winter * * * diff --git a/3rdparty/libmygpo-qt/ApiRequest.h b/3rdparty/libmygpo-qt5/src/ApiRequest.h similarity index 98% rename from 3rdparty/libmygpo-qt/ApiRequest.h rename to 3rdparty/libmygpo-qt5/src/ApiRequest.h index 982db49ba..c61119295 100644 --- a/3rdparty/libmygpo-qt/ApiRequest.h +++ b/3rdparty/libmygpo-qt5/src/ApiRequest.h @@ -1,6 +1,6 @@ /*************************************************************************** * This file is part of libmygpo-qt * -* Copyright (c) 2010 - 2013 Stefan Derkits * +* Copyright (c) 2010 - 2014 Stefan Derkits * * Copyright (c) 2010 - 2011 Christian Wagner * * Copyright (c) 2010 - 2011 Felix Winter * * * @@ -84,7 +84,7 @@ public: */ QNetworkReply* suggestionsOpml( uint count ); - QNetworkReply* downloadSubscriptionsOpml( const QString& username, const QString& device ); + QNetworkReply* downloadSubscriptionsOpml( const QString& username, const QString& device = QString() ); /** * Returns the TXT Result for the Simple API Call "Downloading Podcast Toplists" @@ -111,7 +111,7 @@ public: */ QNetworkReply* suggestionsTxt( uint count ); - QNetworkReply* downloadSubscriptionsTxt( const QString& username, const QString& device ); + QNetworkReply* downloadSubscriptionsTxt( const QString& username, const QString& device = QString() ); /** * Returns the TXT Result for the Simple API Call "Downloading Podcast Toplists" @@ -153,9 +153,9 @@ public: * */ PodcastListPtr suggestions( uint count ); - - QNetworkReply* downloadSubscriptionsJson( const QString& username, const QString& device ); - + + QNetworkReply* downloadSubscriptionsJson( const QString& username, const QString& device = QString() ); + //ADVANCED API /** diff --git a/3rdparty/libmygpo-qt/ApiRequest_p.h b/3rdparty/libmygpo-qt5/src/ApiRequest_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/ApiRequest_p.h rename to 3rdparty/libmygpo-qt5/src/ApiRequest_p.h diff --git a/3rdparty/libmygpo-qt/CMakeLists.txt b/3rdparty/libmygpo-qt5/src/CMakeLists.txt similarity index 67% rename from 3rdparty/libmygpo-qt/CMakeLists.txt rename to 3rdparty/libmygpo-qt5/src/CMakeLists.txt index c09d91448..98950a4ba 100644 --- a/3rdparty/libmygpo-qt/CMakeLists.txt +++ b/3rdparty/libmygpo-qt5/src/CMakeLists.txt @@ -1,11 +1,5 @@ -# Extra bits for Clementine. -set( MYGPO_QT_VERSION_MAJOR "1" ) -set( MYGPO_QT_VERSION_MINOR "0" ) -set( MYGPO_QT_VERSION_PATCH "7" ) -configure_file( Version.h.in ${CMAKE_CURRENT_BINARY_DIR}/Version.h ) -include_directories("${QJSON_INCLUDEDIR}/qjson") -include_directories( ${QT_INCLUDES} ${QJSON_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) +include_directories( ${QJSON_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) set ( LIBMYGPO_QT_SRC Config.cpp @@ -27,6 +21,7 @@ set ( LIBMYGPO_QT_SRC DeviceUpdates.cpp DeviceList.cpp Device.cpp + qjsonwrapper/Json.cpp ) set ( LIBMYGPO_QT_MOC_H @@ -80,9 +75,9 @@ set ( LIBMYGPO_QT_INSTALL_H AddRemoveResult.h ) -QT4_WRAP_CPP(LIBMYGPO_QT_MOC_SRC ${LIBMYGPO_QT_MOC_H} ) +QT_WRAP_CPP(LIBMYGPO_QT_MOC_SRC ${LIBMYGPO_QT_MOC_H} ) -add_library( mygpo-qt STATIC ${LIBMYGPO_QT_SRC} ${LIBMYGPO_QT_MOC_SRC} ) +add_library( ${MYGPO_QT_TARGET_NAME} STATIC ${LIBMYGPO_QT_SRC} ${LIBMYGPO_QT_MOC_SRC} ) -target_link_libraries( mygpo-qt ${QJSON_LIBRARIES} ${QT_QTCORE_LIBRARY} ${QT_QTNETWORK_LIBRARY} ) -set_target_properties( mygpo-qt PROPERTIES VERSION ${MYGPO_QT_VERSION} SOVERSION ${MYGPO_QT_SONAME} DEFINE_SYMBOL MYGPO_MAKEDLL) +target_link_libraries( ${MYGPO_QT_TARGET_NAME} ${QJSON_LIBRARIES} ${QT_QTCORE_LIBRARY} ${QT_QTNETWORK_LIBRARY} ) +qt5_use_modules( ${MYGPO_QT_TARGET_NAME} Core Network ) diff --git a/3rdparty/libmygpo-qt/Config.cpp b/3rdparty/libmygpo-qt5/src/Config.cpp similarity index 100% rename from 3rdparty/libmygpo-qt/Config.cpp rename to 3rdparty/libmygpo-qt5/src/Config.cpp diff --git a/3rdparty/libmygpo-qt/Config.h b/3rdparty/libmygpo-qt5/src/Config.h similarity index 100% rename from 3rdparty/libmygpo-qt/Config.h rename to 3rdparty/libmygpo-qt5/src/Config.h diff --git a/3rdparty/libmygpo-qt/Config_p.h b/3rdparty/libmygpo-qt5/src/Config_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/Config_p.h rename to 3rdparty/libmygpo-qt5/src/Config_p.h diff --git a/3rdparty/libmygpo-qt/Device.cpp b/3rdparty/libmygpo-qt5/src/Device.cpp similarity index 100% rename from 3rdparty/libmygpo-qt/Device.cpp rename to 3rdparty/libmygpo-qt5/src/Device.cpp diff --git a/3rdparty/libmygpo-qt/Device.h b/3rdparty/libmygpo-qt5/src/Device.h similarity index 100% rename from 3rdparty/libmygpo-qt/Device.h rename to 3rdparty/libmygpo-qt5/src/Device.h diff --git a/3rdparty/libmygpo-qt/DeviceList.cpp b/3rdparty/libmygpo-qt5/src/DeviceList.cpp similarity index 97% rename from 3rdparty/libmygpo-qt/DeviceList.cpp rename to 3rdparty/libmygpo-qt5/src/DeviceList.cpp index 46defc258..e972318cc 100644 --- a/3rdparty/libmygpo-qt/DeviceList.cpp +++ b/3rdparty/libmygpo-qt5/src/DeviceList.cpp @@ -22,7 +22,7 @@ #include "DeviceList_p.h" -#include +#include "qjsonwrapper/Json.h" using namespace mygpo; @@ -73,9 +73,8 @@ bool DeviceListPrivate::parse( const QVariant& data ) bool DeviceListPrivate::parse( const QByteArray& data ) { - QJson::Parser parser; bool ok; - QVariant variant = parser.parse( data, &ok ); + QVariant variant = QJsonWrapper::parseJson( data, &ok ); if( ok ) { ok = ( parse( variant ) ); diff --git a/3rdparty/libmygpo-qt/DeviceList.h b/3rdparty/libmygpo-qt5/src/DeviceList.h similarity index 100% rename from 3rdparty/libmygpo-qt/DeviceList.h rename to 3rdparty/libmygpo-qt5/src/DeviceList.h diff --git a/3rdparty/libmygpo-qt/DeviceList_p.h b/3rdparty/libmygpo-qt5/src/DeviceList_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/DeviceList_p.h rename to 3rdparty/libmygpo-qt5/src/DeviceList_p.h diff --git a/3rdparty/libmygpo-qt/DeviceSyncResult.cpp b/3rdparty/libmygpo-qt5/src/DeviceSyncResult.cpp similarity index 97% rename from 3rdparty/libmygpo-qt/DeviceSyncResult.cpp rename to 3rdparty/libmygpo-qt5/src/DeviceSyncResult.cpp index b71f05588..1ee70494e 100644 --- a/3rdparty/libmygpo-qt/DeviceSyncResult.cpp +++ b/3rdparty/libmygpo-qt5/src/DeviceSyncResult.cpp @@ -20,7 +20,7 @@ #include "DeviceSyncResult_p.h" -#include +#include "qjsonwrapper/Json.h" using namespace mygpo; @@ -85,9 +85,8 @@ bool DeviceSyncResultPrivate::parse( const QVariant& data ) bool DeviceSyncResultPrivate::parse( const QByteArray& data ) { - QJson::Parser parser; bool ok; - QVariant variant = parser.parse( data, &ok ); + QVariant variant = QJsonWrapper::parseJson( data, &ok ); if( ok ) { ok = ( parse( variant ) ); @@ -108,7 +107,7 @@ void DeviceSyncResultPrivate::parseData() emit q->parseError(); } } - m_reply->deleteLater(); + m_reply->deleteLater(); } void DeviceSyncResultPrivate::error( QNetworkReply::NetworkError error ) diff --git a/3rdparty/libmygpo-qt/DeviceSyncResult.h b/3rdparty/libmygpo-qt5/src/DeviceSyncResult.h similarity index 100% rename from 3rdparty/libmygpo-qt/DeviceSyncResult.h rename to 3rdparty/libmygpo-qt5/src/DeviceSyncResult.h diff --git a/3rdparty/libmygpo-qt/DeviceSyncResult_p.h b/3rdparty/libmygpo-qt5/src/DeviceSyncResult_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/DeviceSyncResult_p.h rename to 3rdparty/libmygpo-qt5/src/DeviceSyncResult_p.h diff --git a/3rdparty/libmygpo-qt/DeviceUpdates.cpp b/3rdparty/libmygpo-qt5/src/DeviceUpdates.cpp similarity index 98% rename from 3rdparty/libmygpo-qt/DeviceUpdates.cpp rename to 3rdparty/libmygpo-qt5/src/DeviceUpdates.cpp index c74b52fcb..04653c569 100644 --- a/3rdparty/libmygpo-qt/DeviceUpdates.cpp +++ b/3rdparty/libmygpo-qt5/src/DeviceUpdates.cpp @@ -22,7 +22,7 @@ #include "DeviceUpdates_p.h" -#include +#include "qjsonwrapper/Json.h" using namespace mygpo; @@ -102,9 +102,8 @@ bool DeviceUpdatesPrivate::parse( const QVariant& data ) bool DeviceUpdatesPrivate::parse( const QByteArray& data ) { - QJson::Parser parser; bool ok; - QVariant variant = parser.parse( data, &ok ); + QVariant variant = QJsonWrapper::parseJson( data, &ok ); if( ok ) { ok = ( parse( variant ) ); diff --git a/3rdparty/libmygpo-qt/DeviceUpdates.h b/3rdparty/libmygpo-qt5/src/DeviceUpdates.h similarity index 100% rename from 3rdparty/libmygpo-qt/DeviceUpdates.h rename to 3rdparty/libmygpo-qt5/src/DeviceUpdates.h diff --git a/3rdparty/libmygpo-qt/DeviceUpdates_p.h b/3rdparty/libmygpo-qt5/src/DeviceUpdates_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/DeviceUpdates_p.h rename to 3rdparty/libmygpo-qt5/src/DeviceUpdates_p.h diff --git a/3rdparty/libmygpo-qt/Device_p.h b/3rdparty/libmygpo-qt5/src/Device_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/Device_p.h rename to 3rdparty/libmygpo-qt5/src/Device_p.h diff --git a/3rdparty/libmygpo-qt/Episode.cpp b/3rdparty/libmygpo-qt5/src/Episode.cpp similarity index 98% rename from 3rdparty/libmygpo-qt/Episode.cpp rename to 3rdparty/libmygpo-qt5/src/Episode.cpp index 921b72f7d..196de323f 100644 --- a/3rdparty/libmygpo-qt/Episode.cpp +++ b/3rdparty/libmygpo-qt5/src/Episode.cpp @@ -22,7 +22,7 @@ #include "Episode_p.h" -#include +#include "qjsonwrapper/Json.h" using namespace mygpo; @@ -115,9 +115,8 @@ bool EpisodePrivate::parse ( const QVariant& data ) bool EpisodePrivate::parse ( const QByteArray& data ) { - QJson::Parser parser; bool ok; - QVariant variant = parser.parse ( data, &ok ); + QVariant variant = QJsonWrapper::parseJson( data, &ok ); if ( ok ) { if ( !parse ( variant ) ) return false; diff --git a/3rdparty/libmygpo-qt/Episode.h b/3rdparty/libmygpo-qt5/src/Episode.h similarity index 100% rename from 3rdparty/libmygpo-qt/Episode.h rename to 3rdparty/libmygpo-qt5/src/Episode.h diff --git a/3rdparty/libmygpo-qt/EpisodeAction.cpp b/3rdparty/libmygpo-qt5/src/EpisodeAction.cpp similarity index 98% rename from 3rdparty/libmygpo-qt/EpisodeAction.cpp rename to 3rdparty/libmygpo-qt5/src/EpisodeAction.cpp index ad1f0e5e3..95536be02 100644 --- a/3rdparty/libmygpo-qt/EpisodeAction.cpp +++ b/3rdparty/libmygpo-qt5/src/EpisodeAction.cpp @@ -22,7 +22,7 @@ #include "EpisodeAction_p.h" -#include +#include "qjsonwrapper/Json.h" using namespace mygpo; @@ -163,9 +163,8 @@ bool EpisodeActionPrivate::parseActionType( const QString& data ) bool EpisodeActionPrivate::parse( const QByteArray& data ) { - QJson::Parser parser; bool ok; - QVariant variant = parser.parse( data, &ok ); + QVariant variant = QJsonWrapper::parseJson( data, &ok ); if( ok ) { if( !parse( variant ) ) return false; diff --git a/3rdparty/libmygpo-qt/EpisodeAction.h b/3rdparty/libmygpo-qt5/src/EpisodeAction.h similarity index 100% rename from 3rdparty/libmygpo-qt/EpisodeAction.h rename to 3rdparty/libmygpo-qt5/src/EpisodeAction.h diff --git a/3rdparty/libmygpo-qt/EpisodeActionList.cpp b/3rdparty/libmygpo-qt5/src/EpisodeActionList.cpp similarity index 98% rename from 3rdparty/libmygpo-qt/EpisodeActionList.cpp rename to 3rdparty/libmygpo-qt5/src/EpisodeActionList.cpp index 426f0e895..4c221cc7a 100644 --- a/3rdparty/libmygpo-qt/EpisodeActionList.cpp +++ b/3rdparty/libmygpo-qt5/src/EpisodeActionList.cpp @@ -22,7 +22,7 @@ #include "EpisodeActionList_p.h" -#include +#include "qjsonwrapper/Json.h" using namespace mygpo; @@ -88,9 +88,8 @@ bool EpisodeActionListPrivate::parse( const QVariant& data ) bool EpisodeActionListPrivate::parse( const QByteArray& data ) { - QJson::Parser parser; bool ok; - QVariant variant = parser.parse( data, &ok ); + QVariant variant = QJsonWrapper::parseJson( data, &ok ); if( ok ) { ok = ( parse( variant ) ); diff --git a/3rdparty/libmygpo-qt/EpisodeActionList.h b/3rdparty/libmygpo-qt5/src/EpisodeActionList.h similarity index 100% rename from 3rdparty/libmygpo-qt/EpisodeActionList.h rename to 3rdparty/libmygpo-qt5/src/EpisodeActionList.h diff --git a/3rdparty/libmygpo-qt/EpisodeActionList_p.h b/3rdparty/libmygpo-qt5/src/EpisodeActionList_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/EpisodeActionList_p.h rename to 3rdparty/libmygpo-qt5/src/EpisodeActionList_p.h diff --git a/3rdparty/libmygpo-qt/EpisodeAction_p.h b/3rdparty/libmygpo-qt5/src/EpisodeAction_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/EpisodeAction_p.h rename to 3rdparty/libmygpo-qt5/src/EpisodeAction_p.h diff --git a/3rdparty/libmygpo-qt/EpisodeList.cpp b/3rdparty/libmygpo-qt5/src/EpisodeList.cpp similarity index 97% rename from 3rdparty/libmygpo-qt/EpisodeList.cpp rename to 3rdparty/libmygpo-qt5/src/EpisodeList.cpp index e003f2333..6a9de5de3 100644 --- a/3rdparty/libmygpo-qt/EpisodeList.cpp +++ b/3rdparty/libmygpo-qt5/src/EpisodeList.cpp @@ -22,7 +22,7 @@ #include "EpisodeList_p.h" -#include +#include "qjsonwrapper/Json.h" using namespace mygpo; @@ -71,9 +71,8 @@ bool EpisodeListPrivate::parse( const QVariant& data ) bool EpisodeListPrivate::parse( const QByteArray& data ) { - QJson::Parser parser; bool ok; - QVariant variant = parser.parse( data, &ok ); + QVariant variant = QJsonWrapper::parseJson( data, &ok ); if( ok ) { ok = ( parse( variant ) ); diff --git a/3rdparty/libmygpo-qt/EpisodeList.h b/3rdparty/libmygpo-qt5/src/EpisodeList.h similarity index 100% rename from 3rdparty/libmygpo-qt/EpisodeList.h rename to 3rdparty/libmygpo-qt5/src/EpisodeList.h diff --git a/3rdparty/libmygpo-qt/EpisodeList_p.h b/3rdparty/libmygpo-qt5/src/EpisodeList_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/EpisodeList_p.h rename to 3rdparty/libmygpo-qt5/src/EpisodeList_p.h diff --git a/3rdparty/libmygpo-qt/Episode_p.h b/3rdparty/libmygpo-qt5/src/Episode_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/Episode_p.h rename to 3rdparty/libmygpo-qt5/src/Episode_p.h diff --git a/3rdparty/libmygpo-qt/JsonCreator.cpp b/3rdparty/libmygpo-qt5/src/JsonCreator.cpp similarity index 94% rename from 3rdparty/libmygpo-qt/JsonCreator.cpp rename to 3rdparty/libmygpo-qt5/src/JsonCreator.cpp index fc148a0f6..9c4f0bcc4 100644 --- a/3rdparty/libmygpo-qt/JsonCreator.cpp +++ b/3rdparty/libmygpo-qt5/src/JsonCreator.cpp @@ -20,47 +20,44 @@ * USA * ***************************************************************************/ -#include +//#include #include #include #include #include -#include - #include "JsonCreator.h" +#include "qjsonwrapper/Json.h" + using namespace mygpo; static qulonglong c_maxlonglong = (2^64)-1; QByteArray JsonCreator::addRemoveSubsToJSON( const QList< QUrl >& add, const QList< QUrl >& remove ) { - QJson::Serializer serializer; QVariantMap jsonData; QVariant addVar( urlListToQVariantList( add ) ); QVariant removeVar( urlListToQVariantList( remove ) ); jsonData.insert( QString( QLatin1String( "add" ) ), addVar ); jsonData.insert( QString( QLatin1String( "remove" ) ), removeVar ); - QByteArray jsonByteArray = serializer.serialize( QVariant( jsonData ) ); + QByteArray jsonByteArray = QJsonWrapper::toJson( QVariant( jsonData ) ); return jsonByteArray; } QByteArray JsonCreator::saveSettingsToJSON( const QMap< QString, QVariant >& set, const QList< QString >& remove ) { - QJson::Serializer serializer; QVariantMap jsonData; //QVariant setVar(stringMapToQVariantMap(set)); QVariant removeVar( stringListToQVariantList( remove ) ); jsonData.insert( QString( QLatin1String( "set" ) ), set ); jsonData.insert( QString( QLatin1String( "remove" ) ), removeVar ); - QByteArray jsonByteArray = serializer.serialize( QVariant( jsonData ) ); + QByteArray jsonByteArray = QJsonWrapper::toJson( QVariant( jsonData ) ); return jsonByteArray; } QByteArray JsonCreator::episodeActionListToJSON( const QList& episodeActions ) { - QJson::Serializer serializer; QVariantList jsonData; foreach( const EpisodeActionPtr episodeAction, episodeActions ) @@ -68,19 +65,18 @@ QByteArray JsonCreator::episodeActionListToJSON( const QList& jsonData.append( episodeActionToQVariantMap( episodeAction ) ); } - QByteArray jsonByteArray = serializer.serialize( QVariant( jsonData ) ); + QByteArray jsonByteArray = QJsonWrapper::toJson( QVariant( jsonData ) ); return jsonByteArray; } QByteArray JsonCreator::renameDeviceStringToJSON( const QString& caption, const QString& type ) { - QJson::Serializer serializer; QVariantMap jsonData; QVariant captionVar( caption ); QVariant typeVar( type ); jsonData.insert( QString( QLatin1String( "caption" ) ), captionVar ); jsonData.insert( QString( QLatin1String( "type" ) ), typeVar ); - QByteArray jsonByteArray = serializer.serialize( QVariant( jsonData ) ); + QByteArray jsonByteArray = QJsonWrapper::toJson( QVariant( jsonData ) ); return jsonByteArray; } @@ -130,7 +126,7 @@ QByteArray JsonCreator::deviceSynchronizationListsToJSON(const QList< QStringLis jsonStr.append(syncVar); jsonStr.append(QLatin1String(" ,\"stop-synchronize\" : ")); jsonStr.append(stopVar); - jsonStr.append(QLatin1String(" }\n")); + jsonStr.append(QLatin1String(" }")); return jsonStr.toLocal8Bit(); } diff --git a/3rdparty/libmygpo-qt/JsonCreator.h b/3rdparty/libmygpo-qt5/src/JsonCreator.h similarity index 100% rename from 3rdparty/libmygpo-qt/JsonCreator.h rename to 3rdparty/libmygpo-qt5/src/JsonCreator.h diff --git a/3rdparty/libmygpo-qt/Podcast.cpp b/3rdparty/libmygpo-qt5/src/Podcast.cpp similarity index 97% rename from 3rdparty/libmygpo-qt/Podcast.cpp rename to 3rdparty/libmygpo-qt5/src/Podcast.cpp index 589505452..bad7900dc 100644 --- a/3rdparty/libmygpo-qt/Podcast.cpp +++ b/3rdparty/libmygpo-qt5/src/Podcast.cpp @@ -22,7 +22,7 @@ #include "Podcast_p.h" -#include +#include "qjsonwrapper/Json.h" using namespace mygpo; @@ -181,9 +181,8 @@ bool PodcastPrivate::parse( const QVariant& data ) bool PodcastPrivate::parse( const QByteArray& data ) { - QJson::Parser parser; bool ok; - QVariant variant = parser.parse( data, &ok ); + QVariant variant = QJsonWrapper::parseJson( data, &ok ); if ( ok ) { if ( !parse( variant ) ) return false; @@ -197,8 +196,6 @@ bool PodcastPrivate::parse( const QByteArray& data ) void PodcastPrivate::parseData() { - //parsen und signal senden - QJson::Parser parser; if ( parse( m_reply->readAll( ) ) ) { emit q->finished(); diff --git a/3rdparty/libmygpo-qt/Podcast.h b/3rdparty/libmygpo-qt5/src/Podcast.h similarity index 100% rename from 3rdparty/libmygpo-qt/Podcast.h rename to 3rdparty/libmygpo-qt5/src/Podcast.h diff --git a/3rdparty/libmygpo-qt/PodcastList.cpp b/3rdparty/libmygpo-qt5/src/PodcastList.cpp similarity index 97% rename from 3rdparty/libmygpo-qt/PodcastList.cpp rename to 3rdparty/libmygpo-qt5/src/PodcastList.cpp index 7e2d9c4a4..fbd398796 100644 --- a/3rdparty/libmygpo-qt/PodcastList.cpp +++ b/3rdparty/libmygpo-qt5/src/PodcastList.cpp @@ -22,7 +22,7 @@ #include "PodcastList_p.h" -#include +#include "qjsonwrapper/Json.h" using namespace mygpo; @@ -71,9 +71,8 @@ bool PodcastListPrivate::parse( const QVariant& data ) bool PodcastListPrivate::parse( const QByteArray& data ) { - QJson::Parser parser; bool ok; - QVariant variant = parser.parse( data, &ok ); + QVariant variant = QJsonWrapper::parseJson( data, &ok ); if( ok ) { ok = ( parse( variant ) ); diff --git a/3rdparty/libmygpo-qt/PodcastList.h b/3rdparty/libmygpo-qt5/src/PodcastList.h similarity index 100% rename from 3rdparty/libmygpo-qt/PodcastList.h rename to 3rdparty/libmygpo-qt5/src/PodcastList.h diff --git a/3rdparty/libmygpo-qt/PodcastList_p.h b/3rdparty/libmygpo-qt5/src/PodcastList_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/PodcastList_p.h rename to 3rdparty/libmygpo-qt5/src/PodcastList_p.h diff --git a/3rdparty/libmygpo-qt/Podcast_p.h b/3rdparty/libmygpo-qt5/src/Podcast_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/Podcast_p.h rename to 3rdparty/libmygpo-qt5/src/Podcast_p.h diff --git a/3rdparty/libmygpo-qt/RequestHandler.cpp b/3rdparty/libmygpo-qt5/src/RequestHandler.cpp similarity index 99% rename from 3rdparty/libmygpo-qt/RequestHandler.cpp rename to 3rdparty/libmygpo-qt5/src/RequestHandler.cpp index dea1a62db..af504c5c5 100644 --- a/3rdparty/libmygpo-qt/RequestHandler.cpp +++ b/3rdparty/libmygpo-qt5/src/RequestHandler.cpp @@ -77,5 +77,5 @@ void RequestHandler::addAuthData( QNetworkRequest& request ) void RequestHandler::addUserAgent( QNetworkRequest &request ) { - request.setRawHeader("User-Agent", Config::instance()->userAgent().toAscii() ); + request.setRawHeader("User-Agent", Config::instance()->userAgent().toLatin1() ); } diff --git a/3rdparty/libmygpo-qt/RequestHandler.h b/3rdparty/libmygpo-qt5/src/RequestHandler.h similarity index 100% rename from 3rdparty/libmygpo-qt/RequestHandler.h rename to 3rdparty/libmygpo-qt5/src/RequestHandler.h diff --git a/3rdparty/libmygpo-qt/Settings.cpp b/3rdparty/libmygpo-qt5/src/Settings.cpp similarity index 96% rename from 3rdparty/libmygpo-qt/Settings.cpp rename to 3rdparty/libmygpo-qt5/src/Settings.cpp index a9045d9a1..c27e01c87 100644 --- a/3rdparty/libmygpo-qt/Settings.cpp +++ b/3rdparty/libmygpo-qt5/src/Settings.cpp @@ -22,7 +22,7 @@ #include "Settings_p.h" -#include +#include "qjsonwrapper/Json.h" using namespace mygpo; @@ -49,9 +49,8 @@ bool SettingsPrivate::parse( const QVariant& data ) bool SettingsPrivate::parse( const QByteArray& data ) { - QJson::Parser parser; bool ok; - QVariant variant = parser.parse( data, &ok ); + QVariant variant = QJsonWrapper::parseJson( data, &ok ); if( ok ) { ok = ( parse( variant ) ); @@ -63,7 +62,6 @@ void SettingsPrivate::parseData() { if( m_reply->error() == QNetworkReply::NoError ) { - QJson::Parser parser; if( parse( m_reply->readAll() ) ) { emit q->finished(); diff --git a/3rdparty/libmygpo-qt/Settings.h b/3rdparty/libmygpo-qt5/src/Settings.h similarity index 100% rename from 3rdparty/libmygpo-qt/Settings.h rename to 3rdparty/libmygpo-qt5/src/Settings.h diff --git a/3rdparty/libmygpo-qt/Settings_p.h b/3rdparty/libmygpo-qt5/src/Settings_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/Settings_p.h rename to 3rdparty/libmygpo-qt5/src/Settings_p.h diff --git a/3rdparty/libmygpo-qt/Tag.cpp b/3rdparty/libmygpo-qt5/src/Tag.cpp similarity index 100% rename from 3rdparty/libmygpo-qt/Tag.cpp rename to 3rdparty/libmygpo-qt5/src/Tag.cpp diff --git a/3rdparty/libmygpo-qt/Tag.h b/3rdparty/libmygpo-qt5/src/Tag.h similarity index 100% rename from 3rdparty/libmygpo-qt/Tag.h rename to 3rdparty/libmygpo-qt5/src/Tag.h diff --git a/3rdparty/libmygpo-qt/TagList.cpp b/3rdparty/libmygpo-qt5/src/TagList.cpp similarity index 97% rename from 3rdparty/libmygpo-qt/TagList.cpp rename to 3rdparty/libmygpo-qt5/src/TagList.cpp index d975a7273..4c19749cf 100644 --- a/3rdparty/libmygpo-qt/TagList.cpp +++ b/3rdparty/libmygpo-qt5/src/TagList.cpp @@ -22,7 +22,7 @@ #include "TagList_p.h" -#include +#include "qjsonwrapper/Json.h" using namespace mygpo; @@ -70,9 +70,8 @@ bool TagListPrivate::parse( const QVariant& data ) bool TagListPrivate::parse( const QByteArray& data ) { - QJson::Parser parser; bool ok; - QVariant variant = parser.parse( data, &ok ); + QVariant variant = QJsonWrapper::parseJson( data, &ok ); if( ok ) { ok = ( parse( variant ) ); diff --git a/3rdparty/libmygpo-qt/TagList.h b/3rdparty/libmygpo-qt5/src/TagList.h similarity index 100% rename from 3rdparty/libmygpo-qt/TagList.h rename to 3rdparty/libmygpo-qt5/src/TagList.h diff --git a/3rdparty/libmygpo-qt/TagList_p.h b/3rdparty/libmygpo-qt5/src/TagList_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/TagList_p.h rename to 3rdparty/libmygpo-qt5/src/TagList_p.h diff --git a/3rdparty/libmygpo-qt/Tag_p.h b/3rdparty/libmygpo-qt5/src/Tag_p.h similarity index 100% rename from 3rdparty/libmygpo-qt/Tag_p.h rename to 3rdparty/libmygpo-qt5/src/Tag_p.h diff --git a/3rdparty/libmygpo-qt/UrlBuilder.cpp b/3rdparty/libmygpo-qt5/src/UrlBuilder.cpp similarity index 98% rename from 3rdparty/libmygpo-qt/UrlBuilder.cpp rename to 3rdparty/libmygpo-qt5/src/UrlBuilder.cpp index e0ba7649a..eebcc3060 100644 --- a/3rdparty/libmygpo-qt/UrlBuilder.cpp +++ b/3rdparty/libmygpo-qt5/src/UrlBuilder.cpp @@ -74,7 +74,8 @@ QString UrlBuilder::getPodcastSearchUrl( const QString& query, Format f ) QString UrlBuilder::getSubscriptionsUrl( const QString& username, const QString& device, UrlBuilder::Format f) { - return s_server % QLatin1String( "/subscriptions/" ) % username % QLatin1String( "/" ) % device % getFormatExtension( f ); + QString deviceString = device.isNull() ? QString(QLatin1String("")) : (QLatin1String( "/" ) % device); + return s_server % QLatin1String( "/subscriptions/" ) % username % deviceString % getFormatExtension( f ); } QString UrlBuilder::getTopTagsUrl( uint i ) diff --git a/3rdparty/libmygpo-qt/UrlBuilder.h b/3rdparty/libmygpo-qt5/src/UrlBuilder.h similarity index 100% rename from 3rdparty/libmygpo-qt/UrlBuilder.h rename to 3rdparty/libmygpo-qt5/src/UrlBuilder.h diff --git a/3rdparty/libmygpo-qt/Version.h.in b/3rdparty/libmygpo-qt5/src/Version.h.in similarity index 100% rename from 3rdparty/libmygpo-qt/Version.h.in rename to 3rdparty/libmygpo-qt5/src/Version.h.in diff --git a/3rdparty/libmygpo-qt/mygpo_export.h b/3rdparty/libmygpo-qt5/src/mygpo_export.h similarity index 100% rename from 3rdparty/libmygpo-qt/mygpo_export.h rename to 3rdparty/libmygpo-qt5/src/mygpo_export.h diff --git a/3rdparty/libmygpo-qt5/src/qjsonwrapper/Json.cpp b/3rdparty/libmygpo-qt5/src/qjsonwrapper/Json.cpp new file mode 100644 index 000000000..4a8c2ac36 --- /dev/null +++ b/3rdparty/libmygpo-qt5/src/qjsonwrapper/Json.cpp @@ -0,0 +1,123 @@ +/* Copyright 2014, Uwe L. Korn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "Json.h" + +// Qt version specific includes +#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 ) + #include + #include +#else + #include + #include + #include +#endif + +namespace QJsonWrapper +{ + +QVariantMap +qobject2qvariant( const QObject* object ) +{ +#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 ) + QVariantMap map; + if ( object == NULL ) + { + return map; + } + + const QMetaObject* metaObject = object->metaObject(); + for ( int i = 0; i < metaObject->propertyCount(); ++i ) + { + QMetaProperty metaproperty = metaObject->property( i ); + if ( metaproperty.isReadable() ) + { + map[ QLatin1String( metaproperty.name() ) ] = object->property( metaproperty.name() ); + } + } + return map; +#else + return QJson::QObjectHelper::qobject2qvariant( object ); +#endif +} + + +void +qvariant2qobject( const QVariantMap& variant, QObject* object ) +{ +#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 ) + for ( QVariantMap::const_iterator iter = variant.begin(); iter != variant.end(); ++iter ) + { + QVariant property = object->property( iter.key().toLatin1() ); + Q_ASSERT( property.isValid() ); + if ( property.isValid() ) + { + QVariant value = iter.value(); + if ( value.canConvert( property.type() ) ) + { + value.convert( property.type() ); + object->setProperty( iter.key().toLatin1(), value ); + } else if ( QString( QLatin1String("QVariant") ).compare( QLatin1String( property.typeName() ) ) == 0 ) { + object->setProperty( iter.key().toLatin1(), value ); + } + } + } +#else + QJson::QObjectHelper::qvariant2qobject( variant, object ); +#endif +} + + +QVariant +parseJson( const QByteArray& jsonData, bool* ok ) +{ +#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 ) + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson( jsonData, &error ); + if ( ok != NULL ) + { + *ok = ( error.error == QJsonParseError::NoError ); + } + return doc.toVariant(); +#else + QJson::Parser p; + return p.parse( jsonData, ok ); +#endif +} + + +QByteArray +toJson( const QVariant &variant, bool* ok ) +{ +#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 ) + QJsonDocument doc = QJsonDocument::fromVariant( variant ); + if ( ok != NULL ) + { + *ok = !doc.isNull(); + } + return doc.toJson( QJsonDocument::Compact ); +#else + QJson::Serializer serializer; + return serializer.serialize( variant, ok ); +#endif +} + +} diff --git a/3rdparty/libmygpo-qt5/src/qjsonwrapper/Json.h b/3rdparty/libmygpo-qt5/src/qjsonwrapper/Json.h new file mode 100644 index 000000000..36d53a0f9 --- /dev/null +++ b/3rdparty/libmygpo-qt5/src/qjsonwrapper/Json.h @@ -0,0 +1,36 @@ +/* Copyright 2014, Uwe L. Korn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#pragma once +#ifndef QJSONWRAPPER_JSON_H +#define QJSONWRAPPER_JSON_H + +#include + +namespace QJsonWrapper +{ + QVariantMap qobject2qvariant( const QObject* object ); + void qvariant2qobject( const QVariantMap& variant, QObject* object ); + QVariant parseJson( const QByteArray& jsonData, bool* ok = 0 ); + QByteArray toJson( const QVariant &variant, bool* ok = 0 ); +} + +#endif // QJSONWRAPPER_JSON_H From 11938e3d79d4952b87831100898baaf0f78d7700 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sat, 11 Apr 2015 22:45:04 +0200 Subject: [PATCH 003/104] Update of qsqlite (Qt 5.0.0 version) --- 3rdparty/qsqlite/CMakeLists.txt | 11 +- .../qsqlite/clementinesqlcachedresult.cpp | 65 ++++--- 3rdparty/qsqlite/clementinesqlcachedresult.h | 63 ++++--- 3rdparty/qsqlite/qsql_sqlite.cpp | 171 +++++++++++------- 3rdparty/qsqlite/qsql_sqlite.h | 27 +-- 3rdparty/qsqlite/qsqlite.json | 3 + 3rdparty/qsqlite/smain.cpp | 65 ++----- 3rdparty/qsqlite/smain.h | 51 ++++++ 3rdparty/qsqlite/smain.patch | 11 -- 9 files changed, 278 insertions(+), 189 deletions(-) create mode 100644 3rdparty/qsqlite/qsqlite.json create mode 100644 3rdparty/qsqlite/smain.h delete mode 100644 3rdparty/qsqlite/smain.patch diff --git a/3rdparty/qsqlite/CMakeLists.txt b/3rdparty/qsqlite/CMakeLists.txt index 48ac16161..cd958d93c 100644 --- a/3rdparty/qsqlite/CMakeLists.txt +++ b/3rdparty/qsqlite/CMakeLists.txt @@ -5,18 +5,19 @@ add_definitions(-DQT_STATICPLUGIN) # Source files set(SQLITE-SOURCES qsql_sqlite.cpp - smain.cpp clementinesqlcachedresult.cpp + smain.cpp ) # Header files that have Q_OBJECT in set(SQLITE-MOC-HEADERS qsql_sqlite.h + smain.h ) set(SQLITE-WIN32-RESOURCES qsqlite_resource.rc) -qt4_wrap_cpp(SQLITE-SOURCES-MOC ${SQLITE-MOC-HEADERS}) +qt5_wrap_cpp(SQLITE-SOURCES-MOC ${SQLITE-MOC-HEADERS}) include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) @@ -40,7 +41,9 @@ add_library(qsqlite STATIC ${SQLITE-SOURCES-MOC} ${SQLITE-WIN32-RESOURCES} ) + +set_property(TARGET qsqlite PROPERTY QT_STATICPLUGIN 1) + target_link_libraries(qsqlite - ${SQLITE_LIBRARIES} - ${QT_LIBRARIES} + Qt5::Core Qt5::Sql ) diff --git a/3rdparty/qsqlite/clementinesqlcachedresult.cpp b/3rdparty/qsqlite/clementinesqlcachedresult.cpp index adca3ffec..5b3d4c1f7 100644 --- a/3rdparty/qsqlite/clementinesqlcachedresult.cpp +++ b/3rdparty/qsqlite/clementinesqlcachedresult.cpp @@ -1,17 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtSql module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -21,30 +22,31 @@ ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include "clementinesqlcachedresult.h" - #include #include #include +#include "clementinesqlcachedresult.h" + +QT_BEGIN_NAMESPACE + /* ClementineSqlCachedResult is a convenience class for databases that only allow forward only fetching. It will cache all the results so we can iterate @@ -302,12 +304,19 @@ ClementineSqlCachedResult::ValueCache &ClementineSqlCachedResult::cache() void ClementineSqlCachedResult::virtual_hook(int id, void *data) { - switch (id) { - case QSqlResult::DetachFromResultSet: - case QSqlResult::SetNumericalPrecision: - cleanup(); - break; - default: - QSqlResult::virtual_hook(id, data); - } + QSqlResult::virtual_hook(id, data); } + +void ClementineSqlCachedResult::detachFromResultSet() +{ + cleanup(); +} + +void ClementineSqlCachedResult::setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy policy) +{ + QSqlResult::setNumericalPrecisionPolicy(policy); + cleanup(); +} + + +QT_END_NAMESPACE diff --git a/3rdparty/qsqlite/clementinesqlcachedresult.h b/3rdparty/qsqlite/clementinesqlcachedresult.h index 1951789da..7447f2605 100644 --- a/3rdparty/qsqlite/clementinesqlcachedresult.h +++ b/3rdparty/qsqlite/clementinesqlcachedresult.h @@ -1,17 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtSql module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -21,35 +22,47 @@ ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ -#ifndef CLEMENTINECACHEDRESULT_P_H -#define CLEMENTINECACHEDRESULT_P_H +#ifndef QSQLCACHEDRESULT_P_H +#define QSQLCACHEDRESULT_P_H -#include +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "QtSql/qsqlresult.h" + +QT_BEGIN_NAMESPACE class QVariant; template class QVector; class ClementineSqlCachedResultPrivate; -class ClementineSqlCachedResult: public QSqlResult +class Q_SQL_EXPORT ClementineSqlCachedResult: public QSqlResult { public: virtual ~ClementineSqlCachedResult(); @@ -77,9 +90,13 @@ protected: ValueCache &cache(); void virtual_hook(int id, void *data); + void detachFromResultSet(); + void setNumericalPrecisionPolicy(QSql::NumericalPrecisionPolicy policy); private: bool cacheNext(); ClementineSqlCachedResultPrivate *d; }; -#endif // CLEMENTINESQLCACHEDRESULT_P_H +QT_END_NAMESPACE + +#endif // QSQLCACHEDRESULT_P_H diff --git a/3rdparty/qsqlite/qsql_sqlite.cpp b/3rdparty/qsqlite/qsql_sqlite.cpp index c7caae1b1..33d022848 100644 --- a/3rdparty/qsqlite/qsql_sqlite.cpp +++ b/3rdparty/qsqlite/qsql_sqlite.cpp @@ -1,17 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtSql module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -21,8 +22,8 @@ ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage @@ -33,8 +34,7 @@ ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. +** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -59,7 +59,10 @@ #include +Q_DECLARE_OPAQUE_POINTER(sqlite3*) Q_DECLARE_METATYPE(sqlite3*) + +Q_DECLARE_OPAQUE_POINTER(sqlite3_stmt*) Q_DECLARE_METATYPE(sqlite3_stmt*) QT_BEGIN_NAMESPACE @@ -84,10 +87,14 @@ static QVariant::Type qGetColumnType(const QString &tpName) return QVariant::Int; if (typeName == QLatin1String("double") || typeName == QLatin1String("float") + || typeName == QLatin1String("real") || typeName.startsWith(QLatin1String("numeric"))) return QVariant::Double; if (typeName == QLatin1String("blob")) return QVariant::ByteArray; + if (typeName == QLatin1String("boolean") + || typeName == QLatin1String("bool")) + return QVariant::Bool; return QVariant::String; } @@ -95,7 +102,7 @@ static QSqlError qMakeError(sqlite3 *access, const QString &descr, QSqlError::Er int errorCode = -1) { return QSqlError(descr, - QString::fromUtf16(static_cast(sqlite3_errmsg16(access))), + QString(reinterpret_cast(sqlite3_errmsg16(access))), type, errorCode); } @@ -104,6 +111,7 @@ class QSQLiteDriverPrivate public: inline QSQLiteDriverPrivate() : access(0) {} sqlite3 *access; + QList results; }; @@ -162,19 +170,44 @@ void QSQLiteResultPrivate::initColumns(bool emptyResultset) q->init(nCols); for (int i = 0; i < nCols; ++i) { - QString colName = QString::fromUtf16( - static_cast(sqlite3_column_name16(stmt, i)) + QString colName = QString(reinterpret_cast( + sqlite3_column_name16(stmt, i)) ).remove(QLatin1Char('"')); // must use typeName for resolving the type to match QSqliteDriver::record - QString typeName = QString::fromUtf16( - static_cast(sqlite3_column_decltype16(stmt, i))); - - int dotIdx = colName.lastIndexOf(QLatin1Char('.')); - QSqlField fld(colName.mid(dotIdx == -1 ? 0 : dotIdx + 1), qGetColumnType(typeName)); - + QString typeName = QString(reinterpret_cast( + sqlite3_column_decltype16(stmt, i))); // sqlite3_column_type is documented to have undefined behavior if the result set is empty int stp = emptyResultset ? -1 : sqlite3_column_type(stmt, i); + + QVariant::Type fieldType; + + if (!typeName.isEmpty()) { + fieldType = qGetColumnType(typeName); + } else { + // Get the proper type for the field based on stp value + switch (stp) { + case SQLITE_INTEGER: + fieldType = QVariant::Int; + break; + case SQLITE_FLOAT: + fieldType = QVariant::Double; + break; + case SQLITE_BLOB: + fieldType = QVariant::ByteArray; + break; + case SQLITE_TEXT: + fieldType = QVariant::String; + break; + case SQLITE_NULL: + default: + fieldType = QVariant::Invalid; + break; + } + } + + int dotIdx = colName.lastIndexOf(QLatin1Char('.')); + QSqlField fld(colName.mid(dotIdx == -1 ? 0 : dotIdx + 1), fieldType); fld.setSqlType(stp); rInf.append(fld); } @@ -245,9 +278,9 @@ bool QSQLiteResultPrivate::fetchNext(ClementineSqlCachedResult::ValueCache &valu values[i + idx] = QVariant(QVariant::String); break; default: - values[i + idx] = QString::fromUtf16(static_cast( + values[i + idx] = QString(reinterpret_cast( sqlite3_column_text16(stmt, i)), - sqlite3_column_bytes16(stmt, i) / sizeof(ushort)); + sqlite3_column_bytes16(stmt, i) / sizeof(QChar)); break; } } @@ -259,6 +292,7 @@ bool QSQLiteResultPrivate::fetchNext(ClementineSqlCachedResult::ValueCache &valu q->setAt(QSql::AfterLastRow); sqlite3_reset(stmt); return false; + case SQLITE_CONSTRAINT: case SQLITE_ERROR: // SQLITE_ERROR is a generic error code and we must call sqlite3_reset() // to get the specific error message. @@ -285,24 +319,21 @@ QSQLiteResult::QSQLiteResult(const QSQLiteDriver* db) { d = new QSQLiteResultPrivate(this); d->access = db->d->access; + db->d->results.append(this); } QSQLiteResult::~QSQLiteResult() { + const QSqlDriver *sqlDriver = driver(); + if (sqlDriver) + qobject_cast(sqlDriver)->d->results.removeOne(this); d->cleanup(); delete d; } void QSQLiteResult::virtual_hook(int id, void *data) { - switch (id) { - case QSqlResult::DetachFromResultSet: - if (d->stmt) - sqlite3_reset(d->stmt); - break; - default: - ClementineSqlCachedResult::virtual_hook(id, data); - } + ClementineSqlCachedResult::virtual_hook(id, data); } bool QSQLiteResult::reset(const QString &query) @@ -321,12 +352,14 @@ bool QSQLiteResult::prepare(const QString &query) setSelect(false); + const void *pzTail = NULL; + #if (SQLITE_VERSION_NUMBER >= 3003011) int res = sqlite3_prepare16_v2(d->access, query.constData(), (query.size() + 1) * sizeof(QChar), - &d->stmt, 0); + &d->stmt, &pzTail); #else int res = sqlite3_prepare16(d->access, query.constData(), (query.size() + 1) * sizeof(QChar), - &d->stmt, 0); + &d->stmt, &pzTail); #endif if (res != SQLITE_OK) { @@ -334,6 +367,11 @@ bool QSQLiteResult::prepare(const QString &query) "Unable to execute statement"), QSqlError::StatementError, res)); d->finalize(); return false; + } else if (pzTail && !QString(reinterpret_cast(pzTail)).trimmed().isEmpty()) { + setLastError(qMakeError(d->access, QCoreApplication::translate("QSQLiteResult", + "Unable to execute multiple statements at a time"), QSqlError::StatementError, SQLITE_MISUSE)); + d->finalize(); + return false; } return true; } @@ -371,6 +409,7 @@ bool QSQLiteResult::exec() ba->size(), SQLITE_STATIC); break; } case QVariant::Int: + case QVariant::Bool: res = sqlite3_bind_int(d->stmt, i + 1, value.toInt()); break; case QVariant::Double: @@ -403,7 +442,7 @@ bool QSQLiteResult::exec() } } else { setLastError(QSqlError(QCoreApplication::translate("QSQLiteResult", - "Parameter count mismatch"), QString(), QSqlError::StatementError)); + "Parameter count mismatch") + QString::number(paramCount, 10) + "/" + QString::number(values.count(), 10), QString(), QSqlError::StatementError)); return false; } d->skippedStatus = d->fetchNext(d->firstRow, 0, true); @@ -449,9 +488,15 @@ QSqlRecord QSQLiteResult::record() const return d->rInf; } +void QSQLiteResult::detachFromResultSet() +{ + if (d->stmt) + sqlite3_reset(d->stmt); +} + QVariant QSQLiteResult::handle() const { - return qVariantFromValue(d->stmt); + return QVariant::fromValue(d->stmt); } ///////////////////////////////////////////////////////// @@ -500,32 +545,6 @@ bool QSQLiteDriver::hasFeature(DriverFeature f) const return false; } -static int qGetSqliteTimeout(QString opts) -{ - enum { DefaultTimeout = 5000 }; - - opts.remove(QLatin1Char(' ')); - foreach(QString option, opts.split(QLatin1Char(';'))) { - if (option.startsWith(QLatin1String("QSQLITE_BUSY_TIMEOUT="))) { - bool ok; - int nt = option.mid(21).toInt(&ok); - if (ok) - return nt; - } - } - return DefaultTimeout; -} - -static int qGetSqliteOpenMode(QString opts) -{ - opts.remove(QLatin1Char(' ')); - foreach(QString option, opts.split(QLatin1Char(';'))) { - if (option == QLatin1String("QSQLITE_OPEN_READONLY")) - return SQLITE_OPEN_READONLY; - } - return SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; -} - /* SQLite dbs have no user name, passwords, hosts or ports. just file names. @@ -537,13 +556,35 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c if (db.isEmpty()) return false; + bool sharedCache = false; + int openMode = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, timeOut=5000; + QStringList opts=QString(conOpts).remove(QLatin1Char(' ')).split(QLatin1Char(';')); + foreach(const QString &option, opts) { + if (option.startsWith(QLatin1String("QSQLITE_BUSY_TIMEOUT="))) { + bool ok; + int nt = option.mid(21).toInt(&ok); + if (ok) + timeOut = nt; + } + if (option == QLatin1String("QSQLITE_OPEN_READONLY")) + openMode = SQLITE_OPEN_READONLY; + if (option == QLatin1String("QSQLITE_ENABLE_SHARED_CACHE")) + sharedCache = true; + } - if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, qGetSqliteOpenMode(conOpts), NULL) == SQLITE_OK) { - sqlite3_busy_timeout(d->access, qGetSqliteTimeout(conOpts)); + sqlite3_enable_shared_cache(sharedCache); + + if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, openMode, NULL) == SQLITE_OK) { + sqlite3_busy_timeout(d->access, timeOut); setOpen(true); setOpenError(false); return true; } else { + if (d->access) { + sqlite3_close(d->access); + d->access = 0; + } + setLastError(qMakeError(d->access, tr("Error opening database"), QSqlError::ConnectionError)); setOpenError(true); @@ -554,6 +595,10 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c void QSQLiteDriver::close() { if (isOpen()) { + foreach (QSQLiteResult *result, d->results) { + result->d->finalize(); + } + if (sqlite3_close(d->access) != SQLITE_OK) setLastError(qMakeError(d->access, tr("Error closing database"), QSqlError::ConnectionError)); @@ -705,7 +750,7 @@ QSqlRecord QSQLiteDriver::record(const QString &tbl) const QVariant QSQLiteDriver::handle() const { - return qVariantFromValue(d->access); + return QVariant::fromValue(d->access); } QString QSQLiteDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const diff --git a/3rdparty/qsqlite/qsql_sqlite.h b/3rdparty/qsqlite/qsql_sqlite.h index f949aefe8..78db7303b 100644 --- a/3rdparty/qsqlite/qsql_sqlite.h +++ b/3rdparty/qsqlite/qsql_sqlite.h @@ -1,17 +1,18 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtSql module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser @@ -21,8 +22,8 @@ ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage @@ -33,8 +34,7 @@ ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. +** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -42,8 +42,8 @@ #ifndef QSQL_SQLITE_H #define QSQL_SQLITE_H -#include -#include +#include +#include #include "clementinesqlcachedresult.h" struct sqlite3; @@ -79,6 +79,7 @@ protected: int numRowsAffected(); QVariant lastInsertId() const; QSqlRecord record() const; + void detachFromResultSet(); void virtual_hook(int id, void *data); private: diff --git a/3rdparty/qsqlite/qsqlite.json b/3rdparty/qsqlite/qsqlite.json new file mode 100644 index 000000000..0c105eade --- /dev/null +++ b/3rdparty/qsqlite/qsqlite.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "QSQLITE" ] +} diff --git a/3rdparty/qsqlite/smain.cpp b/3rdparty/qsqlite/smain.cpp index 4fb132b5e..35b6b5d71 100644 --- a/3rdparty/qsqlite/smain.cpp +++ b/3rdparty/qsqlite/smain.cpp @@ -1,59 +1,40 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include -#include -#include "qsql_sqlite.h" +#include "smain.h" QT_BEGIN_NAMESPACE -class QSQLiteDriverPlugin : public QSqlDriverPlugin -{ -public: - QSQLiteDriverPlugin(); - - QSqlDriver* create(const QString &); - QStringList keys() const; -}; - QSQLiteDriverPlugin::QSQLiteDriverPlugin() : QSqlDriverPlugin() { @@ -68,14 +49,4 @@ QSqlDriver* QSQLiteDriverPlugin::create(const QString &name) return 0; } -QStringList QSQLiteDriverPlugin::keys() const -{ - QStringList l; - l << QLatin1String("QSQLITE"); - return l; -} - -Q_EXPORT_STATIC_PLUGIN(QSQLiteDriverPlugin) -Q_EXPORT_PLUGIN2(qsqlite, QSQLiteDriverPlugin) - QT_END_NAMESPACE diff --git a/3rdparty/qsqlite/smain.h b/3rdparty/qsqlite/smain.h new file mode 100644 index 000000000..1d91a4544 --- /dev/null +++ b/3rdparty/qsqlite/smain.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include "qsql_sqlite.h" + +QT_BEGIN_NAMESPACE + +class QSQLiteDriverPlugin : public QSqlDriverPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QSqlDriverFactoryInterface" FILE "qsqlite.json") + +public: + QSQLiteDriverPlugin(); + + QSqlDriver* create(const QString &); +}; + +QT_END_NAMESPACE diff --git a/3rdparty/qsqlite/smain.patch b/3rdparty/qsqlite/smain.patch deleted file mode 100644 index e5e596ecc..000000000 --- a/3rdparty/qsqlite/smain.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- smain.cpp.old 2010-03-22 17:34:03.000000000 +0000 -+++ smain.cpp 2010-03-22 17:34:08.000000000 +0000 -@@ -41,7 +41,7 @@ - - #include - #include --#include "../../../../src/sql/drivers/sqlite/qsql_sqlite.h" -+#include "qsql_sqlite.h" - - QT_BEGIN_NAMESPACE - From 39f120d405fd7bca2a31664509d1a5aa377a0761 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sat, 11 Apr 2015 22:45:27 +0200 Subject: [PATCH 004/104] Update qxt to qt5 --- 3rdparty/qxt/CMakeLists.txt | 5 +- 3rdparty/qxt/media-keys.patch | 432 ---------------------- 3rdparty/qxt/meta-modifier.patch | 15 - 3rdparty/qxt/qxtglobal.cpp | 76 ++-- 3rdparty/qxt/qxtglobal.h | 92 +++-- 3rdparty/qxt/qxtglobalshortcut.cpp | 87 +++-- 3rdparty/qxt/qxtglobalshortcut.h | 55 +-- 3rdparty/qxt/qxtglobalshortcut_mac.cpp | 461 +++++++++++++----------- 3rdparty/qxt/qxtglobalshortcut_p.h | 147 ++++---- 3rdparty/qxt/qxtglobalshortcut_win.cpp | 476 +++++++++++++------------ 3rdparty/qxt/qxtglobalshortcut_x11.cpp | 373 ++++++++++++------- 11 files changed, 1019 insertions(+), 1200 deletions(-) delete mode 100644 3rdparty/qxt/media-keys.patch delete mode 100644 3rdparty/qxt/meta-modifier.patch diff --git a/3rdparty/qxt/CMakeLists.txt b/3rdparty/qxt/CMakeLists.txt index 73954ffc9..af8765568 100644 --- a/3rdparty/qxt/CMakeLists.txt +++ b/3rdparty/qxt/CMakeLists.txt @@ -11,6 +11,7 @@ set(QXT-MOC-HEADERS find_package(X11) include_directories(${X11_INCLUDE_DIR}) +include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) if(WIN32) set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_win.cpp) @@ -20,9 +21,11 @@ else(WIN32) set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_x11.cpp) endif(WIN32) -QT4_WRAP_CPP(QXT-SOURCES-MOC ${QXT-MOC-HEADERS}) +QT5_WRAP_CPP(QXT-SOURCES-MOC ${QXT-MOC-HEADERS}) ADD_LIBRARY(qxt STATIC ${QXT-SOURCES} ${QXT-SOURCES-MOC} ) + +QT5_USE_MODULES(qxt Core Widgets X11Extras) diff --git a/3rdparty/qxt/media-keys.patch b/3rdparty/qxt/media-keys.patch deleted file mode 100644 index 31e52f3da..000000000 --- a/3rdparty/qxt/media-keys.patch +++ /dev/null @@ -1,432 +0,0 @@ -diff -ru libqxt-old/src/gui/keymapper_x11.h libqxt/src/gui/keymapper_x11.h ---- libqxt-old/src/gui/keymapper_x11.h 2010-04-21 15:17:56.000000000 +0100 -+++ libqxt/src/gui/keymapper_x11.h 2010-04-21 15:18:16.000000000 +0100 -@@ -0,0 +1,364 @@ -+#ifndef KEYMAPPER_X11_H -+#define KEYMAPPER_X11_H -+ -+// (davidsansome) Nicked from qkeymapper_x11.cpp -+ -+#include -+ -+#define XK_MISCELLANY -+#define XK_LATIN1 -+#define XK_KOREAN -+#define XK_XKB_KEYS -+#include -+ -+// -+// Keyboard event translation -+// -+ -+#ifndef XK_ISO_Left_Tab -+#define XK_ISO_Left_Tab 0xFE20 -+#endif -+ -+#ifndef XK_dead_hook -+#define XK_dead_hook 0xFE61 -+#endif -+ -+#ifndef XK_dead_horn -+#define XK_dead_horn 0xFE62 -+#endif -+ -+#ifndef XK_Codeinput -+#define XK_Codeinput 0xFF37 -+#endif -+ -+#ifndef XK_Kanji_Bangou -+#define XK_Kanji_Bangou 0xFF37 /* same as codeinput */ -+#endif -+ -+// Fix old X libraries -+#ifndef XK_KP_Home -+#define XK_KP_Home 0xFF95 -+#endif -+#ifndef XK_KP_Left -+#define XK_KP_Left 0xFF96 -+#endif -+#ifndef XK_KP_Up -+#define XK_KP_Up 0xFF97 -+#endif -+#ifndef XK_KP_Right -+#define XK_KP_Right 0xFF98 -+#endif -+#ifndef XK_KP_Down -+#define XK_KP_Down 0xFF99 -+#endif -+#ifndef XK_KP_Prior -+#define XK_KP_Prior 0xFF9A -+#endif -+#ifndef XK_KP_Next -+#define XK_KP_Next 0xFF9B -+#endif -+#ifndef XK_KP_End -+#define XK_KP_End 0xFF9C -+#endif -+#ifndef XK_KP_Insert -+#define XK_KP_Insert 0xFF9E -+#endif -+#ifndef XK_KP_Delete -+#define XK_KP_Delete 0xFF9F -+#endif -+ -+// the next lines are taken from XFree > 4.0 (X11/XF86keysyms.h), defining some special -+// multimedia keys. They are included here as not every system has them. -+#define XF86XK_Standby 0x1008FF10 -+#define XF86XK_AudioLowerVolume 0x1008FF11 -+#define XF86XK_AudioMute 0x1008FF12 -+#define XF86XK_AudioRaiseVolume 0x1008FF13 -+#define XF86XK_AudioPlay 0x1008FF14 -+#define XF86XK_AudioStop 0x1008FF15 -+#define XF86XK_AudioPrev 0x1008FF16 -+#define XF86XK_AudioNext 0x1008FF17 -+#define XF86XK_HomePage 0x1008FF18 -+#define XF86XK_Calculator 0x1008FF1D -+#define XF86XK_Mail 0x1008FF19 -+#define XF86XK_Start 0x1008FF1A -+#define XF86XK_Search 0x1008FF1B -+#define XF86XK_AudioRecord 0x1008FF1C -+#define XF86XK_Back 0x1008FF26 -+#define XF86XK_Forward 0x1008FF27 -+#define XF86XK_Stop 0x1008FF28 -+#define XF86XK_Refresh 0x1008FF29 -+#define XF86XK_Favorites 0x1008FF30 -+#define XF86XK_AudioPause 0x1008FF31 -+#define XF86XK_AudioMedia 0x1008FF32 -+#define XF86XK_MyComputer 0x1008FF33 -+#define XF86XK_OpenURL 0x1008FF38 -+#define XF86XK_Launch0 0x1008FF40 -+#define XF86XK_Launch1 0x1008FF41 -+#define XF86XK_Launch2 0x1008FF42 -+#define XF86XK_Launch3 0x1008FF43 -+#define XF86XK_Launch4 0x1008FF44 -+#define XF86XK_Launch5 0x1008FF45 -+#define XF86XK_Launch6 0x1008FF46 -+#define XF86XK_Launch7 0x1008FF47 -+#define XF86XK_Launch8 0x1008FF48 -+#define XF86XK_Launch9 0x1008FF49 -+#define XF86XK_LaunchA 0x1008FF4A -+#define XF86XK_LaunchB 0x1008FF4B -+#define XF86XK_LaunchC 0x1008FF4C -+#define XF86XK_LaunchD 0x1008FF4D -+#define XF86XK_LaunchE 0x1008FF4E -+#define XF86XK_LaunchF 0x1008FF4F -+// end of XF86keysyms.h -+ -+// Special keys used by Qtopia, mapped into the X11 private keypad range. -+#define QTOPIAXK_Select 0x11000601 -+#define QTOPIAXK_Yes 0x11000602 -+#define QTOPIAXK_No 0x11000603 -+#define QTOPIAXK_Cancel 0x11000604 -+#define QTOPIAXK_Printer 0x11000605 -+#define QTOPIAXK_Execute 0x11000606 -+#define QTOPIAXK_Sleep 0x11000607 -+#define QTOPIAXK_Play 0x11000608 -+#define QTOPIAXK_Zoom 0x11000609 -+#define QTOPIAXK_Context1 0x1100060A -+#define QTOPIAXK_Context2 0x1100060B -+#define QTOPIAXK_Context3 0x1100060C -+#define QTOPIAXK_Context4 0x1100060D -+#define QTOPIAXK_Call 0x1100060E -+#define QTOPIAXK_Hangup 0x1100060F -+#define QTOPIAXK_Flip 0x11000610 -+ -+// keyboard mapping table -+static const unsigned int KeyTbl[] = { -+ -+ // misc keys -+ -+ XK_Escape, Qt::Key_Escape, -+ XK_Tab, Qt::Key_Tab, -+ XK_ISO_Left_Tab, Qt::Key_Backtab, -+ XK_BackSpace, Qt::Key_Backspace, -+ XK_Return, Qt::Key_Return, -+ XK_Insert, Qt::Key_Insert, -+ XK_Delete, Qt::Key_Delete, -+ XK_Clear, Qt::Key_Delete, -+ XK_Pause, Qt::Key_Pause, -+ XK_Print, Qt::Key_Print, -+ 0x1005FF60, Qt::Key_SysReq, // hardcoded Sun SysReq -+ 0x1007ff00, Qt::Key_SysReq, // hardcoded X386 SysReq -+ -+ // cursor movement -+ -+ XK_Home, Qt::Key_Home, -+ XK_End, Qt::Key_End, -+ XK_Left, Qt::Key_Left, -+ XK_Up, Qt::Key_Up, -+ XK_Right, Qt::Key_Right, -+ XK_Down, Qt::Key_Down, -+ XK_Prior, Qt::Key_PageUp, -+ XK_Next, Qt::Key_PageDown, -+ -+ // modifiers -+ -+ XK_Shift_L, Qt::Key_Shift, -+ XK_Shift_R, Qt::Key_Shift, -+ XK_Shift_Lock, Qt::Key_Shift, -+ XK_Control_L, Qt::Key_Control, -+ XK_Control_R, Qt::Key_Control, -+ XK_Meta_L, Qt::Key_Meta, -+ XK_Meta_R, Qt::Key_Meta, -+ XK_Alt_L, Qt::Key_Alt, -+ XK_Alt_R, Qt::Key_Alt, -+ XK_Caps_Lock, Qt::Key_CapsLock, -+ XK_Num_Lock, Qt::Key_NumLock, -+ XK_Scroll_Lock, Qt::Key_ScrollLock, -+ XK_Super_L, Qt::Key_Super_L, -+ XK_Super_R, Qt::Key_Super_R, -+ XK_Menu, Qt::Key_Menu, -+ XK_Hyper_L, Qt::Key_Hyper_L, -+ XK_Hyper_R, Qt::Key_Hyper_R, -+ XK_Help, Qt::Key_Help, -+ 0x1000FF74, Qt::Key_Backtab, // hardcoded HP backtab -+ 0x1005FF10, Qt::Key_F11, // hardcoded Sun F36 (labeled F11) -+ 0x1005FF11, Qt::Key_F12, // hardcoded Sun F37 (labeled F12) -+ -+ // numeric and function keypad keys -+ -+ XK_KP_Space, Qt::Key_Space, -+ XK_KP_Tab, Qt::Key_Tab, -+ XK_KP_Enter, Qt::Key_Enter, -+ //XK_KP_F1, Qt::Key_F1, -+ //XK_KP_F2, Qt::Key_F2, -+ //XK_KP_F3, Qt::Key_F3, -+ //XK_KP_F4, Qt::Key_F4, -+ XK_KP_Home, Qt::Key_Home, -+ XK_KP_Left, Qt::Key_Left, -+ XK_KP_Up, Qt::Key_Up, -+ XK_KP_Right, Qt::Key_Right, -+ XK_KP_Down, Qt::Key_Down, -+ XK_KP_Prior, Qt::Key_PageUp, -+ XK_KP_Next, Qt::Key_PageDown, -+ XK_KP_End, Qt::Key_End, -+ XK_KP_Begin, Qt::Key_Clear, -+ XK_KP_Insert, Qt::Key_Insert, -+ XK_KP_Delete, Qt::Key_Delete, -+ XK_KP_Equal, Qt::Key_Equal, -+ XK_KP_Multiply, Qt::Key_Asterisk, -+ XK_KP_Add, Qt::Key_Plus, -+ XK_KP_Separator, Qt::Key_Comma, -+ XK_KP_Subtract, Qt::Key_Minus, -+ XK_KP_Decimal, Qt::Key_Period, -+ XK_KP_Divide, Qt::Key_Slash, -+ -+ // International input method support keys -+ -+ // International & multi-key character composition -+ XK_ISO_Level3_Shift, Qt::Key_AltGr, -+ XK_Multi_key, Qt::Key_Multi_key, -+ XK_Codeinput, Qt::Key_Codeinput, -+ XK_SingleCandidate, Qt::Key_SingleCandidate, -+ XK_MultipleCandidate, Qt::Key_MultipleCandidate, -+ XK_PreviousCandidate, Qt::Key_PreviousCandidate, -+ -+ // Misc Functions -+ XK_Mode_switch, Qt::Key_Mode_switch, -+ XK_script_switch, Qt::Key_Mode_switch, -+ -+ // Japanese keyboard support -+ XK_Kanji, Qt::Key_Kanji, -+ XK_Muhenkan, Qt::Key_Muhenkan, -+ //XK_Henkan_Mode, Qt::Key_Henkan_Mode, -+ XK_Henkan_Mode, Qt::Key_Henkan, -+ XK_Henkan, Qt::Key_Henkan, -+ XK_Romaji, Qt::Key_Romaji, -+ XK_Hiragana, Qt::Key_Hiragana, -+ XK_Katakana, Qt::Key_Katakana, -+ XK_Hiragana_Katakana, Qt::Key_Hiragana_Katakana, -+ XK_Zenkaku, Qt::Key_Zenkaku, -+ XK_Hankaku, Qt::Key_Hankaku, -+ XK_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku, -+ XK_Touroku, Qt::Key_Touroku, -+ XK_Massyo, Qt::Key_Massyo, -+ XK_Kana_Lock, Qt::Key_Kana_Lock, -+ XK_Kana_Shift, Qt::Key_Kana_Shift, -+ XK_Eisu_Shift, Qt::Key_Eisu_Shift, -+ XK_Eisu_toggle, Qt::Key_Eisu_toggle, -+ //XK_Kanji_Bangou, Qt::Key_Kanji_Bangou, -+ //XK_Zen_Koho, Qt::Key_Zen_Koho, -+ //XK_Mae_Koho, Qt::Key_Mae_Koho, -+ XK_Kanji_Bangou, Qt::Key_Codeinput, -+ XK_Zen_Koho, Qt::Key_MultipleCandidate, -+ XK_Mae_Koho, Qt::Key_PreviousCandidate, -+ -+#ifdef XK_KOREAN -+ // Korean keyboard support -+ XK_Hangul, Qt::Key_Hangul, -+ XK_Hangul_Start, Qt::Key_Hangul_Start, -+ XK_Hangul_End, Qt::Key_Hangul_End, -+ XK_Hangul_Hanja, Qt::Key_Hangul_Hanja, -+ XK_Hangul_Jamo, Qt::Key_Hangul_Jamo, -+ XK_Hangul_Romaja, Qt::Key_Hangul_Romaja, -+ //XK_Hangul_Codeinput, Qt::Key_Hangul_Codeinput, -+ XK_Hangul_Codeinput, Qt::Key_Codeinput, -+ XK_Hangul_Jeonja, Qt::Key_Hangul_Jeonja, -+ XK_Hangul_Banja, Qt::Key_Hangul_Banja, -+ XK_Hangul_PreHanja, Qt::Key_Hangul_PreHanja, -+ XK_Hangul_PostHanja, Qt::Key_Hangul_PostHanja, -+ //XK_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate, -+ //XK_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate, -+ //XK_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate, -+ XK_Hangul_SingleCandidate, Qt::Key_SingleCandidate, -+ XK_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate, -+ XK_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate, -+ XK_Hangul_Special, Qt::Key_Hangul_Special, -+ //XK_Hangul_switch, Qt::Key_Hangul_switch, -+ XK_Hangul_switch, Qt::Key_Mode_switch, -+#endif // XK_KOREAN -+ -+ // dead keys -+ XK_dead_grave, Qt::Key_Dead_Grave, -+ XK_dead_acute, Qt::Key_Dead_Acute, -+ XK_dead_circumflex, Qt::Key_Dead_Circumflex, -+ XK_dead_tilde, Qt::Key_Dead_Tilde, -+ XK_dead_macron, Qt::Key_Dead_Macron, -+ XK_dead_breve, Qt::Key_Dead_Breve, -+ XK_dead_abovedot, Qt::Key_Dead_Abovedot, -+ XK_dead_diaeresis, Qt::Key_Dead_Diaeresis, -+ XK_dead_abovering, Qt::Key_Dead_Abovering, -+ XK_dead_doubleacute, Qt::Key_Dead_Doubleacute, -+ XK_dead_caron, Qt::Key_Dead_Caron, -+ XK_dead_cedilla, Qt::Key_Dead_Cedilla, -+ XK_dead_ogonek, Qt::Key_Dead_Ogonek, -+ XK_dead_iota, Qt::Key_Dead_Iota, -+ XK_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound, -+ XK_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound, -+ XK_dead_belowdot, Qt::Key_Dead_Belowdot, -+ XK_dead_hook, Qt::Key_Dead_Hook, -+ XK_dead_horn, Qt::Key_Dead_Horn, -+ -+ // Special multimedia keys -+ // currently only tested with MS internet keyboard -+ -+ // browsing keys -+ XF86XK_Back, Qt::Key_Back, -+ XF86XK_Forward, Qt::Key_Forward, -+ XF86XK_Stop, Qt::Key_Stop, -+ XF86XK_Refresh, Qt::Key_Refresh, -+ XF86XK_Favorites, Qt::Key_Favorites, -+ XF86XK_AudioMedia, Qt::Key_LaunchMedia, -+ XF86XK_OpenURL, Qt::Key_OpenUrl, -+ XF86XK_HomePage, Qt::Key_HomePage, -+ XF86XK_Search, Qt::Key_Search, -+ -+ // media keys -+ XF86XK_AudioLowerVolume, Qt::Key_VolumeDown, -+ XF86XK_AudioMute, Qt::Key_VolumeMute, -+ XF86XK_AudioRaiseVolume, Qt::Key_VolumeUp, -+ XF86XK_AudioPlay, Qt::Key_MediaPlay, -+ XF86XK_AudioStop, Qt::Key_MediaStop, -+ XF86XK_AudioPrev, Qt::Key_MediaPrevious, -+ XF86XK_AudioNext, Qt::Key_MediaNext, -+ XF86XK_AudioRecord, Qt::Key_MediaRecord, -+ -+ // launch keys -+ XF86XK_Mail, Qt::Key_LaunchMail, -+ XF86XK_MyComputer, Qt::Key_Launch0, -+ XF86XK_Calculator, Qt::Key_Launch1, -+ XF86XK_Standby, Qt::Key_Standby, -+ -+ XF86XK_Launch0, Qt::Key_Launch2, -+ XF86XK_Launch1, Qt::Key_Launch3, -+ XF86XK_Launch2, Qt::Key_Launch4, -+ XF86XK_Launch3, Qt::Key_Launch5, -+ XF86XK_Launch4, Qt::Key_Launch6, -+ XF86XK_Launch5, Qt::Key_Launch7, -+ XF86XK_Launch6, Qt::Key_Launch8, -+ XF86XK_Launch7, Qt::Key_Launch9, -+ XF86XK_Launch8, Qt::Key_LaunchA, -+ XF86XK_Launch9, Qt::Key_LaunchB, -+ XF86XK_LaunchA, Qt::Key_LaunchC, -+ XF86XK_LaunchB, Qt::Key_LaunchD, -+ XF86XK_LaunchC, Qt::Key_LaunchE, -+ XF86XK_LaunchD, Qt::Key_LaunchF, -+ -+ // Qtopia keys -+ QTOPIAXK_Select, Qt::Key_Select, -+ QTOPIAXK_Yes, Qt::Key_Yes, -+ QTOPIAXK_No, Qt::Key_No, -+ QTOPIAXK_Cancel, Qt::Key_Cancel, -+ QTOPIAXK_Printer, Qt::Key_Printer, -+ QTOPIAXK_Execute, Qt::Key_Execute, -+ QTOPIAXK_Sleep, Qt::Key_Sleep, -+ QTOPIAXK_Play, Qt::Key_Play, -+ QTOPIAXK_Zoom, Qt::Key_Zoom, -+ QTOPIAXK_Context1, Qt::Key_Context1, -+ QTOPIAXK_Context2, Qt::Key_Context2, -+ QTOPIAXK_Context3, Qt::Key_Context3, -+ QTOPIAXK_Context4, Qt::Key_Context4, -+ QTOPIAXK_Call, Qt::Key_Call, -+ QTOPIAXK_Hangup, Qt::Key_Hangup, -+ QTOPIAXK_Flip, Qt::Key_Flip, -+ -+ 0, 0 -+}; -+ -+#endif // KEYMAPPER_X11_H -diff -ru libqxt-old/src/gui/qxtglobalshortcut_win.cpp libqxt/src/gui/qxtglobalshortcut_win.cpp ---- libqxt-old/src/gui/qxtglobalshortcut_win.cpp 2010-04-21 15:17:56.000000000 +0100 -+++ libqxt/src/gui/qxtglobalshortcut_win.cpp 2010-04-21 15:18:16.000000000 +0100 -@@ -156,6 +156,21 @@ - case Qt::Key_Slash: - return VK_DIVIDE; - -+ case Qt::Key_MediaNext: -+ return VK_MEDIA_NEXT_TRACK; -+ case Qt::Key_MediaPrevious: -+ return VK_MEDIA_PREV_TRACK; -+ case Qt::Key_MediaStop: -+ return VK_MEDIA_STOP; -+ case Qt::Key_MediaPlay: -+ return VK_MEDIA_PLAY_PAUSE; -+ case Qt::Key_VolumeDown: -+ return VK_VOLUME_DOWN; -+ case Qt::Key_VolumeUp: -+ return VK_VOLUME_UP; -+ case Qt::Key_VolumeMute: -+ return VK_VOLUME_MUTE; -+ - // numbers - case Qt::Key_0: - case Qt::Key_1: -diff -ru libqxt-old/src/gui/qxtglobalshortcut_x11.cpp libqxt/src/gui/qxtglobalshortcut_x11.cpp ---- libqxt-old/src/gui/qxtglobalshortcut_x11.cpp 2010-04-21 15:17:56.000000000 +0100 -+++ libqxt/src/gui/qxtglobalshortcut_x11.cpp 2010-04-21 15:18:16.000000000 +0100 -@@ -26,6 +26,8 @@ - #include - #include - -+#include "keymapper_x11.h" -+ - static int (*original_x_errhandler)(Display* display, XErrorEvent* event); - - static int qxt_x_errhandler(Display* display, XErrorEvent *event) -@@ -81,8 +83,25 @@ - - quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) - { -+ // (davidsansome) Try the table from QKeyMapper first - this seems to be -+ // the only way to get Keysyms for the media keys. -+ unsigned int keysym = 0; -+ int i = 0; -+ while (KeyTbl[i]) { -+ if (KeyTbl[i+1] == static_cast(key)) { -+ keysym = KeyTbl[i]; -+ break; -+ } -+ i += 2; -+ } -+ -+ // If that didn't work then fall back on XStringToKeysym -+ if (!keysym) { -+ keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data()); -+ } -+ - Display* display = QX11Info::display(); -- return XKeysymToKeycode(display, XStringToKeysym(QKeySequence(key).toString().toLatin1().data())); -+ return XKeysymToKeycode(display, keysym); - } - - bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) diff --git a/3rdparty/qxt/meta-modifier.patch b/3rdparty/qxt/meta-modifier.patch deleted file mode 100644 index f77b97a57..000000000 --- a/3rdparty/qxt/meta-modifier.patch +++ /dev/null @@ -1,15 +0,0 @@ -Index: qxtglobalshortcut_x11.cpp -=================================================================== ---- qxtglobalshortcut_x11.cpp (revision 1208) -+++ qxtglobalshortcut_x11.cpp (working copy) -@@ -74,8 +74,9 @@ - native |= ControlMask; - if (modifiers & Qt::AltModifier) - native |= Mod1Mask; -+ if (modifiers & Qt::MetaModifier) -+ native |= Mod4Mask; - // TODO: resolve these? -- //if (modifiers & Qt::MetaModifier) - //if (modifiers & Qt::KeypadModifier) - //if (modifiers & Qt::GroupSwitchModifier) - return native; diff --git a/3rdparty/qxt/qxtglobal.cpp b/3rdparty/qxt/qxtglobal.cpp index fe7b9e782..3da47c146 100644 --- a/3rdparty/qxt/qxtglobal.cpp +++ b/3rdparty/qxt/qxtglobal.cpp @@ -1,27 +1,33 @@ + /**************************************************************************** - ** - ** Copyright (C) Qxt Foundation. Some rights reserved. - ** - ** This file is part of the QxtCore module of the Qxt library. - ** - ** This library is free software; you can redistribute it and/or modify it - ** under the terms of the Common Public License, version 1.0, as published - ** by IBM, and/or under the terms of the GNU Lesser General Public License, - ** version 2.1, as published by the Free Software Foundation. - ** - ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY - ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY - ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR - ** FITNESS FOR A PARTICULAR PURPOSE. - ** - ** You should have received a copy of the CPL and the LGPL along with this - ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files - ** included with the source distribution for more information. - ** If you did not receive a copy of the licenses, contact the Qxt Foundation. - ** - ** - ** - ****************************************************************************/ +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ #include "qxtglobal.h" @@ -74,7 +80,7 @@ \sa QXT_VERSION_STR */ -const char* qxtVersion() +const char * qxtVersion() { return QXT_VERSION_STR; } @@ -170,13 +176,14 @@ void MyTestPrivate::doQuux() { * \relates * Declares that a public class has a related private class. * - * This shuold be put in the private section of the public class. The parameter is the name of the public class. + * This shuold be put in the private section of the public class. The + * parameter \a PUB must be the name of the public class. */ /*! * \macro QXT_DECLARE_PUBLIC(PUB) * \relates - * Declares that a private class has a related public class. + * Declares that a private class has a related public class named \a PUB. * * This may be put anywhere in the declaration of the private class. The parameter is the name of the public class. */ @@ -187,23 +194,26 @@ void MyTestPrivate::doQuux() { * Initializes resources owned by the private class. * * This should be called from the public class's constructor, - * before qxt_d() is used for the first time. The parameter is the name of the public class. + * before qxt_d() is used for the first time. The parameter \a PUB must be + * the name of the public class. */ /*! * \macro QXT_D(PUB) * \relates - * Returns a reference in the current scope named "d" to the private class. + * Returns a reference in the current scope named "d" to the private class + * associated with the public class \a PUB. * - * This function is only available in a class using \a QXT_DECLARE_PRIVATE. + * This function is only available in a class using QXT_DECLARE_PRIVATE(). */ /*! * \macro QXT_P(PUB) * \relates - * Creates a reference in the current scope named "q" to the public class. + * Creates a reference in the current scope named "q" to the public class + * named \a PUB. * - * This macro only works in a class using \a QXT_DECLARE_PUBLIC. + * This macro only works in a class using QXT_DECLARE_PUBLIC(). */ /*! @@ -228,7 +238,7 @@ void MyTestPrivate::doQuux() { * \relates * Returns a reference to the public class. * - * This function is only available in a class using \a QXT_DECLARE_PUBLIC. + * This function is only available in a class using QXT_DECLARE_PUBLIC(). */ /*! @@ -236,6 +246,6 @@ void MyTestPrivate::doQuux() { * \relates * Returns a const reference to the public class. * - * This function is only available in a class using \a QXT_DECLARE_PUBLIC. + * This function is only available in a class using QXT_DECLARE_PUBLIC(). * This overload will be automatically used in const functions. */ diff --git a/3rdparty/qxt/qxtglobal.h b/3rdparty/qxt/qxtglobal.h index 575372dcd..7d5abfbe0 100644 --- a/3rdparty/qxt/qxtglobal.h +++ b/3rdparty/qxt/qxtglobal.h @@ -1,47 +1,57 @@ + /**************************************************************************** - ** - ** Copyright (C) Qxt Foundation. Some rights reserved. - ** - ** This file is part of the QxtCore module of the Qxt library. - ** - ** This library is free software; you can redistribute it and/or modify it - ** under the terms of the Common Public License, version 1.0, as published - ** by IBM, and/or under the terms of the GNU Lesser General Public License, - ** version 2.1, as published by the Free Software Foundation. - ** - ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY - ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY - ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR - ** FITNESS FOR A PARTICULAR PURPOSE. - ** - ** You should have received a copy of the CPL and the LGPL along with this - ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files - ** included with the source distribution for more information. - ** If you did not receive a copy of the licenses, contact the Qxt Foundation. - ** - ** - ** - ****************************************************************************/ +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ #ifndef QXTGLOBAL_H #define QXTGLOBAL_H #include -#define QXT_VERSION 0x000600 -#define QXT_VERSION_STR "0.6.0" +#define QXT_VERSION 0x000700 +#define QXT_VERSION_STR "0.7.0" //--------------------------global macros------------------------------ #ifndef QXT_NO_MACROS +#ifndef _countof +#define _countof(x) (sizeof(x)/sizeof(*x)) +#endif + #endif // QXT_NO_MACROS //--------------------------export macros------------------------------ #define QXT_DLLEXPORT DO_NOT_USE_THIS_ANYMORE -#if !defined(QXT_STATIC) +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) # if defined(BUILD_QXT_CORE) # define QXT_CORE_EXPORT Q_DECL_EXPORT # else @@ -51,7 +61,7 @@ # define QXT_CORE_EXPORT #endif // BUILD_QXT_CORE -#if !defined(QXT_STATIC) +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) # if defined(BUILD_QXT_GUI) # define QXT_GUI_EXPORT Q_DECL_EXPORT # else @@ -61,7 +71,7 @@ # define QXT_GUI_EXPORT #endif // BUILD_QXT_GUI -#if !defined(QXT_STATIC) +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) # if defined(BUILD_QXT_NETWORK) # define QXT_NETWORK_EXPORT Q_DECL_EXPORT # else @@ -71,7 +81,7 @@ # define QXT_NETWORK_EXPORT #endif // BUILD_QXT_NETWORK -#if !defined(QXT_STATIC) +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) # if defined(BUILD_QXT_SQL) # define QXT_SQL_EXPORT Q_DECL_EXPORT # else @@ -81,7 +91,7 @@ # define QXT_SQL_EXPORT #endif // BUILD_QXT_SQL -#if !defined(QXT_STATIC) +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) # if defined(BUILD_QXT_WEB) # define QXT_WEB_EXPORT Q_DECL_EXPORT # else @@ -91,7 +101,7 @@ # define QXT_WEB_EXPORT #endif // BUILD_QXT_WEB -#if !defined(QXT_STATIC) +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) # if defined(BUILD_QXT_BERKELEY) # define QXT_BERKELEY_EXPORT Q_DECL_EXPORT # else @@ -101,7 +111,7 @@ # define QXT_BERKELEY_EXPORT #endif // BUILD_QXT_BERKELEY -#if !defined(QXT_STATIC) +#if !defined(QXT_STATIC) && !defined(QXT_DOXYGEN_RUN) # if defined(BUILD_QXT_ZEROCONF) # define QXT_ZEROCONF_EXPORT Q_DECL_EXPORT # else @@ -111,7 +121,7 @@ # define QXT_ZEROCONF_EXPORT #endif // QXT_ZEROCONF_EXPORT -#if defined BUILD_QXT_CORE || defined BUILD_QXT_GUI || defined BUILD_QXT_SQL || defined BUILD_QXT_NETWORK || defined BUILD_QXT_WEB || defined BUILD_QXT_BERKELEY || defined BUILD_QXT_ZEROCONF +#if defined(BUILD_QXT_CORE) || defined(BUILD_QXT_GUI) || defined(BUILD_QXT_SQL) || defined(BUILD_QXT_NETWORK) || defined(BUILD_QXT_WEB) || defined(BUILD_QXT_BERKELEY) || defined(BUILD_QXT_ZEROCONF) # define BUILD_QXT #endif @@ -167,6 +177,14 @@ protected: { return *qxt_p_ptr; } + inline PUB* qxt_ptr() + { + return qxt_p_ptr; + } + inline const PUB* qxt_ptr() const + { + return qxt_p_ptr; + } private: PUB* qxt_p_ptr; @@ -198,6 +216,14 @@ public: { return *static_cast(pvt); } + inline PVT * operator->() + { + return static_cast(pvt); + } + inline const PVT * operator->() const + { + return static_cast(pvt); + } private: QxtPrivateInterface(const QxtPrivateInterface&) { } QxtPrivateInterface& operator=(const QxtPrivateInterface&) { } diff --git a/3rdparty/qxt/qxtglobalshortcut.cpp b/3rdparty/qxt/qxtglobalshortcut.cpp index ef378f965..6ea380ca7 100644 --- a/3rdparty/qxt/qxtglobalshortcut.cpp +++ b/3rdparty/qxt/qxtglobalshortcut.cpp @@ -1,47 +1,69 @@ -/**************************************************************************** - ** - ** Copyright (C) Qxt Foundation. Some rights reserved. - ** - ** This file is part of the QxtGui module of the Qxt library. - ** - ** This library is free software; you can redistribute it and/or modify it - ** under the terms of the Common Public License, version 1.0, as published - ** by IBM, and/or under the terms of the GNU Lesser General Public License, - ** version 2.1, as published by the Free Software Foundation. - ** - ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY - ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY - ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR - ** FITNESS FOR A PARTICULAR PURPOSE. - ** - ** You should have received a copy of the CPL and the LGPL along with this - ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files - ** included with the source distribution for more information. - ** If you did not receive a copy of the licenses, contact the Qxt Foundation. - ** - ** - ** - ****************************************************************************/ #include "qxtglobalshortcut.h" +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + #include "qxtglobalshortcut_p.h" #include #include bool QxtGlobalShortcutPrivate::error = false; +#ifndef Q_WS_MAC int QxtGlobalShortcutPrivate::ref = 0; +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) QAbstractEventDispatcher::EventFilter QxtGlobalShortcutPrivate::prevEventFilter = 0; +#endif +#endif // Q_WS_MAC QHash, QxtGlobalShortcut*> QxtGlobalShortcutPrivate::shortcuts; QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate() : enabled(true), key(Qt::Key(0)), mods(Qt::NoModifier) { +#ifndef Q_WS_MAC if (!ref++) +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) prevEventFilter = QAbstractEventDispatcher::instance()->setEventFilter(eventFilter); +#else + QAbstractEventDispatcher::instance()->installNativeEventFilter(this); +#endif +#endif // Q_WS_MAC } QxtGlobalShortcutPrivate::~QxtGlobalShortcutPrivate() { +#ifndef Q_WS_MAC if (!--ref) +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) QAbstractEventDispatcher::instance()->setEventFilter(prevEventFilter); +#else + QAbstractEventDispatcher::instance()->removeNativeEventFilter(this); +#endif +#endif // Q_WS_MAC } bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut) @@ -52,19 +74,23 @@ bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut) const quint32 nativeKey = nativeKeycode(key); const quint32 nativeMods = nativeModifiers(mods); const bool res = registerShortcut(nativeKey, nativeMods); - shortcuts.insert(qMakePair(nativeKey, nativeMods), &qxt_p()); - if (!res) + if (res) + shortcuts.insert(qMakePair(nativeKey, nativeMods), &qxt_p()); + else qWarning() << "QxtGlobalShortcut failed to register:" << QKeySequence(key + mods).toString(); return res; } bool QxtGlobalShortcutPrivate::unsetShortcut() { + bool res = false; const quint32 nativeKey = nativeKeycode(key); const quint32 nativeMods = nativeModifiers(mods); - const bool res = unregisterShortcut(nativeKey, nativeMods); - shortcuts.remove(qMakePair(nativeKey, nativeMods)); - if (!res) + if (shortcuts.value(qMakePair(nativeKey, nativeMods)) == &qxt_p()) + res = unregisterShortcut(nativeKey, nativeMods); + if (res) + shortcuts.remove(qMakePair(nativeKey, nativeMods)); + else qWarning() << "QxtGlobalShortcut failed to unregister:" << QKeySequence(key + mods).toString(); key = Qt::Key(0); mods = Qt::KeyboardModifiers(0); @@ -80,7 +106,7 @@ void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativ /*! \class QxtGlobalShortcut - \inmodule QxtGui + \inmodule QxtWidgets \brief The QxtGlobalShortcut class provides a global shortcut aka "hotkey". A global shortcut triggers even if the application is not active. This @@ -189,3 +215,4 @@ void QxtGlobalShortcut::setDisabled(bool disabled) { qxt_d().enabled = !disabled; } + diff --git a/3rdparty/qxt/qxtglobalshortcut.h b/3rdparty/qxt/qxtglobalshortcut.h index a97ba2ddb..907e04c5d 100644 --- a/3rdparty/qxt/qxtglobalshortcut.h +++ b/3rdparty/qxt/qxtglobalshortcut.h @@ -1,28 +1,34 @@ -/**************************************************************************** - ** - ** Copyright (C) Qxt Foundation. Some rights reserved. - ** - ** This file is part of the QxtGui module of the Qxt library. - ** - ** This library is free software; you can redistribute it and/or modify it - ** under the terms of the Common Public License, version 1.0, as published - ** by IBM, and/or under the terms of the GNU Lesser General Public License, - ** version 2.1, as published by the Free Software Foundation. - ** - ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY - ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY - ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR - ** FITNESS FOR A PARTICULAR PURPOSE. - ** - ** You should have received a copy of the CPL and the LGPL along with this - ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files - ** included with the source distribution for more information. - ** If you did not receive a copy of the licenses, contact the Qxt Foundation. - ** - ** - ** - ****************************************************************************/ #ifndef QXTGLOBALSHORTCUT_H +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + #define QXTGLOBALSHORTCUT_H #include "qxtglobal.h" @@ -56,3 +62,4 @@ Q_SIGNALS: }; #endif // QXTGLOBALSHORTCUT_H + diff --git a/3rdparty/qxt/qxtglobalshortcut_mac.cpp b/3rdparty/qxt/qxtglobalshortcut_mac.cpp index 0bcea7f36..58b9a9043 100644 --- a/3rdparty/qxt/qxtglobalshortcut_mac.cpp +++ b/3rdparty/qxt/qxtglobalshortcut_mac.cpp @@ -1,207 +1,258 @@ +#include /**************************************************************************** - ** - ** Copyright (C) Qxt Foundation. Some rights reserved. - ** - ** This file is part of the QxtGui module of the Qxt library. - ** - ** This library is free software; you can redistribute it and/or modify it - ** under the terms of the Common Public License, version 1.0, as published - ** by IBM, and/or under the terms of the GNU Lesser General Public License, - ** version 2.1, as published by the Free Software Foundation. - ** - ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY - ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY - ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR - ** FITNESS FOR A PARTICULAR PURPOSE. - ** - ** You should have received a copy of the CPL and the LGPL along with this - ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files - ** included with the source distribution for more information. - ** If you did not receive a copy of the licenses, contact the Qxt Foundation. - ** - ** - ** - ****************************************************************************/ -#include -#include "qxtglobalshortcut_p.h" -#include -#include -#include -#include +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ -typedef QPair Identifier; -static QMap keyRefs; -static QHash keyIDs; -static quint32 hotKeySerial = 0; -static bool qxt_mac_handler_installed = false; - -OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void* data) -{ - // pass event to the app event filter - Q_UNUSED(data); - qApp->macEventFilter(nextHandler, event); - return noErr; -} - -bool QxtGlobalShortcutPrivate::eventFilter(void* message) -//bool QxtGlobalShortcutPrivate::macEventFilter(EventHandlerCallRef caller, EventRef event) -{ - EventRef event = (EventRef) message; - if (GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed) - { - EventHotKeyID keyID; - GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(keyID), NULL, &keyID); - Identifier id = keyIDs.key(keyID.id); - activateShortcut(id.second, id.first); - } - return false; -} - -quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) -{ - quint32 native = 0; - if (modifiers & Qt::ShiftModifier) - native |= shiftKeyBit; - if (modifiers & Qt::ControlModifier) - native |= cmdKey; - if (modifiers & Qt::AltModifier) - native |= optionKey; - if (modifiers & Qt::MetaModifier) - native |= controlKey; - if (modifiers & Qt::KeypadModifier) - native |= kEventKeyModifierNumLockMask; - return native; -} - -quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) -{ - UTF16Char ch; - // Constants found in NSEvent.h from AppKit.framework - if (key == Qt::Key_Up) ch = 0xF700; - else if (key == Qt::Key_Down) ch = 0xF701; - else if (key == Qt::Key_Left) ch = 0xF702; - else if (key == Qt::Key_Right) ch = 0xF703; - else if (key >= Qt::Key_F1 && key <= Qt::Key_F35) - ch = key - Qt::Key_F1 + 0xF704; - else if (key == Qt::Key_Insert) ch = 0xF727; - else if (key == Qt::Key_Delete) ch = 0xF728; - else if (key == Qt::Key_Home) ch = 0xF729; - else if (key == Qt::Key_End) ch = 0xF72B; - else if (key == Qt::Key_PageUp) ch = 0xF72C; - else if (key == Qt::Key_PageDown) ch = 0xF72D; - else if (key == Qt::Key_Print) ch = 0xF72E; - else if (key == Qt::Key_ScrollLock) ch = 0xF72F; - else if (key == Qt::Key_Pause) ch = 0xF730; - else if (key == Qt::Key_SysReq) ch = 0xF731; - else if (key == Qt::Key_Stop) ch = 0xF734; - else if (key == Qt::Key_Menu) ch = 0xF735; - else if (key == Qt::Key_Select) ch = 0xF741; - else if (key == Qt::Key_Execute) ch = 0xF742; - else if (key == Qt::Key_Help) ch = 0xF746; - else if (key == Qt::Key_Mode_switch) ch = 0xF747; - else if (key == Qt::Key_Escape) ch = 27; - else if (key == Qt::Key_Return) ch = 13; - else if (key == Qt::Key_Enter) ch = 3; - else if (key == Qt::Key_Tab) ch = 9; - else ch = key; - - KeyboardLayoutRef layout; - KeyboardLayoutKind layoutKind; - KLGetCurrentKeyboardLayout(&layout); - KLGetKeyboardLayoutProperty(layout, kKLKind, const_cast(reinterpret_cast(&layoutKind))); - - if (layoutKind == kKLKCHRKind) - { // no Unicode available - if (ch > 255) return 0; - - char* data; - KLGetKeyboardLayoutProperty(layout, kKLKCHRData, const_cast(reinterpret_cast(&data))); - int ct = *reinterpret_cast(data + 258); - for (int i = 0; i < ct; i++) - { - char* keyTable = data + 260 + 128 * i; - for (int j = 0; j < 128; j++) - { - if (keyTable[j] == ch) return j; - } - } - - return 0; - } - - char* data; - KLGetKeyboardLayoutProperty(layout, kKLuchrData, const_cast(reinterpret_cast(&data))); - UCKeyboardLayout* header = reinterpret_cast(data); - UCKeyboardTypeHeader* table = header->keyboardTypeList; - - for (quint32 i=0; i < header->keyboardTypeCount; i++) - { - UCKeyStateRecordsIndex* stateRec = 0; - if (table[i].keyStateRecordsIndexOffset != 0) - { - stateRec = reinterpret_cast(data + table[i].keyStateRecordsIndexOffset); - if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0; - } - - UCKeyToCharTableIndex* charTable = reinterpret_cast(data + table[i].keyToCharTableIndexOffset); - if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue; - - for (quint32 j=0; j < charTable->keyToCharTableCount; j++) - { - UCKeyOutput* keyToChar = reinterpret_cast(data + charTable->keyToCharTableOffsets[j]); - for (quint32 k=0; k < charTable->keyToCharTableSize; k++) - { - if (keyToChar[k] & kUCKeyOutputTestForIndexMask) - { - long idx = keyToChar[k] & kUCKeyOutputGetIndexMask; - if (stateRec && idx < stateRec->keyStateRecordCount) - { - UCKeyStateRecord* rec = reinterpret_cast(data + stateRec->keyStateRecordOffsets[idx]); - if (rec->stateZeroCharData == ch) return k; - } - } - else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE) - { - if (keyToChar[k] == ch) return k; - } - } // for k - } // for j - } // for i - - return 0; -} - -bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) -{ - if (!qxt_mac_handler_installed) - { - EventTypeSpec t; - t.eventClass = kEventClassKeyboard; - t.eventKind = kEventHotKeyPressed; - InstallApplicationEventHandler(&qxt_mac_handle_hot_key, 1, &t, NULL, NULL); - } - - EventHotKeyID keyID; - keyID.signature = 'cute'; - keyID.id = ++hotKeySerial; - - EventHotKeyRef ref = 0; - bool rv = !RegisterEventHotKey(nativeKey, nativeMods, keyID, GetApplicationEventTarget(), 0, &ref); - if (rv) - { - keyIDs.insert(Identifier(nativeMods, nativeKey), keyID.id); - keyRefs.insert(keyID.id, ref); - } - qDebug() << ref; - return rv; -} - -bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) -{ - Identifier id(nativeMods, nativeKey); - if (!keyIDs.contains(id)) return false; - - EventHotKeyRef ref = keyRefs.take(keyIDs[id]); - keyIDs.remove(id); - return !UnregisterEventHotKey(ref); -} +#include "qxtglobalshortcut_p.h" +#include +#include +#include +#include + +typedef QPair Identifier; +static QMap keyRefs; +static QHash keyIDs; +static quint32 hotKeySerial = 0; +static bool qxt_mac_handler_installed = false; + +OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void* data) +{ + Q_UNUSED(nextHandler); + Q_UNUSED(data); + if (GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed) + { + EventHotKeyID keyID; + GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(keyID), NULL, &keyID); + Identifier id = keyIDs.key(keyID.id); + QxtGlobalShortcutPrivate::activateShortcut(id.second, id.first); + } + return noErr; +} + +quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) +{ + quint32 native = 0; + if (modifiers & Qt::ShiftModifier) + native |= shiftKey; + if (modifiers & Qt::ControlModifier) + native |= cmdKey; + if (modifiers & Qt::AltModifier) + native |= optionKey; + if (modifiers & Qt::MetaModifier) + native |= controlKey; + if (modifiers & Qt::KeypadModifier) + native |= kEventKeyModifierNumLockMask; + return native; +} + +quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) +{ + UTF16Char ch; + // Constants found in NSEvent.h from AppKit.framework + switch (key) + { + case Qt::Key_Return: + return kVK_Return; + case Qt::Key_Enter: + return kVK_ANSI_KeypadEnter; + case Qt::Key_Tab: + return kVK_Tab; + case Qt::Key_Space: + return kVK_Space; + case Qt::Key_Backspace: + return kVK_Delete; + case Qt::Key_Control: + return kVK_Command; + case Qt::Key_Shift: + return kVK_Shift; + case Qt::Key_CapsLock: + return kVK_CapsLock; + case Qt::Key_Option: + return kVK_Option; + case Qt::Key_Meta: + return kVK_Control; + case Qt::Key_F17: + return kVK_F17; + case Qt::Key_VolumeUp: + return kVK_VolumeUp; + case Qt::Key_VolumeDown: + return kVK_VolumeDown; + case Qt::Key_F18: + return kVK_F18; + case Qt::Key_F19: + return kVK_F19; + case Qt::Key_F20: + return kVK_F20; + case Qt::Key_F5: + return kVK_F5; + case Qt::Key_F6: + return kVK_F6; + case Qt::Key_F7: + return kVK_F7; + case Qt::Key_F3: + return kVK_F3; + case Qt::Key_F8: + return kVK_F8; + case Qt::Key_F9: + return kVK_F9; + case Qt::Key_F11: + return kVK_F11; + case Qt::Key_F13: + return kVK_F13; + case Qt::Key_F16: + return kVK_F16; + case Qt::Key_F14: + return kVK_F14; + case Qt::Key_F10: + return kVK_F10; + case Qt::Key_F12: + return kVK_F12; + case Qt::Key_F15: + return kVK_F15; + case Qt::Key_Help: + return kVK_Help; + case Qt::Key_Home: + return kVK_Home; + case Qt::Key_PageUp: + return kVK_PageUp; + case Qt::Key_Delete: + return kVK_ForwardDelete; + case Qt::Key_F4: + return kVK_F4; + case Qt::Key_End: + return kVK_End; + case Qt::Key_F2: + return kVK_F2; + case Qt::Key_PageDown: + return kVK_PageDown; + case Qt::Key_F1: + return kVK_F1; + case Qt::Key_Left: + return kVK_LeftArrow; + case Qt::Key_Right: + return kVK_RightArrow; + case Qt::Key_Down: + return kVK_DownArrow; + case Qt::Key_Up: + return kVK_UpArrow; + default: + ; + } + + if (key == Qt::Key_Escape) ch = 27; + else if (key == Qt::Key_Return) ch = 13; + else if (key == Qt::Key_Enter) ch = 3; + else if (key == Qt::Key_Tab) ch = 9; + else ch = key; + + CFDataRef currentLayoutData; + TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource(); + + if (currentKeyboard == NULL) + return 0; + + currentLayoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); + CFRelease(currentKeyboard); + if (currentLayoutData == NULL) + return 0; + + UCKeyboardLayout* header = (UCKeyboardLayout*)CFDataGetBytePtr(currentLayoutData); + UCKeyboardTypeHeader* table = header->keyboardTypeList; + + uint8_t *data = (uint8_t*)header; + // God, would a little documentation for this shit kill you... + for (quint32 i=0; i < header->keyboardTypeCount; i++) + { + UCKeyStateRecordsIndex* stateRec = 0; + if (table[i].keyStateRecordsIndexOffset != 0) + { + stateRec = reinterpret_cast(data + table[i].keyStateRecordsIndexOffset); + if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0; + } + + UCKeyToCharTableIndex* charTable = reinterpret_cast(data + table[i].keyToCharTableIndexOffset); + if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue; + + for (quint32 j=0; j < charTable->keyToCharTableCount; j++) + { + UCKeyOutput* keyToChar = reinterpret_cast(data + charTable->keyToCharTableOffsets[j]); + for (quint32 k=0; k < charTable->keyToCharTableSize; k++) + { + if (keyToChar[k] & kUCKeyOutputTestForIndexMask) + { + long idx = keyToChar[k] & kUCKeyOutputGetIndexMask; + if (stateRec && idx < stateRec->keyStateRecordCount) + { + UCKeyStateRecord* rec = reinterpret_cast(data + stateRec->keyStateRecordOffsets[idx]); + if (rec->stateZeroCharData == ch) return k; + } + } + else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE) + { + if (keyToChar[k] == ch) return k; + } + } // for k + } // for j + } // for i + return 0; +} + +bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) +{ + if (!qxt_mac_handler_installed) + { + EventTypeSpec t; + t.eventClass = kEventClassKeyboard; + t.eventKind = kEventHotKeyPressed; + InstallApplicationEventHandler(&qxt_mac_handle_hot_key, 1, &t, NULL, NULL); + } + + EventHotKeyID keyID; + keyID.signature = 'cute'; + keyID.id = ++hotKeySerial; + + EventHotKeyRef ref = 0; + bool rv = !RegisterEventHotKey(nativeKey, nativeMods, keyID, GetApplicationEventTarget(), 0, &ref); + if (rv) + { + keyIDs.insert(Identifier(nativeMods, nativeKey), keyID.id); + keyRefs.insert(keyID.id, ref); + } + return rv; +} + +bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) +{ + Identifier id(nativeMods, nativeKey); + if (!keyIDs.contains(id)) return false; + + EventHotKeyRef ref = keyRefs.take(keyIDs[id]); + keyIDs.remove(id); + return !UnregisterEventHotKey(ref); +} diff --git a/3rdparty/qxt/qxtglobalshortcut_p.h b/3rdparty/qxt/qxtglobalshortcut_p.h index 4570396fe..1a788852e 100644 --- a/3rdparty/qxt/qxtglobalshortcut_p.h +++ b/3rdparty/qxt/qxtglobalshortcut_p.h @@ -1,63 +1,84 @@ -/**************************************************************************** - ** - ** Copyright (C) Qxt Foundation. Some rights reserved. - ** - ** This file is part of the QxtGui module of the Qxt library. - ** - ** This library is free software; you can redistribute it and/or modify it - ** under the terms of the Common Public License, version 1.0, as published - ** by IBM, and/or under the terms of the GNU Lesser General Public License, - ** version 2.1, as published by the Free Software Foundation. - ** - ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY - ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY - ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR - ** FITNESS FOR A PARTICULAR PURPOSE. - ** - ** You should have received a copy of the CPL and the LGPL along with this - ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files - ** included with the source distribution for more information. - ** If you did not receive a copy of the licenses, contact the Qxt Foundation. - ** - ** - ** - ****************************************************************************/ -#ifndef QXTGLOBALSHORTCUT_P_H -#define QXTGLOBALSHORTCUT_P_H - -#include "qxtglobalshortcut.h" -#include -#include -#include - -class QxtGlobalShortcutPrivate : public QxtPrivate -{ -public: - QXT_DECLARE_PUBLIC(QxtGlobalShortcut) - QxtGlobalShortcutPrivate(); - ~QxtGlobalShortcutPrivate(); - - bool enabled; - Qt::Key key; - Qt::KeyboardModifiers mods; - - bool setShortcut(const QKeySequence& shortcut); - bool unsetShortcut(); - - static bool error; - static int ref; - static QAbstractEventDispatcher::EventFilter prevEventFilter; - static bool eventFilter(void* message); - -private: - static quint32 nativeKeycode(Qt::Key keycode); - static quint32 nativeModifiers(Qt::KeyboardModifiers modifiers); - - static bool registerShortcut(quint32 nativeKey, quint32 nativeMods); - static bool unregisterShortcut(quint32 nativeKey, quint32 nativeMods); - static void activateShortcut(quint32 nativeKey, quint32 nativeMods); - - static QHash, QxtGlobalShortcut*> shortcuts; -}; - -#endif // QXTGLOBALSHORTCUT_P_H +#ifndef QXTGLOBALSHORTCUT_P_H +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#define QXTGLOBALSHORTCUT_P_H + +#include "qxtglobalshortcut.h" +#include +#include +#include + +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) +#include +#endif + + +class QxtGlobalShortcutPrivate : public QxtPrivate +#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) + ,public QAbstractNativeEventFilter +#endif +{ +public: + QXT_DECLARE_PUBLIC(QxtGlobalShortcut) + QxtGlobalShortcutPrivate(); + ~QxtGlobalShortcutPrivate(); + + bool enabled; + Qt::Key key; + Qt::KeyboardModifiers mods; + + bool setShortcut(const QKeySequence& shortcut); + bool unsetShortcut(); + + static bool error; +#ifndef Q_WS_MAC + static int ref; +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) + static QAbstractEventDispatcher::EventFilter prevEventFilter; + static bool eventFilter(void* message); +#else + virtual bool nativeEventFilter(const QByteArray & eventType, void * message, long * result); +#endif // QT_VERSION < QT_VERSION_CHECK(5,0,0) +#endif // Q_WS_MAC + + static void activateShortcut(quint32 nativeKey, quint32 nativeMods); + +private: + static quint32 nativeKeycode(Qt::Key keycode); + static quint32 nativeModifiers(Qt::KeyboardModifiers modifiers); + + static bool registerShortcut(quint32 nativeKey, quint32 nativeMods); + static bool unregisterShortcut(quint32 nativeKey, quint32 nativeMods); + + static QHash, QxtGlobalShortcut*> shortcuts; +}; + +#endif // QXTGLOBALSHORTCUT_P_H diff --git a/3rdparty/qxt/qxtglobalshortcut_win.cpp b/3rdparty/qxt/qxtglobalshortcut_win.cpp index d81f1089d..1f4b611d9 100644 --- a/3rdparty/qxt/qxtglobalshortcut_win.cpp +++ b/3rdparty/qxt/qxtglobalshortcut_win.cpp @@ -1,229 +1,247 @@ -/**************************************************************************** - ** - ** Copyright (C) Qxt Foundation. Some rights reserved. - ** - ** This file is part of the QxtGui module of the Qxt library. - ** - ** This library is free software; you can redistribute it and/or modify it - ** under the terms of the Common Public License, version 1.0, as published - ** by IBM, and/or under the terms of the GNU Lesser General Public License, - ** version 2.1, as published by the Free Software Foundation. - ** - ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY - ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY - ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR - ** FITNESS FOR A PARTICULAR PURPOSE. - ** - ** You should have received a copy of the CPL and the LGPL along with this - ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files - ** included with the source distribution for more information. - ** If you did not receive a copy of the licenses, contact the Qxt Foundation. - ** - ** - ** - ****************************************************************************/ -#include "qxtglobalshortcut_p.h" -#include - -bool QxtGlobalShortcutPrivate::eventFilter(void* message) -{ - MSG* msg = static_cast(message); - if (msg->message == WM_HOTKEY) - { - const quint32 keycode = HIWORD(msg->lParam); - const quint32 modifiers = LOWORD(msg->lParam); - activateShortcut(keycode, modifiers); - } - return false; -} - -quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) -{ - // MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN - quint32 native = 0; - if (modifiers & Qt::ShiftModifier) - native |= MOD_SHIFT; - if (modifiers & Qt::ControlModifier) - native |= MOD_CONTROL; - if (modifiers & Qt::AltModifier) - native |= MOD_ALT; - if (modifiers & Qt::MetaModifier) - native |= MOD_WIN; - // TODO: resolve these? - //if (modifiers & Qt::KeypadModifier) - //if (modifiers & Qt::GroupSwitchModifier) - return native; -} - -quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) -{ - switch (key) - { - case Qt::Key_Escape: - return VK_ESCAPE; - case Qt::Key_Tab: - case Qt::Key_Backtab: - return VK_TAB; - case Qt::Key_Backspace: - return VK_BACK; - case Qt::Key_Return: - case Qt::Key_Enter: - return VK_RETURN; - case Qt::Key_Insert: - return VK_INSERT; - case Qt::Key_Delete: - return VK_DELETE; - case Qt::Key_Pause: - return VK_PAUSE; - case Qt::Key_Print: - return VK_PRINT; - case Qt::Key_Clear: - return VK_CLEAR; - case Qt::Key_Home: - return VK_HOME; - case Qt::Key_End: - return VK_END; - case Qt::Key_Left: - return VK_LEFT; - case Qt::Key_Up: - return VK_UP; - case Qt::Key_Right: - return VK_RIGHT; - case Qt::Key_Down: - return VK_DOWN; - case Qt::Key_PageUp: - return VK_PRIOR; - case Qt::Key_PageDown: - return VK_NEXT; - case Qt::Key_F1: - return VK_F1; - case Qt::Key_F2: - return VK_F2; - case Qt::Key_F3: - return VK_F3; - case Qt::Key_F4: - return VK_F4; - case Qt::Key_F5: - return VK_F5; - case Qt::Key_F6: - return VK_F6; - case Qt::Key_F7: - return VK_F7; - case Qt::Key_F8: - return VK_F8; - case Qt::Key_F9: - return VK_F9; - case Qt::Key_F10: - return VK_F10; - case Qt::Key_F11: - return VK_F11; - case Qt::Key_F12: - return VK_F12; - case Qt::Key_F13: - return VK_F13; - case Qt::Key_F14: - return VK_F14; - case Qt::Key_F15: - return VK_F15; - case Qt::Key_F16: - return VK_F16; - case Qt::Key_F17: - return VK_F17; - case Qt::Key_F18: - return VK_F18; - case Qt::Key_F19: - return VK_F19; - case Qt::Key_F20: - return VK_F20; - case Qt::Key_F21: - return VK_F21; - case Qt::Key_F22: - return VK_F22; - case Qt::Key_F23: - return VK_F23; - case Qt::Key_F24: - return VK_F24; - case Qt::Key_Space: - return VK_SPACE; - case Qt::Key_Asterisk: - return VK_MULTIPLY; - case Qt::Key_Plus: - return VK_ADD; - case Qt::Key_Comma: - return VK_SEPARATOR; - case Qt::Key_Minus: - return VK_SUBTRACT; - case Qt::Key_Slash: - return VK_DIVIDE; - - case Qt::Key_MediaNext: - return VK_MEDIA_NEXT_TRACK; - case Qt::Key_MediaPrevious: - return VK_MEDIA_PREV_TRACK; - case Qt::Key_MediaStop: - return VK_MEDIA_STOP; - case Qt::Key_MediaPlay: - return VK_MEDIA_PLAY_PAUSE; - case Qt::Key_VolumeDown: - return VK_VOLUME_DOWN; - case Qt::Key_VolumeUp: - return VK_VOLUME_UP; - case Qt::Key_VolumeMute: - return VK_VOLUME_MUTE; - - // numbers - case Qt::Key_0: - case Qt::Key_1: - case Qt::Key_2: - case Qt::Key_3: - case Qt::Key_4: - case Qt::Key_5: - case Qt::Key_6: - case Qt::Key_7: - case Qt::Key_8: - case Qt::Key_9: - return key; - - // letters - case Qt::Key_A: - case Qt::Key_B: - case Qt::Key_C: - case Qt::Key_D: - case Qt::Key_E: - case Qt::Key_F: - case Qt::Key_G: - case Qt::Key_H: - case Qt::Key_I: - case Qt::Key_J: - case Qt::Key_K: - case Qt::Key_L: - case Qt::Key_M: - case Qt::Key_N: - case Qt::Key_O: - case Qt::Key_P: - case Qt::Key_Q: - case Qt::Key_R: - case Qt::Key_S: - case Qt::Key_T: - case Qt::Key_U: - case Qt::Key_V: - case Qt::Key_W: - case Qt::Key_X: - case Qt::Key_Y: - case Qt::Key_Z: - return key; - - default: - return 0; - } -} - -bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) -{ - return RegisterHotKey(0, nativeMods ^ nativeKey, nativeMods, nativeKey); -} - -bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) -{ - return UnregisterHotKey(0, nativeMods ^ nativeKey); -} +#include "qxtglobalshortcut_p.h" +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#include + + +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) +bool QxtGlobalShortcutPrivate::eventFilter(void* message) +{ +#else +bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, + void * message, long * result) +{ + Q_UNUSED(eventType); + Q_UNUSED(result); +#endif + MSG* msg = static_cast(message); + if (msg->message == WM_HOTKEY) + { + const quint32 keycode = HIWORD(msg->lParam); + const quint32 modifiers = LOWORD(msg->lParam); + activateShortcut(keycode, modifiers); + } + return false; +} + + +quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) +{ + // MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN + quint32 native = 0; + if (modifiers & Qt::ShiftModifier) + native |= MOD_SHIFT; + if (modifiers & Qt::ControlModifier) + native |= MOD_CONTROL; + if (modifiers & Qt::AltModifier) + native |= MOD_ALT; + if (modifiers & Qt::MetaModifier) + native |= MOD_WIN; + // TODO: resolve these? + //if (modifiers & Qt::KeypadModifier) + //if (modifiers & Qt::GroupSwitchModifier) + return native; +} + +quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) +{ + switch (key) + { + case Qt::Key_Escape: + return VK_ESCAPE; + case Qt::Key_Tab: + case Qt::Key_Backtab: + return VK_TAB; + case Qt::Key_Backspace: + return VK_BACK; + case Qt::Key_Return: + case Qt::Key_Enter: + return VK_RETURN; + case Qt::Key_Insert: + return VK_INSERT; + case Qt::Key_Delete: + return VK_DELETE; + case Qt::Key_Pause: + return VK_PAUSE; + case Qt::Key_Print: + return VK_PRINT; + case Qt::Key_Clear: + return VK_CLEAR; + case Qt::Key_Home: + return VK_HOME; + case Qt::Key_End: + return VK_END; + case Qt::Key_Left: + return VK_LEFT; + case Qt::Key_Up: + return VK_UP; + case Qt::Key_Right: + return VK_RIGHT; + case Qt::Key_Down: + return VK_DOWN; + case Qt::Key_PageUp: + return VK_PRIOR; + case Qt::Key_PageDown: + return VK_NEXT; + case Qt::Key_F1: + return VK_F1; + case Qt::Key_F2: + return VK_F2; + case Qt::Key_F3: + return VK_F3; + case Qt::Key_F4: + return VK_F4; + case Qt::Key_F5: + return VK_F5; + case Qt::Key_F6: + return VK_F6; + case Qt::Key_F7: + return VK_F7; + case Qt::Key_F8: + return VK_F8; + case Qt::Key_F9: + return VK_F9; + case Qt::Key_F10: + return VK_F10; + case Qt::Key_F11: + return VK_F11; + case Qt::Key_F12: + return VK_F12; + case Qt::Key_F13: + return VK_F13; + case Qt::Key_F14: + return VK_F14; + case Qt::Key_F15: + return VK_F15; + case Qt::Key_F16: + return VK_F16; + case Qt::Key_F17: + return VK_F17; + case Qt::Key_F18: + return VK_F18; + case Qt::Key_F19: + return VK_F19; + case Qt::Key_F20: + return VK_F20; + case Qt::Key_F21: + return VK_F21; + case Qt::Key_F22: + return VK_F22; + case Qt::Key_F23: + return VK_F23; + case Qt::Key_F24: + return VK_F24; + case Qt::Key_Space: + return VK_SPACE; + case Qt::Key_Asterisk: + return VK_MULTIPLY; + case Qt::Key_Plus: + return VK_ADD; + case Qt::Key_Comma: + return VK_SEPARATOR; + case Qt::Key_Minus: + return VK_SUBTRACT; + case Qt::Key_Slash: + return VK_DIVIDE; + case Qt::Key_MediaNext: + return VK_MEDIA_NEXT_TRACK; + case Qt::Key_MediaPrevious: + return VK_MEDIA_PREV_TRACK; + case Qt::Key_MediaPlay: + return VK_MEDIA_PLAY_PAUSE; + case Qt::Key_MediaStop: + return VK_MEDIA_STOP; + // couldn't find those in VK_* + //case Qt::Key_MediaLast: + //case Qt::Key_MediaRecord: + case Qt::Key_VolumeDown: + return VK_VOLUME_DOWN; + case Qt::Key_VolumeUp: + return VK_VOLUME_UP; + case Qt::Key_VolumeMute: + return VK_VOLUME_MUTE; + + // numbers + case Qt::Key_0: + case Qt::Key_1: + case Qt::Key_2: + case Qt::Key_3: + case Qt::Key_4: + case Qt::Key_5: + case Qt::Key_6: + case Qt::Key_7: + case Qt::Key_8: + case Qt::Key_9: + return key; + + // letters + case Qt::Key_A: + case Qt::Key_B: + case Qt::Key_C: + case Qt::Key_D: + case Qt::Key_E: + case Qt::Key_F: + case Qt::Key_G: + case Qt::Key_H: + case Qt::Key_I: + case Qt::Key_J: + case Qt::Key_K: + case Qt::Key_L: + case Qt::Key_M: + case Qt::Key_N: + case Qt::Key_O: + case Qt::Key_P: + case Qt::Key_Q: + case Qt::Key_R: + case Qt::Key_S: + case Qt::Key_T: + case Qt::Key_U: + case Qt::Key_V: + case Qt::Key_W: + case Qt::Key_X: + case Qt::Key_Y: + case Qt::Key_Z: + return key; + + default: + return 0; + } +} + +bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) +{ + return RegisterHotKey(0, nativeMods ^ nativeKey, nativeMods, nativeKey); +} + +bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) +{ + return UnregisterHotKey(0, nativeMods ^ nativeKey); +} diff --git a/3rdparty/qxt/qxtglobalshortcut_x11.cpp b/3rdparty/qxt/qxtglobalshortcut_x11.cpp index c22894dc1..7ecbdf24a 100644 --- a/3rdparty/qxt/qxtglobalshortcut_x11.cpp +++ b/3rdparty/qxt/qxtglobalshortcut_x11.cpp @@ -1,135 +1,238 @@ -/**************************************************************************** - ** - ** Copyright (C) Qxt Foundation. Some rights reserved. - ** - ** This file is part of the QxtGui module of the Qxt library. - ** - ** This library is free software; you can redistribute it and/or modify it - ** under the terms of the Common Public License, version 1.0, as published - ** by IBM, and/or under the terms of the GNU Lesser General Public License, - ** version 2.1, as published by the Free Software Foundation. - ** - ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY - ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY - ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR - ** FITNESS FOR A PARTICULAR PURPOSE. - ** - ** You should have received a copy of the CPL and the LGPL along with this - ** file. See the LICENSE file and the cpl1.0.txt/lgpl-2.1.txt files - ** included with the source distribution for more information. - ** If you did not receive a copy of the licenses, contact the Qxt Foundation. - ** - ** - ** - ****************************************************************************/ -#include "qxtglobalshortcut_p.h" -#include -#include - -#include "keymapper_x11.h" - -static int (*original_x_errhandler)(Display* display, XErrorEvent* event); - -static int qxt_x_errhandler(Display* display, XErrorEvent *event) -{ - Q_UNUSED(display); - switch (event->error_code) - { - case BadAccess: - case BadValue: - case BadWindow: - if (event->request_code == 33 /* X_GrabKey */ || - event->request_code == 34 /* X_UngrabKey */) - { - QxtGlobalShortcutPrivate::error = true; - //TODO: - //char errstr[256]; - //XGetErrorText(dpy, err->error_code, errstr, 256); - } - default: - return 0; - } -} - -bool QxtGlobalShortcutPrivate::eventFilter(void* message) -{ - XEvent* event = static_cast(message); - if (event->type == KeyPress) - { - XKeyEvent* key = (XKeyEvent*) event; - activateShortcut(key->keycode, - // Mod1Mask == Alt, Mod4Mask == Meta - key->state & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask)); - } - return false; -} - -quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) -{ - // ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask - quint32 native = 0; - if (modifiers & Qt::ShiftModifier) - native |= ShiftMask; - if (modifiers & Qt::ControlModifier) - native |= ControlMask; - if (modifiers & Qt::AltModifier) - native |= Mod1Mask; - if (modifiers & Qt::MetaModifier) - native |= Mod4Mask; - // TODO: resolve these? - //if (modifiers & Qt::KeypadModifier) - //if (modifiers & Qt::GroupSwitchModifier) - return native; -} - -quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) -{ - // (davidsansome) Try the table from QKeyMapper first - this seems to be - // the only way to get Keysyms for the media keys. - unsigned int keysym = 0; - int i = 0; - while (KeyTbl[i]) { - if (KeyTbl[i+1] == static_cast(key)) { - keysym = KeyTbl[i]; - break; - } - i += 2; - } - - // If that didn't work then fall back on XStringToKeysym - if (!keysym) { - keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data()); - } - - Display* display = QX11Info::display(); - return XKeysymToKeycode(display, keysym); -} - -bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) -{ - Display* display = QX11Info::display(); - Window window = QX11Info::appRootWindow(); - Bool owner = True; - int pointer = GrabModeAsync; - int keyboard = GrabModeAsync; - error = false; - original_x_errhandler = XSetErrorHandler(qxt_x_errhandler); - XGrabKey(display, nativeKey, nativeMods, window, owner, pointer, keyboard); - XGrabKey(display, nativeKey, nativeMods | Mod2Mask, window, owner, pointer, keyboard); // allow numlock - XSync(display, False); - XSetErrorHandler(original_x_errhandler); - return !error; -} - -bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) -{ - Display* display = QX11Info::display(); - Window window = QX11Info::appRootWindow(); - error = false; - original_x_errhandler = XSetErrorHandler(qxt_x_errhandler); - XUngrabKey(display, nativeKey, nativeMods, window); - XUngrabKey(display, nativeKey, nativeMods | Mod2Mask, window); // allow numlock - XSync(display, False); - XSetErrorHandler(original_x_errhandler); - return !error; -} +#include "qxtglobalshortcut_p.h" +/**************************************************************************** +** Copyright (c) 2006 - 2011, the LibQxt project. +** See the Qxt AUTHORS file for a list of authors and copyright holders. +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** * Neither the name of the LibQxt project nor the +** names of its contributors may be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** +*****************************************************************************/ + +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) +# include +#else +# include +# include +# include +#endif +#include +#include + +namespace { + +const QVector maskModifiers = QVector() + << 0 << Mod2Mask << LockMask << (Mod2Mask | LockMask); + +typedef int (*X11ErrorHandler)(Display *display, XErrorEvent *event); + +class QxtX11ErrorHandler { +public: + static bool error; + + static int qxtX11ErrorHandler(Display *display, XErrorEvent *event) + { + Q_UNUSED(display); + switch (event->error_code) + { + case BadAccess: + case BadValue: + case BadWindow: + if (event->request_code == 33 /* X_GrabKey */ || + event->request_code == 34 /* X_UngrabKey */) + { + error = true; + //TODO: + //char errstr[256]; + //XGetErrorText(dpy, err->error_code, errstr, 256); + } + } + return 0; + } + + QxtX11ErrorHandler() + { + error = false; + m_previousErrorHandler = XSetErrorHandler(qxtX11ErrorHandler); + } + + ~QxtX11ErrorHandler() + { + XSetErrorHandler(m_previousErrorHandler); + } + +private: + X11ErrorHandler m_previousErrorHandler; +}; + +bool QxtX11ErrorHandler::error = false; + +class QxtX11Data { +public: + QxtX11Data() + { +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) + m_display = QX11Info::display(); +#else + QPlatformNativeInterface *native = qApp->platformNativeInterface(); + void *display = native->nativeResourceForScreen(QByteArray("display"), + QGuiApplication::primaryScreen()); + m_display = reinterpret_cast(display); +#endif + } + + bool isValid() + { + return m_display != 0; + } + + Display *display() + { + Q_ASSERT(isValid()); + return m_display; + } + + Window rootWindow() + { + return DefaultRootWindow(display()); + } + + bool grabKey(quint32 keycode, quint32 modifiers, Window window) + { + QxtX11ErrorHandler errorHandler; + + for (int i = 0; !errorHandler.error && i < maskModifiers.size(); ++i) { + XGrabKey(display(), keycode, modifiers | maskModifiers[i], window, True, + GrabModeAsync, GrabModeAsync); + } + + if (errorHandler.error) { + ungrabKey(keycode, modifiers, window); + return false; + } + + return true; + } + + bool ungrabKey(quint32 keycode, quint32 modifiers, Window window) + { + QxtX11ErrorHandler errorHandler; + + foreach (quint32 maskMods, maskModifiers) { + XUngrabKey(display(), keycode, modifiers | maskMods, window); + } + + return !errorHandler.error; + } + +private: + Display *m_display; +}; + +} // namespace + +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) +bool QxtGlobalShortcutPrivate::eventFilter(void *message) +{ + XEvent *event = static_cast(message); + if (event->type == KeyPress) + { + XKeyEvent *key = reinterpret_cast(event); + unsigned int keycode = key->keycode; + unsigned int keystate = key->state; +#else +bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, + void *message, long *result) +{ + Q_UNUSED(result); + + xcb_key_press_event_t *kev = 0; + if (eventType == "xcb_generic_event_t") { + xcb_generic_event_t *ev = static_cast(message); + if ((ev->response_type & 127) == XCB_KEY_PRESS) + kev = static_cast(message); + } + + if (kev != 0) { + unsigned int keycode = kev->detail; + unsigned int keystate = 0; + if(kev->state & XCB_MOD_MASK_1) + keystate |= Mod1Mask; + if(kev->state & XCB_MOD_MASK_CONTROL) + keystate |= ControlMask; + if(kev->state & XCB_MOD_MASK_4) + keystate |= Mod4Mask; + if(kev->state & XCB_MOD_MASK_SHIFT) + keystate |= ShiftMask; +#endif + activateShortcut(keycode, + // Mod1Mask == Alt, Mod4Mask == Meta + keystate & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask)); + } + return false; +} + +quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) +{ + // ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask + quint32 native = 0; + if (modifiers & Qt::ShiftModifier) + native |= ShiftMask; + if (modifiers & Qt::ControlModifier) + native |= ControlMask; + if (modifiers & Qt::AltModifier) + native |= Mod1Mask; + if (modifiers & Qt::MetaModifier) + native |= Mod4Mask; + + // TODO: resolve these? + //if (modifiers & Qt::MetaModifier) + //if (modifiers & Qt::KeypadModifier) + //if (modifiers & Qt::GroupSwitchModifier) + return native; +} + +quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) +{ + QxtX11Data x11; + if (!x11.isValid()) + return 0; + + KeySym keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data()); + if (keysym == NoSymbol) + keysym = static_cast(key); + + return XKeysymToKeycode(x11.display(), keysym); +} + +bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) +{ + QxtX11Data x11; + return x11.isValid() && x11.grabKey(nativeKey, nativeMods, x11.rootWindow()); +} + +bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) +{ + QxtX11Data x11; + return x11.isValid() && x11.ungrabKey(nativeKey, nativeMods, x11.rootWindow()); +} From 6830cb92f79a8c609342263b0f3edec7407f177d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sat, 11 Apr 2015 22:48:34 +0200 Subject: [PATCH 005/104] Update cmakelist of 3rdparties to qt5 --- 3rdparty/fancytabwidget/CMakeLists.txt | 2 +- 3rdparty/qocoa/CMakeLists.txt | 4 ++-- 3rdparty/qtiocompressor/CMakeLists.txt | 4 +++- 3rdparty/vreen/vreen/CMakeLists.txt | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/3rdparty/fancytabwidget/CMakeLists.txt b/3rdparty/fancytabwidget/CMakeLists.txt index bdc7b8e28..122f38a57 100644 --- a/3rdparty/fancytabwidget/CMakeLists.txt +++ b/3rdparty/fancytabwidget/CMakeLists.txt @@ -9,7 +9,7 @@ set(HEADERS fancytabwidget.h ) -qt4_wrap_cpp(MOC ${HEADERS}) +qt5_wrap_cpp(MOC ${HEADERS}) include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/3rdparty/qocoa/CMakeLists.txt b/3rdparty/qocoa/CMakeLists.txt index 92ac7ce29..b3b7fa4aa 100644 --- a/3rdparty/qocoa/CMakeLists.txt +++ b/3rdparty/qocoa/CMakeLists.txt @@ -6,7 +6,7 @@ set(HEADERS qprogressindicatorspinning.h ) -qt4_wrap_cpp(MOC_SOURCES ${HEADERS}) +qt5_wrap_cpp(MOC_SOURCES ${HEADERS}) if(APPLE) list(APPEND SOURCES @@ -23,7 +23,7 @@ else() set(RESOURCES qprogressindicatorspinning_nonmac.qrc ) - qt4_add_resources(RESOURCES_SOURCES ${RESOURCES}) + qt5_add_resources(RESOURCES_SOURCES ${RESOURCES}) endif() add_library(Qocoa STATIC diff --git a/3rdparty/qtiocompressor/CMakeLists.txt b/3rdparty/qtiocompressor/CMakeLists.txt index f339daba9..03578c554 100644 --- a/3rdparty/qtiocompressor/CMakeLists.txt +++ b/3rdparty/qtiocompressor/CMakeLists.txt @@ -8,9 +8,11 @@ set(IOCOMPRESSOR-MOC-HEADERS qtiocompressor.h ) -QT4_WRAP_CPP(IOCOMPRESSOR-SOURCES-MOC ${IOCOMPRESSOR-MOC-HEADERS}) +QT5_WRAP_CPP(IOCOMPRESSOR-SOURCES-MOC ${IOCOMPRESSOR-MOC-HEADERS}) ADD_LIBRARY(qtiocompressor STATIC ${IOCOMPRESSOR-SOURCES} ${IOCOMPRESSOR-SOURCES-MOC} ) + +QT5_USE_MODULES(qtiocompressor Core) diff --git a/3rdparty/vreen/vreen/CMakeLists.txt b/3rdparty/vreen/vreen/CMakeLists.txt index 80ddde319..44241581e 100644 --- a/3rdparty/vreen/vreen/CMakeLists.txt +++ b/3rdparty/vreen/vreen/CMakeLists.txt @@ -16,7 +16,7 @@ option(VREEN_WITH_EXAMPLES "Enable vreen tests" ON) option(VREEN_WITH_TESTS "Enable vreen examples" ON) option(VREEN_INSTALL_HEADERS "Install devel headers for vreen" ON) option(VREEN_DEVELOPER_BUILD "Install devel headers for vreen" OFF) -option(USE_QT5 "Build with Qt 5" OFF) +option(USE_QT5 "Build with Qt 5" ON) #TODO check if vars is defined set(RLIBDIR bin) From f5414d5535b4a943f8ec9343cf350538abc64ca6 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sat, 11 Apr 2015 22:49:34 +0200 Subject: [PATCH 006/104] Update main cmakelists to qt5 --- CMakeLists.txt | 104 +++++++++++++++++-------------------- cmake/OptionalSource.cmake | 2 +- cmake/Translations.cmake | 2 +- 3 files changed, 51 insertions(+), 57 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d813928c..7fccae8aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,15 +33,22 @@ if (UNIX AND NOT APPLE) set(LINUX 1) endif (UNIX AND NOT APPLE) -find_package(Qt4 4.5.0 REQUIRED QtCore QtGui QtOpenGL QtSql QtNetwork QtXml) +set(QT_MIN_VERSION 5.0.0) + +find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core OpenGL Sql Network Xml Widgets Concurrent) +find_package(X11) +if(X11_FOUND) + find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS X11Extras) +endif() + if(NOT APPLE) - find_package(Qt4 COMPONENTS QtWebKit) + find_package(Qt5 COMPONENTS WebKitWidgets) endif(NOT APPLE) # Find Qt's lconvert binary. Try qt's binary dir first, fall back to looking in PATH -find_program(QT_LCONVERT_EXECUTABLE NAMES lconvert lconvert-qt4 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH) -find_program(QT_LCONVERT_EXECUTABLE NAMES lconvert lconvert-qt4) +find_program(QT_LCONVERT_EXECUTABLE NAMES lconvert lconvert-qt5 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH) +find_program(QT_LCONVERT_EXECUTABLE NAMES lconvert lconvert-qt5) if(APPLE) if(NOT QT_MAC_USE_COCOA) @@ -68,11 +75,10 @@ pkg_check_modules(GSTREAMER_BASE REQUIRED gstreamer-base-1.0) pkg_check_modules(GSTREAMER_TAG REQUIRED gstreamer-tag-1.0) pkg_check_modules(LIBGPOD libgpod-1.0>=0.7.92) pkg_check_modules(LIBMTP libmtp>=1.0) -pkg_check_modules(LIBMYGPO_QT libmygpo-qt>=1.0.7) +pkg_check_modules(LIBMYGPO_QT5 libmygpo-qt5>=1.0.7) pkg_check_modules(LIBPULSE libpulse) pkg_check_modules(LIBXML libxml-2.0) -pkg_check_modules(QCA qca2) -pkg_check_modules(QJSON REQUIRED QJson) +pkg_check_modules(QCA_QT5 qca2-qt5) pkg_check_modules(SPOTIFY libspotify>=12.1.45) pkg_check_modules(TAGLIB REQUIRED taglib>=1.6) @@ -138,7 +144,6 @@ endif(${CMAKE_BUILD_TYPE} MATCHES "Release") # Set up definitions and paths add_definitions(${QT_DEFINITIONS}) link_directories(${TAGLIB_LIBRARY_DIRS}) -link_directories(${QJSON_LIBRARY_DIRS}) link_directories(${GSTREAMER_LIBRARY_DIRS}) # Don't try to use webkit if their include directories couldn't be found. @@ -148,7 +153,6 @@ endif (NOT QT_QTWEBKIT_INCLUDE_DIR) include_directories(${Boost_INCLUDE_DIRS}) include_directories(${TAGLIB_INCLUDE_DIRS}) -include_directories(${QJSON_INCLUDE_DIRS}) include_directories(${GSTREAMER_INCLUDE_DIRS}) include_directories(${GSTREAMER_APP_INCLUDE_DIRS}) include_directories(${GSTREAMER_AUDIO_INCLUDE_DIRS}) @@ -188,96 +192,96 @@ endif(WIN32) optional_component(BREAKPAD OFF "Crash reporting") -optional_component(GOOGLE_DRIVE ON "Google Drive support" +optional_component(GOOGLE_DRIVE OFF "Google Drive support" DEPENDS "Google sparsehash" SPARSEHASH_INCLUDE_DIRS DEPENDS "Taglib 1.8" "TAGLIB_VERSION VERSION_GREATER 1.7.999" ) -optional_component(DROPBOX ON "Dropbox support" +optional_component(DROPBOX OFF "Dropbox support" DEPENDS "Google sparsehash" SPARSEHASH_INCLUDE_DIRS DEPENDS "Taglib 1.8" "TAGLIB_VERSION VERSION_GREATER 1.7.999" ) -optional_component(SKYDRIVE ON "Skydrive support" +optional_component(SKYDRIVE OFF "Skydrive support" DEPENDS "Google sparsehash" SPARSEHASH_INCLUDE_DIRS DEPENDS "Taglib 1.8" "TAGLIB_VERSION VERSION_GREATER 1.7.999" ) -optional_component(BOX ON "Box support" +optional_component(BOX OFF "Box support" DEPENDS "Google sparsehash" SPARSEHASH_INCLUDE_DIRS DEPENDS "Taglib 1.8" "TAGLIB_VERSION VERSION_GREATER 1.7.999" ) -optional_component(VK ON "Vk.com support") +optional_component(VK OFF "Vk.com support") -optional_component(SEAFILE ON "Seafile support" +optional_component(SEAFILE OFF "Seafile support" DEPENDS "Google sparsehash" SPARSEHASH_INCLUDE_DIRS DEPENDS "Taglib 1.8" "TAGLIB_VERSION VERSION_GREATER 1.7.999" ) -optional_component(AUDIOCD ON "Devices: Audio CD support" +optional_component(AUDIOCD OFF "Devices: Audio CD support" DEPENDS "libcdio" CDIO_FOUND ) -optional_component(LIBGPOD ON "Devices: iPod classic support" +optional_component(LIBGPOD OFF "Devices: iPod classic support" DEPENDS "libgpod" LIBGPOD_FOUND ) -optional_component(GIO ON "Devices: GIO device backend" +optional_component(GIO OFF "Devices: GIO device backend" DEPENDS "libgio" GIO_FOUND DEPENDS "Linux or Windows" "NOT APPLE" ) -optional_component(LIBMTP ON "Devices: MTP support" +optional_component(LIBMTP OFF "Devices: MTP support" DEPENDS "libmtp" LIBMTP_FOUND ) -optional_component(LIBLASTFM ON "Last.fm support" +optional_component(LIBLASTFM OFF "Last.fm support" DEPENDS "liblastfm" LASTFM_LIBRARIES LASTFM_INCLUDE_DIRS ) -optional_component(DBUS ON "D-Bus support" +optional_component(DBUS OFF "D-Bus support" DEPENDS "Linux" LINUX ) -optional_component(WIIMOTEDEV ON "Wiimote support" +optional_component(WIIMOTEDEV OFF "Wiimote support" DEPENDS "D-Bus support" HAVE_DBUS ) -optional_component(DEVICEKIT ON "Devices: DeviceKit backend" +optional_component(DEVICEKIT OFF "Devices: DeviceKit backend" DEPENDS "D-Bus support" HAVE_DBUS ) -optional_component(SPOTIFY_BLOB ON "Spotify support: non-GPL binary helper" +optional_component(SPOTIFY_BLOB OFF "Spotify support: non-GPL binary helper" DEPENDS "protobuf" PROTOBUF_FOUND PROTOBUF_PROTOC_EXECUTABLE DEPENDS "libspotify" SPOTIFY_FOUND ) -optional_component(MOODBAR ON "Moodbar support" +optional_component(MOODBAR OFF "Moodbar support" DEPENDS "fftw3" FFTW3_FOUND ) -optional_component(SPARKLE ON "Sparkle integration" +optional_component(SPARKLE OFF "Sparkle integration" DEPENDS "Mac OS X" APPLE DEPENDS "Sparkle" SPARKLE ) -optional_component(LIBPULSE ON "Pulse audio integration" +optional_component(LIBPULSE OFF "Pulse audio integration" DEPENDS "libpulse" LIBPULSE_FOUND ) -optional_component(VISUALISATIONS ON "Visualisations") +optional_component(VISUALISATIONS OFF "Visualisations") -if(NOT HAVE_SPOTIFY_BLOB AND NOT QCA_FOUND) - message(FATAL_ERROR "Either QCA must be available or the non-GPL Spotify " +if(NOT HAVE_SPOTIFY_BLOB AND NOT QCA_QT5_FOUND) + message(FATAL_ERROR "Either QCA-qt5 must be available or the non-GPL Spotify " "code must be compiled in") -elseif(QCA_FOUND) +elseif(QCA_QT5_FOUND) set(HAVE_SPOTIFY_DOWNLOADER ON) endif() # Find DBus if it's enabled if (HAVE_DBUS) - find_package(Qt4 REQUIRED QtDbus) + find_package(Qt5 COMPONENTS DBus) endif () if (HAVE_VK) @@ -287,7 +291,7 @@ if (HAVE_VK) endif(HAVE_VK) # We can include the Qt definitions now -include(${QT_USE_FILE}) +set(QT_LIBRARIES Qt5::Core Qt5::OpenGL Qt5::Sql Qt5::Network Qt5::Xml Qt5::Widgets Qt5::Concurrent Qt5::X11Extras) # Remove GLU and GL from the link line - they're not really required # and don't exist on my mingw toolchain @@ -317,18 +321,9 @@ endif(ENABLE_VISUALISATIONS) add_subdirectory(3rdparty/qsqlite) include_directories("3rdparty/qsqlite") -# When/if upstream accepts our patches then these options can be used to link -# to system installed qtsingleapplication instead. -option(USE_SYSTEM_QTSINGLEAPPLICATION "Don't set this option unless your system QtSingleApplication library has been compiled with the Clementine patches in 3rdparty" OFF) -if(USE_SYSTEM_QTSINGLEAPPLICATION) - find_path(QTSINGLEAPPLICATION_INCLUDE_DIRS qtsingleapplication.h PATH_SUFFIXES QtSolutions) - find_library(QTSINGLEAPPLICATION_LIBRARIES QtSolutions_SingleApplication-2.6) - find_library(QTSINGLECOREAPPLICATION_LIBRARIES QtSolutions_SingleCoreApplication-2.6) -else(USE_SYSTEM_QTSINGLEAPPLICATION) - add_subdirectory(3rdparty/qtsingleapplication) - set(QTSINGLEAPPLICATION_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/qtsingleapplication) - set(QTSINGLEAPPLICATION_LIBRARIES qtsingleapplication) -endif(USE_SYSTEM_QTSINGLEAPPLICATION) +add_subdirectory(3rdparty/singleapplication) +set(SINGLEAPPLICATION_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/singleapplication) +set(SINGLEAPPLICATION_LIBRARIES singleapplication) # QtIoCompressor isn't patched, so we can use a system version if it's # available @@ -358,8 +353,8 @@ else (USE_SYSTEM_QXT) endif (NOT APPLE) endif (USE_SYSTEM_QXT) -find_path(ECHONEST_INCLUDE_DIRS echonest/echonest_export.h) -find_library(ECHONEST_LIBRARIES echonest) +find_path(ECHONEST5_INCLUDE_DIRS echonest5/echonest_export.h) +find_library(ECHONEST5_LIBRARIES echonest5) # Use system gmock if it's available # We need to look for both gmock and gtest @@ -388,15 +383,14 @@ else() set(SHA2_LIBRARIES sha2) endif() -# Use the system libmygpo-qt if a recent enough version was found -if(LIBMYGPO_QT_FOUND) - set(MYGPOQT_LIBRARIES ${LIBMYGPO_QT_LIBRARIES}) - set(MYGPOQT_INCLUDE_DIRS ${LIBMYGPO_QT_INCLUDE_DIRS}) +# Use the system libmygpo-qt5 if a recent enough version was found +if(LIBMYGPO_QT5_FOUND) + set(MYGPOQT5_LIBRARIES ${LIBMYGPO_QT5_LIBRARIES}) + set(MYGPOQT5_INCLUDE_DIRS ${LIBMYGPO_QT5_INCLUDE_DIRS}) else() - add_definitions(-DMYGPO_EXPORT=) - add_subdirectory(3rdparty/libmygpo-qt) - set(MYGPOQT_LIBRARIES mygpo-qt) - set(MYGPOQT_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/3rdparty/libmygpo-qt/) + add_subdirectory(3rdparty/libmygpo-qt5) + set(MYGPOQT5_LIBRARIES mygpo-qt5) + set(MYGPOQT5_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/libmygpo-qt5/src) endif() # Qocoa diff --git a/cmake/OptionalSource.cmake b/cmake/OptionalSource.cmake index 2b816984f..d543e21f9 100644 --- a/cmake/OptionalSource.cmake +++ b/cmake/OptionalSource.cmake @@ -15,7 +15,7 @@ macro(optional_source TOGGLE) list(APPEND OTHER_SOURCES ${OPTIONAL_SOURCE_HEADERS}) set(_uic_sources) - qt4_wrap_ui(_uic_sources ${OPTIONAL_SOURCE_UI}) + qt5_wrap_ui(_uic_sources ${OPTIONAL_SOURCE_UI}) list(APPEND OTHER_SOURCES ${_uic_sources}) list(APPEND OTHER_UIC_SOURCES ${_uic_sources}) endif(${TOGGLE}) diff --git a/cmake/Translations.cmake b/cmake/Translations.cmake index 462145e2c..8ec962992 100644 --- a/cmake/Translations.cmake +++ b/cmake/Translations.cmake @@ -68,5 +68,5 @@ macro(add_po outfiles po_prefix) file(APPEND ${_qrc} "${po_prefix}${_lang}.qm") endforeach(_lang) file(APPEND ${_qrc} "") - qt4_add_resources(${outfiles} ${_qrc}) + qt5_add_resources(${outfiles} ${_qrc}) endmacro(add_po) From 419eb61b546df442844f86fdef04e615737b7b2c Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sat, 11 Apr 2015 22:49:59 +0200 Subject: [PATCH 007/104] Update Clementine spec to qt5 --- dist/clementine.spec.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/clementine.spec.in b/dist/clementine.spec.in index 9717fd265..7ab96e58a 100644 --- a/dist/clementine.spec.in +++ b/dist/clementine.spec.in @@ -10,7 +10,7 @@ Source0: %{name}-@CLEMENTINE_VERSION_SPARKLE@.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: desktop-file-utils liblastfm-devel taglib-devel gettext -BuildRequires: qt4-devel boost-devel gcc-c++ glew-devel libgpod-devel +BuildRequires: qt5-devel boost-devel gcc-c++ glew-devel libgpod-devel BuildRequires: cmake gstreamer1-devel gstreamer1-plugins-base-devel BuildRequires: libmtp-devel protobuf-devel protobuf-compiler libcdio-devel BuildRequires: qjson-devel qca2-devel fftw-devel sparsehash-devel From ded70d655549da40d15c22a3bc4860c0a13c8d76 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sat, 11 Apr 2015 22:51:40 +0200 Subject: [PATCH 008/104] Update internals CMakeLits to qt5 --- ext/clementine-spotifyblob/CMakeLists.txt | 2 +- ext/clementine-tagreader/CMakeLists.txt | 4 +- ext/libclementine-common/CMakeLists.txt | 4 +- ext/libclementine-tagreader/CMakeLists.txt | 2 +- gst/moodbar/CMakeLists.txt | 2 + src/CMakeLists.txt | 52 ++++++++++----------- tests/CMakeLists.txt | 4 +- tools/ultimate_lyrics_parser/CMakeLists.txt | 3 +- 8 files changed, 39 insertions(+), 34 deletions(-) diff --git a/ext/clementine-spotifyblob/CMakeLists.txt b/ext/clementine-spotifyblob/CMakeLists.txt index f971216b5..96d558c39 100644 --- a/ext/clementine-spotifyblob/CMakeLists.txt +++ b/ext/clementine-spotifyblob/CMakeLists.txt @@ -28,7 +28,7 @@ if(APPLE) list(APPEND SOURCES spotify_utilities.mm) endif(APPLE) -qt4_wrap_cpp(MOC ${HEADERS}) +qt5_wrap_cpp(MOC ${HEADERS}) if(WIN32 AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT ENABLE_WIN32_CONSOLE) set(win32_build_flag WIN32) diff --git a/ext/clementine-tagreader/CMakeLists.txt b/ext/clementine-tagreader/CMakeLists.txt index b88169697..bee991195 100644 --- a/ext/clementine-tagreader/CMakeLists.txt +++ b/ext/clementine-tagreader/CMakeLists.txt @@ -16,8 +16,8 @@ set(SOURCES tagreaderworker.cpp ) -qt4_wrap_cpp(MOC ${HEADERS}) -qt4_add_resources(QRC data/data.qrc) +qt5_wrap_cpp(MOC ${HEADERS}) +qt5_add_resources(QRC data/data.qrc) add_executable(clementine-tagreader ${SOURCES} diff --git a/ext/libclementine-common/CMakeLists.txt b/ext/libclementine-common/CMakeLists.txt index db5b4c0aa..13e3c0a73 100644 --- a/ext/libclementine-common/CMakeLists.txt +++ b/ext/libclementine-common/CMakeLists.txt @@ -21,7 +21,7 @@ set(HEADERS core/workerpool.h ) -qt4_wrap_cpp(MOC ${HEADERS}) +qt5_wrap_cpp(MOC ${HEADERS}) add_library(libclementine-common STATIC ${SOURCES} @@ -33,3 +33,5 @@ target_link_libraries(libclementine-common ${TAGLIB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) + +QT5_USE_MODULES(libclementine-common Core Network) diff --git a/ext/libclementine-tagreader/CMakeLists.txt b/ext/libclementine-tagreader/CMakeLists.txt index 52372a16b..ba9e3ff31 100644 --- a/ext/libclementine-tagreader/CMakeLists.txt +++ b/ext/libclementine-tagreader/CMakeLists.txt @@ -27,7 +27,7 @@ optional_source(HAVE_GOOGLE_DRIVE cloudstream.h ) -qt4_wrap_cpp(MOC ${HEADERS}) +qt5_wrap_cpp(MOC ${HEADERS}) protobuf_generate_cpp(PROTO_SOURCES PROTO_HEADERS ${MESSAGES}) diff --git a/gst/moodbar/CMakeLists.txt b/gst/moodbar/CMakeLists.txt index 44c136253..2606c1baa 100644 --- a/gst/moodbar/CMakeLists.txt +++ b/gst/moodbar/CMakeLists.txt @@ -27,3 +27,5 @@ target_link_libraries(gstmoodbar ${GSTREAMER_BASE_LIBRARIES} ${FFTW3_FFTW_LIBRARY} ) + +QT5_USE_MODULES(gstmoodbar Core) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 917db286a..b9cc0d438 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,13 +32,13 @@ include_directories(${GLIB_INCLUDE_DIRS}) include_directories(${LIBXML_INCLUDE_DIRS}) include_directories(${GOBJECT_INCLUDE_DIRS}) include_directories(${LIBPROJECTM_INCLUDE_DIRS}) -include_directories(${QTSINGLEAPPLICATION_INCLUDE_DIRS}) +include_directories(${SINGLEAPPLICATION_INCLUDE_DIRS}) include_directories(${QTIOCOMPRESSOR_INCLUDE_DIRS}) include_directories(${QXT_INCLUDE_DIRS}) -include_directories(${ECHONEST_INCLUDE_DIRS}) +include_directories(${ECHONEST5_INCLUDE_DIRS}) include_directories(${SHA2_INCLUDE_DIRS}) include_directories(${CHROMAPRINT_INCLUDE_DIRS}) -include_directories(${MYGPOQT_INCLUDE_DIRS}) +include_directories(${MYGPOQT5_INCLUDE_DIRS}) find_package(OpenGL) include_directories(${OPENGL_INCLUDE_DIR}) @@ -852,7 +852,7 @@ optional_source(HAVE_SPOTIFY_DOWNLOADER HEADERS internet/spotify/spotifyblobdownloader.h INCLUDE_DIRECTORIES - ${QCA_INCLUDE_DIRS} + ${QCA_QT5_INCLUDE_DIRS} ) # Platform specific - OS X @@ -896,39 +896,39 @@ if(HAVE_DBUS) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dbus) # MPRIS DBUS interfaces - qt4_add_dbus_adaptor(SOURCES + qt5_add_dbus_adaptor(SOURCES dbus/org.freedesktop.MediaPlayer.player.xml core/mpris1.h mpris::Mpris1Player core/mpris_player MprisPlayer) - qt4_add_dbus_adaptor(SOURCES + qt5_add_dbus_adaptor(SOURCES dbus/org.freedesktop.MediaPlayer.root.xml core/mpris1.h mpris::Mpris1Root core/mpris_root MprisRoot) - qt4_add_dbus_adaptor(SOURCES + qt5_add_dbus_adaptor(SOURCES dbus/org.freedesktop.MediaPlayer.tracklist.xml core/mpris1.h mpris::Mpris1TrackList core/mpris_tracklist MprisTrackList) # MPRIS 2.0 DBUS interfaces - qt4_add_dbus_adaptor(SOURCES + qt5_add_dbus_adaptor(SOURCES dbus/org.mpris.MediaPlayer2.Player.xml core/mpris2.h mpris::Mpris2 core/mpris2_player Mpris2Player) - qt4_add_dbus_adaptor(SOURCES + qt5_add_dbus_adaptor(SOURCES dbus/org.mpris.MediaPlayer2.xml core/mpris2.h mpris::Mpris2 core/mpris2_root Mpris2Root) - qt4_add_dbus_adaptor(SOURCES + qt5_add_dbus_adaptor(SOURCES dbus/org.mpris.MediaPlayer2.TrackList.xml core/mpris2.h mpris::Mpris2 core/mpris2_tracklist Mpris2TrackList) # MPRIS 2.1 DBUS interfaces - qt4_add_dbus_adaptor(SOURCES + qt5_add_dbus_adaptor(SOURCES dbus/org.mpris.MediaPlayer2.Playlists.xml core/mpris2.h mpris::Mpris2 core/mpris2_playlists Mpris2Playlists) # org.freedesktop.Notifications DBUS interface - qt4_add_dbus_interface(SOURCES + qt5_add_dbus_interface(SOURCES dbus/org.freedesktop.Notifications.xml dbus/notification) # org.gnome.SettingsDaemon interface - qt4_add_dbus_interface(SOURCES + qt5_add_dbus_interface(SOURCES dbus/org.gnome.SettingsDaemon.MediaKeys.xml dbus/gnomesettingsdaemon) @@ -966,17 +966,17 @@ if(HAVE_DBUS) PROPERTIES NO_NAMESPACE dbus/udisks) set_source_files_properties(dbus/org.freedesktop.UDisks.Device.xml PROPERTIES NO_NAMESPACE dbus/udisksdevice) - qt4_add_dbus_interface(SOURCES + qt5_add_dbus_interface(SOURCES dbus/org.freedesktop.UDisks.xml dbus/udisks) - qt4_add_dbus_interface(SOURCES + qt5_add_dbus_interface(SOURCES dbus/org.freedesktop.UDisks.Device.xml dbus/udisksdevice) endif(HAVE_DEVICEKIT) # Wiimotedev interface classes if(ENABLE_WIIMOTEDEV) - qt4_add_dbus_interface(SOURCES + qt5_add_dbus_interface(SOURCES dbus/org.wiimotedev.deviceEvents.xml dbus/wiimotedev) endif(ENABLE_WIIMOTEDEV) @@ -1197,9 +1197,10 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h) -qt4_wrap_cpp(MOC ${HEADERS}) -qt4_wrap_ui(UIC ${UI}) -qt4_add_resources(QRC ${RESOURCES}) +qt5_wrap_cpp(MOC ${HEADERS}) +qt5_wrap_ui(UIC ${UI}) +qt5_add_resources(QRC ${RESOURCES}) + add_pot(POT ${CMAKE_CURRENT_SOURCE_DIR}/translations/header @@ -1232,18 +1233,17 @@ target_link_libraries(clementine_lib libclementine-remote ${SHA2_LIBRARIES} ${TAGLIB_LIBRARIES} - ${MYGPOQT_LIBRARIES} + ${MYGPOQT5_LIBRARIES} ${CHROMAPRINT_LIBRARIES} - ${ECHONEST_LIBRARIES} + ${ECHONEST5_LIBRARIES} ${GOBJECT_LIBRARIES} ${GLIB_LIBRARIES} - ${QJSON_LIBRARIES} ${QT_LIBRARIES} ${GSTREAMER_BASE_LIBRARIES} ${GSTREAMER_LIBRARIES} ${GSTREAMER_APP_LIBRARIES} ${GSTREAMER_TAG_LIBRARIES} - ${QTSINGLEAPPLICATION_LIBRARIES} + ${SINGLEAPPLICATION_LIBRARIES} ${QTSINGLECOREAPPLICATION_LIBRARIES} ${QTIOCOMPRESSOR_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} @@ -1297,9 +1297,9 @@ endif(HAVE_BREAKPAD) if(HAVE_SPOTIFY_DOWNLOADER) target_link_libraries(clementine_lib - ${QCA_LIBRARIES} + ${QCA_QT5_LIBRARIES} ) - link_directories(${QCA_LIBRARY_DIRS}) + link_directories(${QCA_QT5_LIBRARY_DIRS}) endif(HAVE_SPOTIFY_DOWNLOADER) if(HAVE_LIBPULSE) @@ -1352,7 +1352,7 @@ if (UNIX AND NOT APPLE) endif () endif () -add_dependencies(clementine_lib qtsingleapplication) +add_dependencies(clementine_lib singleapplication) ############################################################################### diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f7d0a42ac..7c46c02d2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -69,7 +69,7 @@ set(TESTUTILS-MOC-HEADERS testobjectdecorators.h ) -qt4_wrap_cpp(TESTUTILS-SOURCES-MOC ${TESTUTILS-MOC-HEADERS}) +qt5_wrap_cpp(TESTUTILS-SOURCES-MOC ${TESTUTILS-MOC-HEADERS}) add_library(test_utils STATIC EXCLUDE_FROM_ALL ${TESTUTILS-SOURCES} ${TESTUTILS-SOURCES-MOC}) target_link_libraries(test_utils ${GMOCK_LIBRARIES} ${QT_LIBRARIES} ${QT_QTTEST_LIBRARY}) @@ -83,7 +83,7 @@ add_custom_target(build_tests ) add_dependencies(test build_tests) -qt4_add_resources(TEST-RESOURCE-SOURCES data/testdata.qrc) +qt5_add_resources(TEST-RESOURCE-SOURCES data/testdata.qrc) add_library(test_gui_main STATIC EXCLUDE_FROM_ALL ${TEST-RESOURCE-SOURCES} main.cpp) target_link_libraries(test_gui_main clementine_lib) diff --git a/tools/ultimate_lyrics_parser/CMakeLists.txt b/tools/ultimate_lyrics_parser/CMakeLists.txt index 7c41e6601..e410d2eb4 100644 --- a/tools/ultimate_lyrics_parser/CMakeLists.txt +++ b/tools/ultimate_lyrics_parser/CMakeLists.txt @@ -4,4 +4,5 @@ set(CMAKE_C_FLAGS "-Wall ${CMAKE_C_FLAGS}") set(CMAKE_CXX_FLAGS "-Woverloaded-virtual -Wall -Wno-sign-compare ${CMAKE_CXX_FLAGS}") add_executable(ultimate_lyrics_parser EXCLUDE_FROM_ALL main.cpp) -target_link_libraries(ultimate_lyrics_parser ${QT_LIBRARIES}) + +target_link_libraries(ultimate_lyrics_parser Qt5::Core) From 8b226c21710864c6f92d124647c65ba8dc4873eb Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sat, 11 Apr 2015 22:52:31 +0200 Subject: [PATCH 009/104] Update non optionnals sources to qt5 --- ext/libclementine-common/core/logging.cpp | 23 ++- src/core/database.cpp | 44 ++-- src/core/mergedproxymodel.cpp | 9 +- src/core/metatypes.cpp | 2 +- src/core/organiseformat.h | 1 + src/core/potranslator.h | 2 +- src/core/qxtglobalshortcutbackend.cpp | 1 - src/core/qxtglobalshortcutbackend.h | 1 + src/covers/amazoncoverprovider.cpp | 9 +- src/covers/musicbrainzcoverprovider.cpp | 7 +- src/dbus/org.mpris.MediaPlayer2.TrackList.xml | 15 +- src/devices/devicedatabasebackend.cpp | 24 +-- src/devices/deviceproperties.cpp | 2 +- src/engines/gstengine.cpp | 2 +- src/engines/gstenginepipeline.cpp | 2 +- src/globalsearch/globalsearchsettingspage.cpp | 4 +- src/internet/core/geolocator.cpp | 16 +- .../core/internetshowsettingspage.cpp | 4 +- src/internet/core/oauthenticator.cpp | 55 ++--- .../digitally/digitallyimportedclient.cpp | 63 +++--- .../grooveshark/groovesharkservice.cpp | 191 +++++++++-------- src/internet/grooveshark/groovesharkservice.h | 16 +- src/internet/icecast/icecastbackend.cpp | 21 +- src/internet/icecast/icecastmodel.cpp | 3 +- .../jamendo/jamendodynamicplaylist.cpp | 32 +-- src/internet/jamendo/jamendoservice.cpp | 6 +- .../magnatune/magnatunedownloaddialog.cpp | 11 +- src/internet/magnatune/magnatuneservice.cpp | 2 +- src/internet/podcasts/itunessearchpage.cpp | 41 ++-- src/internet/podcasts/podcastbackend.cpp | 81 ++++---- src/internet/podcasts/podcastparser.cpp | 12 +- src/internet/podcasts/podcasturlloader.cpp | 6 +- src/internet/soundcloud/soundcloudservice.cpp | 100 ++++----- src/internet/soundcloud/soundcloudservice.h | 9 +- src/internet/subsonic/subsonicservice.cpp | 23 ++- src/internet/subsonic/subsonicurlhandler.cpp | 6 +- src/library/librarybackend.cpp | 192 +++++++++--------- src/library/librarymodel.cpp | 3 +- src/library/libraryquery.cpp | 3 +- src/main.cpp | 49 +---- src/musicbrainz/acoustidclient.cpp | 39 ++-- src/musicbrainz/chromaprinter.cpp | 2 +- src/musicbrainz/musicbrainzclient.cpp | 9 +- src/networkremote/outgoingdatacreator.cpp | 2 +- src/playlist/playlistbackend.cpp | 58 +++--- src/playlist/playlistdelegates.cpp | 4 +- src/playlist/playlistview.cpp | 11 +- src/playlist/playlistview.h | 6 +- src/smartplaylists/searchtermwidget.cpp | 2 +- src/songinfo/songinfobase.cpp | 2 +- src/songinfo/songkickconcerts.cpp | 48 ++--- src/songinfo/songkickconcertwidget.cpp | 9 +- src/songinfo/ultimatelyricsprovider.cpp | 4 +- src/transcoder/transcodedialog.cpp | 2 +- src/transcoder/transcoder.cpp | 6 +- src/ui/albumcoverchoicecontroller.cpp | 1 + src/ui/edittagdialog.cpp | 13 +- src/ui/flowlayout.cpp | 2 +- src/ui/globalshortcutssettingspage.cpp | 2 +- src/ui/mainwindow.cpp | 1 - src/ui/qtsystemtrayicon.cpp | 12 +- src/widgets/errordialog.cpp | 2 +- src/widgets/fancytabwidget.cpp | 8 +- src/widgets/forcescrollperpixel.cpp | 3 +- src/widgets/groupediconview.cpp | 2 +- src/widgets/groupediconview.h | 2 +- src/widgets/nowplayingwidget.cpp | 4 +- src/widgets/stylehelper.cpp | 8 +- src/widgets/stylehelper.h | 4 +- tests/scopedtransaction_test.cpp | 9 +- tools/ultimate_lyrics_parser/main.cpp | 2 - 71 files changed, 714 insertions(+), 658 deletions(-) diff --git a/ext/libclementine-common/core/logging.cpp b/ext/libclementine-common/core/logging.cpp index acbc0e2f0..b0a3564d8 100644 --- a/ext/libclementine-common/core/logging.cpp +++ b/ext/libclementine-common/core/logging.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -43,7 +44,7 @@ const char* kDefaultLogLevels = "GstEnginePipeline:2,*:3"; static const char* kMessageHandlerMagic = "__logging_message__"; static const int kMessageHandlerMagicLength = strlen(kMessageHandlerMagic); -static QtMsgHandler sOriginalMessageHandler = nullptr; +static QtMessageHandler sOriginalMessageHandler = nullptr; void GLog(const char* domain, int level, const char* message, void* user_data) { switch (level) { @@ -67,9 +68,9 @@ void GLog(const char* domain, int level, const char* message, void* user_data) { } } -static void MessageHandler(QtMsgType type, const char* message) { - if (strncmp(kMessageHandlerMagic, message, kMessageHandlerMagicLength) == 0) { - fprintf(stderr, "%s\n", message + kMessageHandlerMagicLength); +static void MessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message) { + if (strncmp(kMessageHandlerMagic, message.toLocal8Bit().data(), kMessageHandlerMagicLength) == 0) { + fprintf(stderr, "%s\n", message.toLocal8Bit().data() + kMessageHandlerMagicLength); return; } @@ -88,7 +89,7 @@ static void MessageHandler(QtMsgType type, const char* message) { break; } - for (const QString& line : QString::fromLocal8Bit(message).split('\n')) { + for (const QString& line : message.split('\n')) { CreateLogger(level, "unknown", -1) << line.toLocal8Bit().constData(); } @@ -106,7 +107,7 @@ void Init() { // Catch other messages from Qt if (!sOriginalMessageHandler) { - sOriginalMessageHandler = qInstallMsgHandler(MessageHandler); + sOriginalMessageHandler = qInstallMessageHandler(MessageHandler); } } @@ -204,9 +205,9 @@ QDebug CreateLogger(Level level, const QString& class_name, int line) { QDebug ret(type); ret.nospace() << kMessageHandlerMagic << QDateTime::currentDateTime() .toString("hh:mm:ss.zzz") - .toAscii() + .toLatin1() .constData() << level_name - << function_line.leftJustified(32).toAscii().constData(); + << function_line.leftJustified(32).toLatin1().constData(); return ret.space(); } @@ -214,9 +215,9 @@ QDebug CreateLogger(Level level, const QString& class_name, int line) { QString CXXDemangle(const QString& mangled_function) { int status; char* demangled_function = abi::__cxa_demangle( - mangled_function.toAscii().constData(), nullptr, nullptr, &status); + mangled_function.toLatin1().constData(), nullptr, nullptr, &status); if (status == 0) { - QString ret = QString::fromAscii(demangled_function); + QString ret = QString::fromLatin1(demangled_function); free(demangled_function); return ret; } @@ -257,7 +258,7 @@ void DumpStackTrace() { backtrace_symbols(reinterpret_cast(&callstack), callstack_size); // Start from 1 to skip ourself. for (int i = 1; i < callstack_size; ++i) { - qLog(Debug) << DemangleSymbol(QString::fromAscii(symbols[i])); + qLog(Debug) << DemangleSymbol(QString::fromLatin1(symbols[i])); } free(symbols); #else diff --git a/src/core/database.cpp b/src/core/database.cpp index e351aa32e..908ee7f4b 100644 --- a/src/core/database.cpp +++ b/src/core/database.cpp @@ -265,13 +265,14 @@ QSqlDatabase Database::Connect() { StaticInit(); { - QSqlQuery set_fts_tokenizer("SELECT fts3_tokenizer(:name, :pointer)", db); + QSqlQuery set_fts_tokenizer(db); + set_fts_tokenizer.prepare("SELECT fts3_tokenizer(:name, :pointer)"); set_fts_tokenizer.bindValue(":name", "unicode"); set_fts_tokenizer.bindValue( ":pointer", QByteArray(reinterpret_cast(&sFTSTokenizer), sizeof(&sFTSTokenizer))); if (!set_fts_tokenizer.exec()) { - qLog(Warning) << "Couldn't register FTS3 tokenizer"; + qLog(Warning) << "Couldn't register FTS3 tokenizer : " << set_fts_tokenizer.lastError(); } // Implicit invocation of ~QSqlQuery() when leaving the scope // to release any remaining database locks! @@ -290,12 +291,13 @@ QSqlDatabase Database::Connect() { if (!injected_database_name_.isNull()) filename = injected_database_name_; // Attach the db - QSqlQuery q("ATTACH DATABASE :filename AS :alias", db); + QSqlQuery q(db); + q.prepare("ATTACH DATABASE :filename AS :alias"); q.bindValue(":filename", filename); q.bindValue(":alias", key); if (!q.exec()) { qFatal("Couldn't attach external database '%s'", - key.toAscii().constData()); + key.toLatin1().constData()); } } @@ -310,10 +312,10 @@ QSqlDatabase Database::Connect() { attached_databases_[key].schema_.isEmpty()) continue; // Find out if there are any tables in this database - QSqlQuery q(QString( + QSqlQuery q(db); + q.prepare(QString( "SELECT ROWID FROM %1.sqlite_master" - " WHERE type='table'").arg(key), - db); + " WHERE type='table'").arg(key)); if (!q.exec() || !q.next()) { q.finish(); ExecSchemaCommandsFromFile(db, attached_databases_[key].schema_, 0); @@ -360,7 +362,8 @@ void Database::RecreateAttachedDb(const QString& database_name) { { QSqlDatabase db(Connect()); - QSqlQuery q("DETACH DATABASE :alias", db); + QSqlQuery q(db); + q.prepare("DETACH DATABASE :alias"); q.bindValue(":alias", database_name); if (!q.exec()) { qLog(Warning) << "Failed to detach database" << database_name; @@ -391,12 +394,13 @@ void Database::AttachDatabaseOnDbConnection(const QString& database_name, AttachDatabase(database_name, database); // Attach the db - QSqlQuery q("ATTACH DATABASE :filename AS :alias", db); + QSqlQuery q(db); + q.prepare("ATTACH DATABASE :filename AS :alias"); q.bindValue(":filename", database.filename_); q.bindValue(":alias", database_name); if (!q.exec()) { qFatal("Couldn't attach external database '%s'", - database_name.toAscii().constData()); + database_name.toLatin1().constData()); } } @@ -405,7 +409,8 @@ void Database::DetachDatabase(const QString& database_name) { { QSqlDatabase db(Connect()); - QSqlQuery q("DETACH DATABASE :alias", db); + QSqlQuery q(db); + q.prepare("DETACH DATABASE :alias"); q.bindValue(":alias", database_name); if (!q.exec()) { qLog(Warning) << "Failed to detach database" << database_name; @@ -448,10 +453,10 @@ void Database::UpdateDatabaseSchema(int version, QSqlDatabase& db) { } void Database::UrlEncodeFilenameColumn(const QString& table, QSqlDatabase& db) { - QSqlQuery select(QString("SELECT ROWID, filename FROM %1").arg(table), db); - QSqlQuery update( - QString("UPDATE %1 SET filename=:filename WHERE ROWID=:id").arg(table), - db); + QSqlQuery select(db); + select.prepare(QString("SELECT ROWID, filename FROM %1").arg(table)); + QSqlQuery update(db); + update.prepare(QString("UPDATE %1 SET filename=:filename WHERE ROWID=:id").arg(table)); select.exec(); if (CheckErrors(select)) return; while (select.next()) { @@ -545,12 +550,11 @@ QStringList Database::SongsTables(QSqlDatabase& db, int schema_version) const { // look for the tables in attached dbs for (const QString& key : attached_databases_.keys()) { - QSqlQuery q( - QString( + QSqlQuery q(db); + q.prepare(QString( "SELECT NAME FROM %1.sqlite_master" " WHERE type='table' AND name='songs' OR name LIKE '%songs'") - .arg(key), - db); + .arg(key)); if (q.exec()) { while (q.next()) { QString tab_name = key + "." + q.value(0).toString(); @@ -587,7 +591,7 @@ bool Database::IntegrityCheck(QSqlDatabase db) { bool ok = false; bool error_reported = false; // Ask for 10 error messages at most. - QSqlQuery q(QString("PRAGMA integrity_check(10)"), db); + QSqlQuery q("PRAGMA integrity_check(10)", db); while (q.next()) { QString message = q.value(0).toString(); diff --git a/src/core/mergedproxymodel.cpp b/src/core/mergedproxymodel.cpp index 56217f6fd..e7f6587f9 100644 --- a/src/core/mergedproxymodel.cpp +++ b/src/core/mergedproxymodel.cpp @@ -183,12 +183,14 @@ void MergedProxyModel::SourceModelReset() { // Delete all mappings DeleteAllMappings(); + // Reset the proxy + beginResetModel(); + // Clear the containers p_->mappings_.clear(); merge_points_.clear(); - // Reset the proxy - reset(); + endResetModel(); } void MergedProxyModel::SubModelReset() { @@ -497,7 +499,8 @@ void MergedProxyModel::LayoutChanged() { const int new_row = merge_points_[key].row(); if (old_row != new_row) { - reset(); + beginResetModel(); + endResetModel(); return; } } diff --git a/src/core/metatypes.cpp b/src/core/metatypes.cpp index daf5b71f7..7691e4e32 100644 --- a/src/core/metatypes.cpp +++ b/src/core/metatypes.cpp @@ -29,6 +29,7 @@ #include "covers/albumcoverfetcher.h" #include "engines/enginebase.h" #include "engines/gstengine.h" +#include "engines/gstenginepipeline.h" #include "globalsearch/searchprovider.h" #include "internet/digitally/digitallyimportedclient.h" #include "internet/core/geolocator.h" @@ -53,7 +54,6 @@ class GstEnginePipeline; class QNetworkReply; void RegisterMetaTypes() { - qRegisterMetaType("ColumnAlignmentMap"); qRegisterMetaType("const char*"); qRegisterMetaType("CoverSearchResult"); qRegisterMetaType("CoverSearchResults"); diff --git a/src/core/organiseformat.h b/src/core/organiseformat.h index e24a22461..77005794c 100644 --- a/src/core/organiseformat.h +++ b/src/core/organiseformat.h @@ -22,6 +22,7 @@ #include #include +#include #include "core/song.h" diff --git a/src/core/potranslator.h b/src/core/potranslator.h index eafdccf2f..e92ba3429 100644 --- a/src/core/potranslator.h +++ b/src/core/potranslator.h @@ -29,7 +29,7 @@ class PoTranslator : public QTranslator { public: QString translate(const char* context, const char* source_text, - const char* disambiguation = 0) const { + const char* disambiguation = 0, int n = -1) const { QString ret = QTranslator::translate(context, source_text, disambiguation); if (!ret.isEmpty()) return ret; return QTranslator::translate(nullptr, source_text, disambiguation); diff --git a/src/core/qxtglobalshortcutbackend.cpp b/src/core/qxtglobalshortcutbackend.cpp index f33b3e325..c04e41d4a 100644 --- a/src/core/qxtglobalshortcutbackend.cpp +++ b/src/core/qxtglobalshortcutbackend.cpp @@ -40,7 +40,6 @@ bool QxtGlobalShortcutBackend::DoRegister() { void QxtGlobalShortcutBackend::AddShortcut(QAction* action) { if (action->shortcut().isEmpty()) return; - QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(action->shortcut(), this); connect(shortcut, SIGNAL(activated()), action, SLOT(trigger())); shortcuts_ << shortcut; diff --git a/src/core/qxtglobalshortcutbackend.h b/src/core/qxtglobalshortcutbackend.h index 32361291c..4976241c5 100644 --- a/src/core/qxtglobalshortcutbackend.h +++ b/src/core/qxtglobalshortcutbackend.h @@ -23,6 +23,7 @@ #include "globalshortcutbackend.h" class QxtGlobalShortcut; +class QAction; class QxtGlobalShortcutBackend : public GlobalShortcutBackend { public: diff --git a/src/covers/amazoncoverprovider.cpp b/src/covers/amazoncoverprovider.cpp index 63aead35a..7d991bb0d 100644 --- a/src/covers/amazoncoverprovider.cpp +++ b/src/covers/amazoncoverprovider.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "core/closure.h" #include "core/logging.h" @@ -79,14 +80,14 @@ bool AmazonCoverProvider::StartSearch(const QString& artist, const QByteArray data_to_sign = QString("GET\n%1\n%2\n%3") .arg(url.host(), url.path(), query_items.join("&")) - .toAscii(); + .toLatin1(); const QByteArray signature(Utilities::HmacSha256( QByteArray::fromBase64(kSecretAccessKeyB64), data_to_sign)); // Add the signature to the request - encoded_args << EncodedArg("Signature", - QUrl::toPercentEncoding(signature.toBase64())); - url.setEncodedQueryItems(encoded_args); + QUrlQuery url_query; + url_query.addQueryItem("Signature", QUrl::toPercentEncoding(signature.toBase64())); + url.setQuery(url_query); QNetworkReply* reply = network_->get(QNetworkRequest(url)); NewClosure(reply, SIGNAL(finished()), this, diff --git a/src/covers/musicbrainzcoverprovider.cpp b/src/covers/musicbrainzcoverprovider.cpp index 827bd085c..fffaab179 100644 --- a/src/covers/musicbrainzcoverprovider.cpp +++ b/src/covers/musicbrainzcoverprovider.cpp @@ -22,6 +22,7 @@ #include #include +#include #include "core/closure.h" #include "core/network.h" @@ -46,8 +47,10 @@ bool MusicbrainzCoverProvider::StartSearch(const QString& artist, QString query = QString("release:\"%1\" AND artist:\"%2\"") .arg(album.trimmed().replace('"', "\\\"")) .arg(artist.trimmed().replace('"', "\\\"")); - url.addQueryItem("query", query); - url.addQueryItem("limit", "5"); + QUrlQuery url_query; + url_query.addQueryItem("query", query); + url_query.addQueryItem("limit", "5"); + url.setQuery(url_query); QNetworkRequest request(url); QNetworkReply* reply = network_->get(request); diff --git a/src/dbus/org.mpris.MediaPlayer2.TrackList.xml b/src/dbus/org.mpris.MediaPlayer2.TrackList.xml index 51b4bbc6a..5b609c7b3 100644 --- a/src/dbus/org.mpris.MediaPlayer2.TrackList.xml +++ b/src/dbus/org.mpris.MediaPlayer2.TrackList.xml @@ -5,9 +5,8 @@ - - - + + @@ -25,19 +24,17 @@ - - - + + - - - + + diff --git a/src/devices/devicedatabasebackend.cpp b/src/devices/devicedatabasebackend.cpp index 14f28ed66..308805507 100644 --- a/src/devices/devicedatabasebackend.cpp +++ b/src/devices/devicedatabasebackend.cpp @@ -36,11 +36,10 @@ DeviceDatabaseBackend::DeviceList DeviceDatabaseBackend::GetAllDevices() { DeviceList ret; - QSqlQuery q( - "SELECT ROWID, unique_id, friendly_name, size, icon," + QSqlQuery q(db); + q.prepare("SELECT ROWID, unique_id, friendly_name, size, icon," " transcode_mode, transcode_format" - " FROM devices", - db); + " FROM devices"); q.exec(); if (db_->CheckErrors(q)) return ret; @@ -65,13 +64,12 @@ int DeviceDatabaseBackend::AddDevice(const Device& device) { ScopedTransaction t(&db); // Insert the device into the devices table - QSqlQuery q( - "INSERT INTO devices (" + QSqlQuery q(db); + q.prepare("INSERT INTO devices (" " unique_id, friendly_name, size, icon," " transcode_mode, transcode_format)" " VALUES (:unique_id, :friendly_name, :size, :icon," - " :transcode_mode, :transcode_format)", - db); + " :transcode_mode, :transcode_format)"); q.bindValue(":unique_id", device.unique_id_); q.bindValue(":friendly_name", device.friendly_name_); q.bindValue(":size", device.size_); @@ -103,7 +101,8 @@ void DeviceDatabaseBackend::RemoveDevice(int id) { ScopedTransaction t(&db); // Remove the device from the devices table - QSqlQuery q("DELETE FROM devices WHERE ROWID=:id", db); + QSqlQuery q(db); + q.prepare("DELETE FROM devices WHERE ROWID=:id"); q.bindValue(":id", id); q.exec(); if (db_->CheckErrors(q)) return; @@ -125,14 +124,13 @@ void DeviceDatabaseBackend::SetDeviceOptions(int id, QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q( - "UPDATE devices" + QSqlQuery q(db); + q.prepare("UPDATE devices" " SET friendly_name=:friendly_name," " icon=:icon_name," " transcode_mode=:transcode_mode," " transcode_format=:transcode_format" - " WHERE ROWID=:id", - db); + " WHERE ROWID=:id"); q.bindValue(":friendly_name", friendly_name); q.bindValue(":icon_name", icon_name); q.bindValue(":transcode_mode", mode); diff --git a/src/devices/deviceproperties.cpp b/src/devices/deviceproperties.cpp index c097d409d..1b6cd2f64 100644 --- a/src/devices/deviceproperties.cpp +++ b/src/devices/deviceproperties.cpp @@ -155,7 +155,7 @@ void DeviceProperties::UpdateHardwareInfo() { AddHardwareInfo(row++, tr("Model"), lister->DeviceModel(id)); AddHardwareInfo(row++, tr("Manufacturer"), lister->DeviceManufacturer(id)); for (const QString& key : info.keys()) { - AddHardwareInfo(row++, tr(key.toAscii()), info[key].toString()); + AddHardwareInfo(row++, tr(key.toLatin1()), info[key].toString()); } ui_->hardware_info->sortItems(0); diff --git a/src/engines/gstengine.cpp b/src/engines/gstengine.cpp index 7f903ff7b..35b9bbfc7 100755 --- a/src/engines/gstengine.cpp +++ b/src/engines/gstengine.cpp @@ -709,7 +709,7 @@ GstElement* GstEngine::CreateElement(const QString& factoryName, QString name = factoryName + "-" + QString::number(next_element_id_++); GstElement* element = gst_element_factory_make( - factoryName.toAscii().constData(), name.toAscii().constData()); + factoryName.toLatin1().constData(), name.toLatin1().constData()); if (!element) { emit Error(QString( diff --git a/src/engines/gstenginepipeline.cpp b/src/engines/gstenginepipeline.cpp index 7f48f1fb2..d381f0b04 100644 --- a/src/engines/gstenginepipeline.cpp +++ b/src/engines/gstenginepipeline.cpp @@ -413,7 +413,7 @@ bool GstEnginePipeline::InitFromString(const QString& pipeline) { pipeline_ = gst_pipeline_new("pipeline"); GstElement* new_bin = - CreateDecodeBinFromString(pipeline.toAscii().constData()); + CreateDecodeBinFromString(pipeline.toLatin1().constData()); if (!new_bin) { return false; } diff --git a/src/globalsearch/globalsearchsettingspage.cpp b/src/globalsearch/globalsearchsettingspage.cpp index 460d63a81..3ea953630 100644 --- a/src/globalsearch/globalsearchsettingspage.cpp +++ b/src/globalsearch/globalsearchsettingspage.cpp @@ -28,8 +28,8 @@ GlobalSearchSettingsPage::GlobalSearchSettingsPage(SettingsDialog* dialog) : SettingsPage(dialog), ui_(new Ui::GlobalSearchSettingsPage) { ui_->setupUi(this); - ui_->sources->header()->setResizeMode(0, QHeaderView::Stretch); - ui_->sources->header()->setResizeMode(1, QHeaderView::ResizeToContents); + ui_->sources->header()->setSectionResizeMode(0, QHeaderView::Stretch); + ui_->sources->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); warning_icon_ = IconLoader::Load("dialog-warning"); diff --git a/src/internet/core/geolocator.cpp b/src/internet/core/geolocator.cpp index f527dd81d..990308d0c 100644 --- a/src/internet/core/geolocator.cpp +++ b/src/internet/core/geolocator.cpp @@ -22,9 +22,10 @@ #include #include -#include - #include +#include +#include +#include #include "core/closure.h" #include "core/logging.h" @@ -97,16 +98,15 @@ void Geolocator::RequestFinished(QNetworkReply* reply) { return; } - QJson::Parser parser; - bool ok = false; - QVariant result = parser.parse(reply, &ok); - if (!ok) { + QJsonParseError error; + QJsonDocument json_document = QJsonDocument::fromJson(reply->readAll(), &error); + if (error.error != QJsonParseError::NoError) { emit Finished(LatLng()); return; } - QVariantMap map = result.toMap(); - QString latlng = map["latlng"].toString(); + QJsonObject json_object = json_document.object(); + QString latlng = json_object["latlng"].toString(); LatLng ll(latlng); emit Finished(ll); diff --git a/src/internet/core/internetshowsettingspage.cpp b/src/internet/core/internetshowsettingspage.cpp index 6df377921..639f22ab7 100644 --- a/src/internet/core/internetshowsettingspage.cpp +++ b/src/internet/core/internetshowsettingspage.cpp @@ -29,8 +29,8 @@ InternetShowSettingsPage::InternetShowSettingsPage(SettingsDialog* parent) : SettingsPage(parent), ui_(new Ui::InternetShowSettingsPage) { ui_->setupUi(this); - ui_->sources->header()->setResizeMode(0, QHeaderView::Stretch); - ui_->sources->header()->setResizeMode(1, QHeaderView::ResizeToContents); + ui_->sources->header()->setSectionResizeMode(0, QHeaderView::Stretch); + ui_->sources->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); } void InternetShowSettingsPage::Load() { diff --git a/src/internet/core/oauthenticator.cpp b/src/internet/core/oauthenticator.cpp index 8996da5f4..08f78f947 100644 --- a/src/internet/core/oauthenticator.cpp +++ b/src/internet/core/oauthenticator.cpp @@ -23,8 +23,10 @@ #include #include #include - -#include +#include +#include +#include +#include #include "core/closure.h" #include "core/logging.h" @@ -49,24 +51,29 @@ void OAuthenticator::StartAuthorisation(const QString& oauth_endpoint, server->Listen(); QUrl url = QUrl(oauth_endpoint); - url.addQueryItem("response_type", "code"); - url.addQueryItem("client_id", client_id_); + QUrlQuery url_query; + url_query.addQueryItem("response_type", "code"); + url_query.addQueryItem("client_id", client_id_); QUrl redirect_url; + QUrlQuery redirect_url_query; const QString port = QString::number(server->url().port()); if (redirect_style_ == RedirectStyle::REMOTE) { redirect_url = QUrl(kRemoteURL); - redirect_url.addQueryItem("port", port); + redirect_url_query.addQueryItem("port", port); } else if (redirect_style_ == RedirectStyle::REMOTE_WITH_STATE) { redirect_url = QUrl(kRemoteURL); - url.addQueryItem("state", port); + url_query.addQueryItem("state", port); } else { redirect_url = server->url(); } - url.addQueryItem("redirect_uri", redirect_url.toString()); - url.addQueryItem("scope", scope); + url_query.addQueryItem("redirect_uri", redirect_url.toString()); + url_query.addQueryItem("scope", scope); + + url.setQuery(url_query); + redirect_url.setQuery(redirect_url_query); NewClosure(server, SIGNAL(Finished()), this, &OAuthenticator::RedirectArrived, server, redirect_url); @@ -78,7 +85,7 @@ void OAuthenticator::RedirectArrived(LocalRedirectServer* server, QUrl url) { server->deleteLater(); QUrl request_url = server->request_url(); qLog(Debug) << Q_FUNC_INFO << request_url; - RequestAccessToken(request_url.queryItemValue("code").toUtf8(), url); + RequestAccessToken(QUrlQuery(request_url).queryItemValue("code").toUtf8(), url); } QByteArray OAuthenticator::ParseHttpRequest(const QByteArray& request) const { @@ -126,19 +133,20 @@ void OAuthenticator::FetchAccessTokenFinished(QNetworkReply* reply) { return; } - QJson::Parser parser; - bool ok = false; - QVariantMap result = parser.parse(reply, &ok).toMap(); - if (!ok) { + QJsonParseError error; + QJsonDocument json_document = QJsonDocument::fromJson(reply->readAll(), &error); + + if (error.error != QJsonParseError::NoError) { qLog(Error) << "Failed to parse oauth reply"; return; } - qLog(Debug) << result; + QJsonObject json_result = json_document.object(); + qLog(Debug) << json_result; - access_token_ = result["access_token"].toString(); - refresh_token_ = result["refresh_token"].toString(); - SetExpiryTime(result["expires_in"].toInt()); + access_token_ = json_result["access_token"].toString(); + refresh_token_ = json_result["refresh_token"].toString(); + SetExpiryTime(json_result["expires_in"].toInt()); emit Finished(); } @@ -178,14 +186,13 @@ void OAuthenticator::SetExpiryTime(int expires_in_seconds) { void OAuthenticator::RefreshAccessTokenFinished(QNetworkReply* reply) { reply->deleteLater(); - QJson::Parser parser; - bool ok = false; - QVariantMap result = parser.parse(reply, &ok).toMap(); - access_token_ = result["access_token"].toString(); - if (result.contains("refresh_token")) { - refresh_token_ = result["refresh_token"].toString(); + QJsonObject json_result = QJsonDocument::fromJson(reply->readAll()).object(); + + access_token_ = json_result["access_token"].toString(); + if (json_result.contains("refresh_token")) { + refresh_token_ = json_result["refresh_token"].toString(); } - SetExpiryTime(result["expires_in"].toInt()); + SetExpiryTime(json_result["expires_in"].toInt()); emit Finished(); } diff --git a/src/internet/digitally/digitallyimportedclient.cpp b/src/internet/digitally/digitallyimportedclient.cpp index 9609301d6..f72d2ea34 100644 --- a/src/internet/digitally/digitallyimportedclient.cpp +++ b/src/internet/digitally/digitallyimportedclient.cpp @@ -19,10 +19,11 @@ #include "digitallyimportedclient.h" -#include - #include #include +#include +#include +#include #include "core/logging.h" #include "core/network.h" @@ -52,7 +53,7 @@ void DigitallyImportedClient::SetAuthorisationHeader( req->setRawHeader("Authorization", "Basic " + QString("%1:%2") .arg(kApiUsername, kApiPassword) - .toAscii() + .toLatin1() .toBase64()); } @@ -82,32 +83,30 @@ DigitallyImportedClient::AuthReply DigitallyImportedClient::ParseAuthReply( return ret; } - QJson::Parser parser; - QVariantMap data = parser.parse(reply).toMap(); + QJsonObject json_root_object = QJsonDocument::fromJson(reply->readAll()).object(); - if (!data.contains("subscriptions")) { + if (json_root_object["subscriptions"].isUndefined()) { return ret; } - QVariantList subscriptions = - data.value("subscriptions", QVariantList()).toList(); - if (subscriptions.isEmpty() || - subscriptions[0].toMap().value("status").toString() != "active") { + QJsonArray json_subscriptions = json_root_object["subscriptions"].toArray(); + if (json_subscriptions.isEmpty() || + json_subscriptions[0].toObject()["status"].toString() != "active") { ret.error_reason_ = tr("You do not have an active subscription"); return ret; } - if (!data.contains("first_name") || !data.contains("last_name") || - !subscriptions[0].toMap().contains("expires_on") || - !data.contains("listen_key")) + if (json_root_object["first_name"].isUndefined() || json_root_object["last_name"].isUndefined() || + json_subscriptions[0].toObject()["expires_on"].isUndefined() || + json_root_object["listen_key"].isUndefined()) return ret; ret.success_ = true; - ret.first_name_ = data["first_name"].toString(); - ret.last_name_ = data["last_name"].toString(); + ret.first_name_ = json_root_object["first_name"].toString(); + ret.last_name_ = json_root_object["last_name"].toString(); ret.expires_ = QDateTime::fromString( - subscriptions[0].toMap()["expires_on"].toString(), Qt::ISODate); - ret.listen_hash_ = data["listen_key"].toString(); + json_subscriptions[0].toObject()["expires_on"].toString(), Qt::ISODate); + ret.listen_hash_ = json_root_object["listen_key"].toString(); return ret; } @@ -123,30 +122,28 @@ DigitallyImportedClient::ChannelList DigitallyImportedClient::ParseChannelList( QNetworkReply* reply) const { ChannelList ret; - QJson::Parser parser; - QVariantMap data = parser.parse(reply).toMap(); + QJsonObject json_root_object = QJsonDocument::fromJson(reply->readAll()).object(); - if (!data.contains("channel_filters")) return ret; + if (json_root_object["channel_filters"].isUndefined()) return ret; - QVariantList filters = data["channel_filters"].toList(); + QJsonArray json_filters = json_root_object["channel_filters"].toArray(); - for (const QVariant& filter : filters) { + for (const QJsonValue & filter: json_filters) { // Find the filter called "All" - QVariantMap filter_map = filter.toMap(); - if (filter_map.value("name", QString()).toString() != "All") continue; + QJsonObject json_filter = filter.toObject(); + if (json_filter["name"].toString() != "All") continue; // Add all its stations to the result - QVariantList channels = - filter_map.value("channels", QVariantList()).toList(); - for (const QVariant& channel_var : channels) { - QVariantMap channel_map = channel_var.toMap(); + QJsonArray json_channels = json_filter["channels"].toArray(); + for (const QJsonValue& channel_var : json_channels) { + QJsonObject json_channel = channel_var.toObject(); Channel channel; - channel.art_url_ = QUrl(channel_map.value("asset_url").toString()); - channel.description_ = channel_map.value("description").toString(); - channel.director_ = channel_map.value("channel_director").toString(); - channel.key_ = channel_map.value("key").toString(); - channel.name_ = channel_map.value("name").toString(); + channel.art_url_ = QUrl(json_channel["asset_url"].toString()); + channel.description_ = json_channel["description"].toString(); + channel.director_ = json_channel["channel_director"].toString(); + channel.key_ = json_channel["key"].toString(); + channel.name_ = json_channel["name"].toString(); ret << channel; } diff --git a/src/internet/grooveshark/groovesharkservice.cpp b/src/internet/grooveshark/groovesharkservice.cpp index dd9bca060..5c5f8e67a 100644 --- a/src/internet/grooveshark/groovesharkservice.cpp +++ b/src/internet/grooveshark/groovesharkservice.cpp @@ -35,9 +35,11 @@ #include #include #include - -#include -#include +#include +#include +#include +#include +#include #include "qtiocompressor.h" @@ -215,7 +217,7 @@ int GroovesharkService::SimpleSearch(const QString& query) { void GroovesharkService::SimpleSearchFinished(QNetworkReply* reply, int id) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); SongList songs = ExtractSongs(result); emit SimpleSearchResults(id, songs); } @@ -238,12 +240,12 @@ int GroovesharkService::SearchAlbums(const QString& query) { void GroovesharkService::SearchAlbumsFinished(QNetworkReply* reply, int id) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); - QVariantList albums = result["albums"].toList(); + QJsonObject result = ExtractResult(reply).object(); + QJsonArray json_albums = result["albums"].toArray(); QList ret; - for (const QVariant& v : albums) { - quint64 album_id = v.toMap()["AlbumID"].toULongLong(); + for (const QJsonValue& v : json_albums) { + quint64 album_id = v.toObject()["AlbumID"].toString().toULongLong(); GetAlbumSongs(album_id); ret << album_id; } @@ -263,7 +265,7 @@ void GroovesharkService::GetAlbumSongs(quint64 album_id) { void GroovesharkService::GetAlbumSongsFinished(QNetworkReply* reply, quint64 album_id) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); SongList songs = ExtractSongs(result); emit AlbumSongsLoaded(album_id, songs); @@ -291,7 +293,7 @@ void GroovesharkService::SearchSongsFinished(QNetworkReply* reply) { if (reply != last_search_reply_) return; - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); SongList songs = ExtractSongs(result); app_->task_manager()->SetTaskFinished(task_search_id_); task_search_id_ = 0; @@ -311,7 +313,7 @@ void GroovesharkService::InitCountry() { // Get country info QNetworkReply* reply_country = CreateRequest("getCountry", QList()); if (WaitForReply(reply_country)) { - country_ = ExtractResult(reply_country); + country_ = ExtractResult(reply_country).object().toVariantMap(); } reply_country->deleteLater(); } @@ -332,12 +334,12 @@ QUrl GroovesharkService::GetStreamingUrlFromSongId(const QString& song_id, reply->deleteLater(); if (reply_has_timeouted) return QUrl(); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); server_id->clear(); server_id->append(result["StreamServerID"].toString()); stream_key->clear(); stream_key->append(result["StreamKey"].toString()); - *length_nanosec = result["uSecs"].toLongLong() * 1000; + *length_nanosec = result["uSecs"].toString().toLongLong() * 1000; // Keep in mind that user has request to listen to this song last_songs_ids_.append(song_id.toInt()); last_artists_ids_.append(artist_id.toInt()); @@ -375,7 +377,7 @@ void GroovesharkService::SessionCreated(QNetworkReply* reply) { return; } - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); if (!result["success"].toBool()) { qLog(Error) << "Grooveshark returned an error during session creation"; } @@ -397,7 +399,7 @@ void GroovesharkService::AuthenticateSession() { void GroovesharkService::Authenticated(QNetworkReply* reply) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); // Check if the user has been authenticated correctly QString error; if (!result["success"].toBool() || result["UserID"].toInt() == 0) { @@ -700,7 +702,7 @@ void GroovesharkService::RetrieveUserPlaylists() { void GroovesharkService::UserPlaylistsRetrieved(QNetworkReply* reply) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); QList playlists = ExtractPlaylistInfo(result); for (const PlaylistInfo& playlist_info : playlists) { @@ -737,7 +739,7 @@ void GroovesharkService::PlaylistSongsRetrieved(QNetworkReply* reply, : &playlists_[playlist_id]; playlist_info->item_->removeRows(0, playlist_info->item_->rowCount()); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); SongList songs = ExtractSongs(result); SortSongsAlphabeticallyIfNeeded(&songs); @@ -778,7 +780,7 @@ void GroovesharkService::UserFavoritesRetrieved(QNetworkReply* reply, favorites_->removeRows(0, favorites_->rowCount()); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); SongList songs = ExtractSongs(result); SortSongsAlphabeticallyIfNeeded(&songs); @@ -812,7 +814,7 @@ void GroovesharkService::UserLibrarySongsRetrieved(QNetworkReply* reply, library_->removeRows(0, library_->rowCount()); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); SongList songs = ExtractSongs(result); SortSongsAlphabeticallyIfNeeded(&songs); @@ -841,7 +843,7 @@ void GroovesharkService::RetrievePopularSongsMonth() { void GroovesharkService::PopularSongsMonthRetrieved(QNetworkReply* reply) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); SongList songs = ExtractSongs(result); app_->task_manager()->IncreaseTaskProgress(task_popular_id_, 50, 100); @@ -867,7 +869,7 @@ void GroovesharkService::RetrievePopularSongsToday() { void GroovesharkService::PopularSongsTodayRetrieved(QNetworkReply* reply) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); SongList songs = ExtractSongs(result); app_->task_manager()->IncreaseTaskProgress(task_popular_id_, 50, 100); @@ -893,7 +895,7 @@ void GroovesharkService::RetrieveSubscribedPlaylists() { void GroovesharkService::SubscribedPlaylistsRetrieved(QNetworkReply* reply) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); QList playlists = ExtractPlaylistInfo(result); for (const PlaylistInfo& playlist_info : playlists) { @@ -924,9 +926,10 @@ void GroovesharkService::RetrieveAutoplayTags() { void GroovesharkService::AutoplayTagsRetrieved(QNetworkReply* reply) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); - QVariantMap::const_iterator it; + QJsonObject result = ExtractResult(reply).object(); + QJsonObject::const_iterator it; if (!stations_) return; + for (it = result.constBegin(); it != result.constEnd(); ++it) { int id = it.key().toInt(); QString name = it.value().toString().toLower(); @@ -955,9 +958,9 @@ Song GroovesharkService::StartAutoplayTag(int tag_id, reply->deleteLater(); if (reply_has_timeouted) return Song(); - QVariantMap result = ExtractResult(reply); - autoplay_state = result["autoplayState"].toMap(); - return ExtractSong(result["nextSong"].toMap()); + QJsonObject result = ExtractResult(reply).object(); + autoplay_state = result["autoplayState"].toObject().toVariantMap(); + return ExtractSong(result["nextSong"].toObject()); } Song GroovesharkService::StartAutoplay(QVariantMap& autoplay_state) { @@ -978,9 +981,9 @@ Song GroovesharkService::StartAutoplay(QVariantMap& autoplay_state) { reply->deleteLater(); if (reply_has_timeouted) return Song(); - QVariantMap result = ExtractResult(reply); - autoplay_state = result["autoplayState"].toMap(); - return ExtractSong(result["nextSong"].toMap()); + QJsonObject result = ExtractResult(reply).object(); + autoplay_state = result["autoplayState"].toObject().toVariantMap(); + return ExtractSong(result["nextSong"].toObject()); } Song GroovesharkService::GetAutoplaySong(QVariantMap& autoplay_state) { @@ -992,9 +995,9 @@ Song GroovesharkService::GetAutoplaySong(QVariantMap& autoplay_state) { reply->deleteLater(); if (reply_has_timeouted) return Song(); - QVariantMap result = ExtractResult(reply); - autoplay_state = result["autoplayState"].toMap(); - return ExtractSong(result["nextSong"].toMap()); + QJsonObject result = ExtractResult(reply).object(); + autoplay_state = result["autoplayState"].toObject().toVariantMap(); + return ExtractSong(result["nextSong"].toObject()); } void GroovesharkService::MarkStreamKeyOver30Secs(const QString& stream_key, @@ -1010,7 +1013,7 @@ void GroovesharkService::MarkStreamKeyOver30Secs(const QString& stream_key, void GroovesharkService::StreamMarked(QNetworkReply* reply) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); if (!result["success"].toBool()) { qLog(Warning) << "Grooveshark markStreamKeyOver30Secs failed"; } @@ -1030,7 +1033,7 @@ void GroovesharkService::MarkSongComplete(const QString& song_id, void GroovesharkService::SongMarkedAsComplete(QNetworkReply* reply) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); if (!result["success"].toBool()) { qLog(Warning) << "Grooveshark markSongComplete failed"; } @@ -1177,8 +1180,8 @@ void GroovesharkService::GetSongUrlToShare(int song_id) { void GroovesharkService::SongUrlToShareReceived(QNetworkReply* reply) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); - if (!result["url"].isValid()) return; + QJsonObject result = ExtractResult(reply).object(); + if (result["url"].isUndefined()) return; QString url = result["url"].toString(); ShowUrlBox(tr("Grooveshark song's URL"), url); } @@ -1199,8 +1202,8 @@ void GroovesharkService::GetPlaylistUrlToShare(int playlist_id) { void GroovesharkService::PlaylistUrlToShareReceived(QNetworkReply* reply) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); - if (!result["url"].isValid()) return; + QJsonObject result = ExtractResult(reply).object(); + if (result["url"].isUndefined()) return; QString url = result["url"].toString(); ShowUrlBox(tr("Grooveshark playlist's URL"), url); } @@ -1249,7 +1252,7 @@ void GroovesharkService::PlaylistSongsSet(QNetworkReply* reply, int playlist_id, reply->deleteLater(); app_->task_manager()->SetTaskFinished(task_id); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); if (!result["success"].toBool()) { qLog(Warning) << "Grooveshark setPlaylistSongs failed"; return; @@ -1289,8 +1292,8 @@ void GroovesharkService::CreateNewPlaylist() { void GroovesharkService::NewPlaylistCreated(QNetworkReply* reply, const QString& name) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); - if (!result["success"].toBool() || !result["playlistID"].isValid()) { + QJsonObject result = ExtractResult(reply).object(); + if (!result["success"].toBool() || result["playlistID"].isUndefined()) { qLog(Warning) << "Grooveshark createPlaylist failed"; return; } @@ -1336,7 +1339,7 @@ void GroovesharkService::DeletePlaylist(int playlist_id) { void GroovesharkService::PlaylistDeleted(QNetworkReply* reply, int playlist_id) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); if (!result["success"].toBool()) { qLog(Warning) << "Grooveshark deletePlaylist failed"; return; @@ -1384,7 +1387,7 @@ void GroovesharkService::RenamePlaylist(int playlist_id) { void GroovesharkService::PlaylistRenamed(QNetworkReply* reply, int playlist_id, const QString& new_name) { reply->deleteLater(); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); if (!result["success"].toBool()) { qLog(Warning) << "Grooveshark renamePlaylist failed"; return; @@ -1411,7 +1414,7 @@ void GroovesharkService::UserFavoriteSongAdded(QNetworkReply* reply, reply->deleteLater(); app_->task_manager()->SetTaskFinished(task_id); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); if (!result["success"].toBool()) { qLog(Warning) << "Grooveshark addUserFavoriteSong failed"; return; @@ -1447,7 +1450,7 @@ void GroovesharkService::UserLibrarySongAdded(QNetworkReply* reply, reply->deleteLater(); app_->task_manager()->SetTaskFinished(task_id); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); if (!result["success"].toBool()) { qLog(Warning) << "Grooveshark addUserLibrarySongs failed"; return; @@ -1536,7 +1539,7 @@ void GroovesharkService::SongsRemovedFromFavorites(QNetworkReply* reply, app_->task_manager()->SetTaskFinished(task_id); reply->deleteLater(); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); if (!result["success"].toBool()) { qLog(Warning) << "Grooveshark removeUserFavoriteSongs failed"; return; @@ -1595,7 +1598,7 @@ void GroovesharkService::SongsRemovedFromLibrary(QNetworkReply* reply, app_->task_manager()->SetTaskFinished(task_id); reply->deleteLater(); - QVariantMap result = ExtractResult(reply); + QJsonObject result = ExtractResult(reply).object(); if (!result["success"].toBool()) { qLog(Warning) << "Grooveshark removeUserLibrarySongs failed"; return; @@ -1606,11 +1609,12 @@ void GroovesharkService::SongsRemovedFromLibrary(QNetworkReply* reply, QNetworkReply* GroovesharkService::CreateRequest(const QString& method_name, const QList& params, bool use_https) { - QVariantMap request_params; - request_params.insert("method", method_name); + QJsonDocument json_document; + QJsonObject json_request_params; + json_request_params.insert("method", QJsonValue(method_name)); - QVariantMap header; - header.insert("wsKey", kApiKey); + QJsonObject json_header; + json_header.insert("wsKey", QJsonValue(kApiKey)); if (session_id_.isEmpty()) { if (method_name != "startSession") { // It's normal to not have a session_id when calling startSession. @@ -1618,26 +1622,28 @@ QNetworkReply* GroovesharkService::CreateRequest(const QString& method_name, qLog(Warning) << "Session ID is empty: will not be added to query"; } } else { - header.insert("sessionID", session_id_); + json_header.insert("sessionID", QJsonValue(session_id_)); } - request_params.insert("header", header); + json_request_params["header"] = json_header; - QVariantMap parameters; + QJsonObject json_parameters; for (const Param& param : params) { - parameters.insert(param.first, param.second); + json_parameters.insert(param.first, QJsonValue(param.second.toString())); } - request_params.insert("parameters", parameters); + json_request_params["parameters"] = json_parameters; - QJson::Serializer serializer; - QByteArray post_params = serializer.serialize(request_params); + json_document.setObject(json_request_params); + QByteArray post_params = json_document.toBinaryData(); QUrl url(kUrl); if (use_https) { url.setScheme("https"); } - url.setQueryItems( + QUrlQuery url_query; + url_query.setQueryItems( QList>() << QPair( "sig", Utilities::HmacMd5(api_key_, post_params).toHex())); + url.setQuery(url_query); QNetworkRequest req(url); QNetworkReply* reply = network_->post(req, post_params); @@ -1673,20 +1679,24 @@ bool GroovesharkService::WaitForReply(QNetworkReply* reply) { return true; } -QVariantMap GroovesharkService::ExtractResult(QNetworkReply* reply) { - QJson::Parser parser; - bool ok; - QVariantMap result = parser.parse(reply, &ok).toMap(); - if (!ok) { +QJsonDocument GroovesharkService::ExtractResult(QNetworkReply* reply) { + reply->deleteLater(); + + QJsonParseError error; + QJsonDocument json_document = QJsonDocument::fromJson(reply->readAll(), &error); + if (error.error != QJsonParseError::NoError) { qLog(Error) << "Error while parsing Grooveshark result"; } - QVariantList errors = result["errors"].toList(); - QVariantList::iterator it; - for (it = errors.begin(); it != errors.end(); ++it) { - QVariantMap error = (*it).toMap(); - qLog(Error) << "Grooveshark error: (" << error["code"].toInt() << ") " - << error["message"].toString(); - switch (error["code"].toInt()) { + + QJsonObject json_object = json_document.object(); + QJsonArray json_errors = json_object["errors"].toArray(); + + for(const QJsonValue & error : json_errors) { + QJsonObject json_error = error.toObject(); + + qLog(Error) << "Grooveshark error: (" << json_error["code"].toInt() << ") " + << json_error["message"].toString(); + switch (json_error["code"].toInt()) { case 100: // User auth required case 102: // User premium required case 300: // Session required @@ -1697,7 +1707,10 @@ QVariantMap GroovesharkService::ExtractResult(QNetworkReply* reply) { break; } } - return result["result"].toMap(); + + QJsonDocument doc_ret; + doc_ret.setObject(json_object["result"].toObject()); + return doc_ret; } namespace { @@ -1709,24 +1722,26 @@ bool CompareSongs(const QVariant& song1, const QVariant& song2) { if (song1_sort == song2_sort) { // Favorite songs have a "TSFavorited" and (currently) no "Sort" field return song1_map["TSFavorited"].toString() < - song2_map["TSFavorited"].toString(); + song2_map["TSFavorited"].toString(); } return song1_sort < song2_sort; } -} // namespace +} // namespace -SongList GroovesharkService::ExtractSongs(const QVariantMap& result) { - QVariantList result_songs = result["songs"].toList(); +SongList GroovesharkService::ExtractSongs(const QJsonObject& result) { + QVariantList result_songs = result["songs"].toArray().toVariantList(); + // We don't automatically sort QJsonValue because it doesn't implement swap and so I think it simplier like that + // https://bugreports.qt.io/browse/QTBUG-44944 qStableSort(result_songs.begin(), result_songs.end(), CompareSongs); SongList songs; for (int i = 0; i < result_songs.size(); ++i) { QVariantMap result_song = result_songs[i].toMap(); - songs << ExtractSong(result_song); + songs << ExtractSong(QJsonObject::fromVariantMap(result_song)); } return songs; } -Song GroovesharkService::ExtractSong(const QVariantMap& result_song) { +Song GroovesharkService::ExtractSong(const QJsonObject& result_song) { Song song; if (!result_song.isEmpty()) { int song_id = result_song["SongID"].toInt(); @@ -1765,11 +1780,11 @@ Song GroovesharkService::ExtractSong(const QVariantMap& result_song) { return song; } -QList GroovesharkService::ExtractSongsIds(const QVariantMap& result) { - QVariantList result_songs = result["songs"].toList(); +QList GroovesharkService::ExtractSongsIds(const QJsonObject& result) { + QJsonArray result_songs = result["songs"].toArray(); QList songs_ids; for (int i = 0; i < result_songs.size(); ++i) { - QVariantMap result_song = result_songs[i].toMap(); + QJsonObject result_song = result_songs[i].toObject(); int song_id = result_song["SongID"].toInt(); songs_ids << song_id; } @@ -1798,16 +1813,16 @@ int GroovesharkService::ExtractSongId(const QUrl& url) { } QList GroovesharkService::ExtractPlaylistInfo( - const QVariantMap& result) { - QVariantList playlists_qvariant = result["playlists"].toList(); + const QJsonObject result) { + QJsonArray json_playlists = result["playlists"].toArray(); QList playlists; // Get playlists info - for (const QVariant& playlist_qvariant : playlists_qvariant) { - QVariantMap playlist = playlist_qvariant.toMap(); - int playlist_id = playlist["PlaylistID"].toInt(); - QString playlist_name = playlist["PlaylistName"].toString(); + for (const QJsonValue& playlist : json_playlists) { + QJsonObject json_playlist = playlist.toObject(); + int playlist_id = json_playlist["PlaylistID"].toInt(); + QString playlist_name = json_playlist["PlaylistName"].toString(); playlists << PlaylistInfo(playlist_id, playlist_name); } diff --git a/src/internet/grooveshark/groovesharkservice.h b/src/internet/grooveshark/groovesharkservice.h index 17c16c42f..dc946890a 100644 --- a/src/internet/grooveshark/groovesharkservice.h +++ b/src/internet/grooveshark/groovesharkservice.h @@ -106,8 +106,8 @@ class GroovesharkService : public InternetService { void GetPlaylistUrlToShare(int playlist_id); // Start autoplay for the given tag_id, fill the autoplay_state, returns a // first song to play - Song StartAutoplayTag(int tag_id, QVariantMap& autoplay_state); - Song StartAutoplay(QVariantMap& autoplay_state); + Song StartAutoplayTag(int tag_id, QVariantMap &autoplay_state); + Song StartAutoplay(QVariantMap &autoplay_state); // Get another autoplay song. autoplay_state is the autoplay_state received // from StartAutoplayTag Song GetAutoplaySong(QVariantMap& autoplay_state); @@ -232,22 +232,22 @@ class GroovesharkService : public InternetService { // seconds. Returns false if reply has timeouted bool WaitForReply(QNetworkReply* reply); // Convenient function for extracting result from reply - QVariantMap ExtractResult(QNetworkReply* reply); + QJsonDocument ExtractResult(QNetworkReply* reply); // Convenient function for extracting songs from grooveshark result. result // should be the "result" field of most Grooveshark replies - SongList ExtractSongs(const QVariantMap& result); + SongList ExtractSongs(const QJsonObject &result); // Convenient function for extracting song from grooveshark result. // result_song should be the song field ('song', 'nextSong', ...) of the // Grooveshark reply - Song ExtractSong(const QVariantMap& result_song); + Song ExtractSong(const QJsonObject &result_song); // Convenient functions for extracting Grooveshark songs ids - QList ExtractSongsIds(const QVariantMap& result); + QList ExtractSongsIds(const QJsonObject &result); QList ExtractSongsIds(const QList& urls); int ExtractSongId( const QUrl& url); // Returns 0 if url is not a Grooveshark url // Convenient function for extracting basic playlist info (only 'id' and // 'name': QStandardItem still need to be created), and sort them by name - QList ExtractPlaylistInfo(const QVariantMap& result); + QList ExtractPlaylistInfo(const QJsonObject result); void ResetSessionId(); @@ -308,7 +308,7 @@ class GroovesharkService : public InternetService { QString password_; // In fact, password's md5 hash QString user_id_; QString session_id_; - QMap country_; + QVariantMap country_; // The last artists and songs ids th users has listened to. Used for autoplay QList last_artists_ids_; QList last_songs_ids_; diff --git a/src/internet/icecast/icecastbackend.cpp b/src/internet/icecast/icecastbackend.cpp index 35daa3c24..2c9f1bbe7 100644 --- a/src/internet/icecast/icecastbackend.cpp +++ b/src/internet/icecast/icecastbackend.cpp @@ -43,7 +43,8 @@ QStringList IcecastBackend::GetGenresAlphabetical(const QString& filter) { QString sql = QString("SELECT DISTINCT genre FROM %1 %2 ORDER BY genre") .arg(kTableName, where); - QSqlQuery q(sql, db); + QSqlQuery q(db); + q.prepare(sql); if (!filter.isEmpty()) { q.bindValue(":filter", QString("%" + filter + "%")); } @@ -69,7 +70,8 @@ QStringList IcecastBackend::GetGenresByPopularity(const QString& filter) { " %2" " GROUP BY genre" " ORDER BY count DESC").arg(kTableName, where); - QSqlQuery q(sql, db); + QSqlQuery q(db); + q.prepare(sql); if (!filter.isEmpty()) { q.bindValue(":filter", QString("%" + filter + "%")); } @@ -109,7 +111,8 @@ IcecastBackend::StationList IcecastBackend::GetStations(const QString& filter, if (!where_clauses.isEmpty()) { sql += " WHERE " + where_clauses.join(" AND "); } - QSqlQuery q(sql, db); + QSqlQuery q(db); + q.prepare(sql); for (const QString& value : bound_items) { q.addBindValue(value); } @@ -134,7 +137,8 @@ IcecastBackend::StationList IcecastBackend::GetStations(const QString& filter, bool IcecastBackend::IsEmpty() { QMutexLocker l(db_->Mutex()); QSqlDatabase db = db_->Connect(); - QSqlQuery q(QString("SELECT ROWID FROM %1 LIMIT 1").arg(kTableName), db); + QSqlQuery q(db); + q.prepare(QString("SELECT ROWID FROM %1 LIMIT 1").arg(kTableName)); q.exec(); return !q.next(); } @@ -146,17 +150,16 @@ void IcecastBackend::ClearAndAddStations(const StationList& stations) { ScopedTransaction t(&db); // Remove all existing items - QSqlQuery q(QString("DELETE FROM %1").arg(kTableName), db); + QSqlQuery q(db); + q.prepare(QString("DELETE FROM %1").arg(kTableName)); q.exec(); if (db_->CheckErrors(q)) return; - q = QSqlQuery( - QString( + q.prepare(QString( "INSERT INTO %1 (name, url, mime_type, bitrate," " channels, samplerate, genre)" " VALUES (:name, :url, :mime_type, :bitrate," - " :channels, :samplerate, :genre)").arg(kTableName), - db); + " :channels, :samplerate, :genre)").arg(kTableName)); // Add these ones for (const Station& station : stations) { diff --git a/src/internet/icecast/icecastmodel.cpp b/src/internet/icecast/icecastmodel.cpp index 98ef34493..79d4c99fd 100644 --- a/src/internet/icecast/icecastmodel.cpp +++ b/src/internet/icecast/icecastmodel.cpp @@ -46,7 +46,8 @@ void IcecastModel::Reset() { LazyPopulate(root_); - reset(); + beginResetModel(); + endResetModel(); } void IcecastModel::LazyPopulate(IcecastItem* parent) { diff --git a/src/internet/jamendo/jamendodynamicplaylist.cpp b/src/internet/jamendo/jamendodynamicplaylist.cpp index cfcfb16a8..4424a978a 100644 --- a/src/internet/jamendo/jamendodynamicplaylist.cpp +++ b/src/internet/jamendo/jamendodynamicplaylist.cpp @@ -21,9 +21,8 @@ #include "jamendodynamicplaylist.h" #include -#include -#include #include +#include #include "core/logging.h" #include "core/network.h" @@ -119,35 +118,36 @@ QString JamendoDynamicPlaylist::OrderSpec(OrderBy by, OrderDirection dir) { void JamendoDynamicPlaylist::Fetch() { QUrl url(kUrl); - url.addQueryItem("pn", QString::number(current_page_++)); - url.addQueryItem("n", QString::number(kPageSize)); - url.addQueryItem("order", OrderSpec(order_by_, order_direction_)); + QUrlQuery url_query; + url_query.addQueryItem("pn", QString::number(current_page_++)); + url_query.addQueryItem("n", QString::number(kPageSize)); + url_query.addQueryItem("order", OrderSpec(order_by_, order_direction_)); + url.setQuery(url_query); + // TODO // We have to use QHttp here because there's no way to disable Keep-Alive // with QNetworkManager. - QHttpRequestHeader header( - "GET", QString(url.encodedPath() + "?" + url.encodedQuery())); - header.setValue("Host", url.encodedHost()); - - QHttp http(url.host()); - http.request(header); + QNetworkAccessManager network(this); + QNetworkRequest req(url); + QNetworkReply *reply = network.get(req); // Wait for the reply { QEventLoop event_loop; - connect(&http, SIGNAL(requestFinished(int, bool)), &event_loop, - SLOT(quit())); + connect(reply, SIGNAL(finished()), &event_loop, SLOT(quit())); event_loop.exec(); } - if (http.error() != QHttp::NoError) { - qLog(Warning) << "HTTP error returned from Jamendo:" << http.errorString() + reply->deleteLater(); + + if (reply->error() != QNetworkReply::NoError) { + qLog(Warning) << "HTTP error returned from Jamendo:" << reply->errorString() << ", url:" << url.toString(); return; } // The reply will contain one track ID per line - QStringList lines = QString::fromAscii(http.readAll()).split('\n'); + QStringList lines = QString::fromLatin1(reply->readAll()).split('\n'); // Get the songs from the database SongList songs = backend_->GetSongsByForeignId( diff --git a/src/internet/jamendo/jamendoservice.cpp b/src/internet/jamendo/jamendoservice.cpp index d68662e1d..6fba45482 100644 --- a/src/internet/jamendo/jamendoservice.cpp +++ b/src/internet/jamendo/jamendoservice.cpp @@ -289,9 +289,9 @@ void JamendoService::InsertTrackIds(const TrackIdList& ids) const { ScopedTransaction t(&db); - QSqlQuery insert(QString("INSERT INTO %1 (%2) VALUES (:id)") - .arg(kTrackIdsTable, kTrackIdsColumn), - db); + QSqlQuery insert(db); + insert.prepare(QString("INSERT INTO %1 (%2) VALUES (:id)") + .arg(kTrackIdsTable, kTrackIdsColumn)); for (int id : ids) { insert.bindValue(":id", id); diff --git a/src/internet/magnatune/magnatunedownloaddialog.cpp b/src/internet/magnatune/magnatunedownloaddialog.cpp index c502a0682..12957913b 100644 --- a/src/internet/magnatune/magnatunedownloaddialog.cpp +++ b/src/internet/magnatune/magnatunedownloaddialog.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "magnatuneservice.h" #include "internet/core/internetmodel.h" @@ -49,8 +50,8 @@ MagnatuneDownloadDialog::MagnatuneDownloadDialog(MagnatuneService* service, current_reply_(nullptr), next_row_(0) { ui_->setupUi(this); - ui_->albums->header()->setResizeMode(QHeaderView::ResizeToContents); - ui_->albums->header()->setResizeMode(1, QHeaderView::Fixed); + ui_->albums->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + ui_->albums->header()->setSectionResizeMode(1, QHeaderView::Fixed); ui_->albums->header()->resizeSection(1, 150); ui_->albums->setItemDelegateForColumn(1, new ProgressItemDelegate(this)); @@ -126,8 +127,10 @@ void MagnatuneDownloadDialog::DownloadNext() { QUrl url(MagnatuneService::kDownloadUrl); url.setUserName(service_->username()); url.setPassword(service_->password()); - url.addQueryItem("id", MagnatuneService::kPartnerId); - url.addQueryItem("sku", sku); + + QUrlQuery url_query; + url_query.addQueryItem("id", MagnatuneService::kPartnerId); + url_query.addQueryItem("sku", sku); current_reply_ = network_->get(QNetworkRequest(url)); diff --git a/src/internet/magnatune/magnatuneservice.cpp b/src/internet/magnatune/magnatuneservice.cpp index 7206e8808..2c7f1764b 100644 --- a/src/internet/magnatune/magnatuneservice.cpp +++ b/src/internet/magnatune/magnatuneservice.cpp @@ -227,7 +227,7 @@ Song MagnatuneService::ReadTrack(QXmlStreamReader& reader) { if (name == "url") { QUrl url; // Magnatune's URLs are already encoded - url.setEncodedUrl(value.toLocal8Bit()); + url.setUrl(value.toLocal8Bit()); url.setScheme("magnatune"); song.set_url(url); } diff --git a/src/internet/podcasts/itunessearchpage.cpp b/src/internet/podcasts/itunessearchpage.cpp index a17005f95..dccfebded 100644 --- a/src/internet/podcasts/itunessearchpage.cpp +++ b/src/internet/podcasts/itunessearchpage.cpp @@ -19,9 +19,13 @@ #include "itunessearchpage.h" -#include #include #include +#include +#include +#include +#include +#include #include "core/closure.h" #include "core/network.h" @@ -47,7 +51,9 @@ void ITunesSearchPage::SearchClicked() { emit Busy(true); QUrl url(QUrl::fromEncoded(kUrlBase)); - url.addQueryItem("term", ui_->query->text()); + QUrlQuery url_query; + url_query.addQueryItem("term", ui_->query->text()); + url.setQuery(url_query); QNetworkReply* reply = network_->get(QNetworkRequest(url)); NewClosure(reply, SIGNAL(finished()), this, @@ -67,37 +73,38 @@ void ITunesSearchPage::SearchFinished(QNetworkReply* reply) { return; } - QJson::Parser parser; - QVariant data = parser.parse(reply); + QJsonParseError error; + QJsonDocument json_document = QJsonDocument::fromJson(reply->readAll(), &error); - // Was it valid JSON? - if (data.isNull()) { + if (error.error != QJsonParseError::NoError) { QMessageBox::warning( this, tr("Failed to fetch podcasts"), tr("There was a problem parsing the response from the iTunes Store")); return; } + QJsonObject json_data = json_document.object(); + // Was there an error message in the JSON? - if (data.toMap().contains("errorMessage")) { + if (!json_data["errorMessage"].isUndefined()) { QMessageBox::warning(this, tr("Failed to fetch podcasts"), - data.toMap()["errorMessage"].toString()); + json_data["errorMessage"].toString()); return; } - for (const QVariant& result_variant : data.toMap()["results"].toList()) { - QVariantMap result(result_variant.toMap()); - if (result["kind"].toString() != "podcast") { + for (const QJsonValue& result : json_data["results"].toArray()) { + QJsonObject json_result = result.toObject(); + if (json_result["kind"].toString() != "podcast") { continue; } Podcast podcast; - podcast.set_author(result["artistName"].toString()); - podcast.set_title(result["trackName"].toString()); - podcast.set_url(result["feedUrl"].toUrl()); - podcast.set_link(result["trackViewUrl"].toUrl()); - podcast.set_image_url_small(QUrl(result["artworkUrl30"].toString())); - podcast.set_image_url_large(QUrl(result["artworkUrl100"].toString())); + podcast.set_author(json_result["artistName"].toString()); + podcast.set_title(json_result["trackName"].toString()); + podcast.set_url(QUrl(json_result["feedUrl"].toString())); + podcast.set_link(QUrl(json_result["trackViewUrl"].toString())); + podcast.set_image_url_small(QUrl(json_result["artworkUrl30"].toString())); + podcast.set_image_url_large(QUrl(json_result["artworkUrl100"].toString())); model()->appendRow(model()->CreatePodcastItem(podcast)); } diff --git a/src/internet/podcasts/podcastbackend.cpp b/src/internet/podcasts/podcastbackend.cpp index c6657586e..c37bb701c 100644 --- a/src/internet/podcasts/podcastbackend.cpp +++ b/src/internet/podcasts/podcastbackend.cpp @@ -47,11 +47,11 @@ void PodcastBackend::Subscribe(Podcast* podcast) { ScopedTransaction t(&db); // Insert the podcast. - QSqlQuery q("INSERT INTO podcasts (" + Podcast::kColumnSpec + + QSqlQuery q(db); + q.prepare("INSERT INTO podcasts (" + Podcast::kColumnSpec + ")" " VALUES (" + - Podcast::kBindSpec + ")", - db); + Podcast::kBindSpec + ")"); podcast->BindToQuery(&q); q.exec(); @@ -86,13 +86,14 @@ void PodcastBackend::Unsubscribe(const Podcast& podcast) { ScopedTransaction t(&db); // Remove the podcast. - QSqlQuery q("DELETE FROM podcasts WHERE ROWID = :id", db); + QSqlQuery q(db); + q.prepare("DELETE FROM podcasts WHERE ROWID = :id"); q.bindValue(":id", podcast.database_id()); q.exec(); if (db_->CheckErrors(q)) return; // Remove all episodes in the podcast - q = QSqlQuery("DELETE FROM podcast_episodes WHERE podcast_id = :id", db); + q.prepare("DELETE FROM podcast_episodes WHERE podcast_id = :id"); q.bindValue(":id", podcast.database_id()); q.exec(); if (db_->CheckErrors(q)) return; @@ -104,11 +105,11 @@ void PodcastBackend::Unsubscribe(const Podcast& podcast) { void PodcastBackend::AddEpisodes(PodcastEpisodeList* episodes, QSqlDatabase* db) { - QSqlQuery q("INSERT INTO podcast_episodes (" + PodcastEpisode::kColumnSpec + + QSqlQuery q(*db); + q.prepare("INSERT INTO podcast_episodes (" + PodcastEpisode::kColumnSpec + ")" " VALUES (" + - PodcastEpisode::kBindSpec + ")", - *db); + PodcastEpisode::kBindSpec + ")"); for (auto it = episodes->begin(); it != episodes->end(); ++it) { it->BindToQuery(&q); @@ -136,14 +137,13 @@ void PodcastBackend::UpdateEpisodes(const PodcastEpisodeList& episodes) { QSqlDatabase db(db_->Connect()); ScopedTransaction t(&db); - QSqlQuery q( - "UPDATE podcast_episodes" + QSqlQuery q(db); + q.prepare("UPDATE podcast_episodes" " SET listened = :listened," " listened_date = :listened_date," " downloaded = :downloaded," " local_url = :local_url" - " WHERE ROWID = :id", - db); + " WHERE ROWID = :id"); for (const PodcastEpisode& episode : episodes) { q.bindValue(":listened", episode.listened()); @@ -166,7 +166,8 @@ PodcastList PodcastBackend::GetAllSubscriptions() { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q("SELECT ROWID, " + Podcast::kColumnSpec + " FROM podcasts", db); + QSqlQuery q(db); + q.prepare("SELECT ROWID, " + Podcast::kColumnSpec + " FROM podcasts"); q.exec(); if (db_->CheckErrors(q)) return ret; @@ -185,10 +186,10 @@ Podcast PodcastBackend::GetSubscriptionById(int id) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q("SELECT ROWID, " + Podcast::kColumnSpec + + QSqlQuery q(db); + q.prepare("SELECT ROWID, " + Podcast::kColumnSpec + " FROM podcasts" - " WHERE ROWID = :id", - db); + " WHERE ROWID = :id"); q.bindValue(":id", id); q.exec(); if (!db_->CheckErrors(q) && q.next()) { @@ -204,10 +205,10 @@ Podcast PodcastBackend::GetSubscriptionByUrl(const QUrl& url) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q("SELECT ROWID, " + Podcast::kColumnSpec + + QSqlQuery q(db); + q.prepare("SELECT ROWID, " + Podcast::kColumnSpec + " FROM podcasts" - " WHERE url = :url", - db); + " WHERE url = :url"); q.bindValue(":url", url.toEncoded()); q.exec(); if (!db_->CheckErrors(q) && q.next()) { @@ -223,11 +224,11 @@ PodcastEpisodeList PodcastBackend::GetEpisodes(int podcast_id) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q("SELECT ROWID, " + PodcastEpisode::kColumnSpec + + QSqlQuery q(db); + q.prepare("SELECT ROWID, " + PodcastEpisode::kColumnSpec + " FROM podcast_episodes" " WHERE podcast_id = :id" - " ORDER BY publication_date DESC", - db); + " ORDER BY publication_date DESC"); q.bindValue(":db", podcast_id); q.exec(); if (db_->CheckErrors(q)) return ret; @@ -247,10 +248,10 @@ PodcastEpisode PodcastBackend::GetEpisodeById(int id) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q("SELECT ROWID, " + PodcastEpisode::kColumnSpec + + QSqlQuery q(db); + q.prepare("SELECT ROWID, " + PodcastEpisode::kColumnSpec + " FROM podcast_episodes" - " WHERE ROWID = :id", - db); + " WHERE ROWID = :id"); q.bindValue(":db", id); q.exec(); if (!db_->CheckErrors(q) && q.next()) { @@ -266,10 +267,10 @@ PodcastEpisode PodcastBackend::GetEpisodeByUrl(const QUrl& url) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q("SELECT ROWID, " + PodcastEpisode::kColumnSpec + + QSqlQuery q(db); + q.prepare("SELECT ROWID, " + PodcastEpisode::kColumnSpec + " FROM podcast_episodes" - " WHERE url = :url", - db); + " WHERE url = :url"); q.bindValue(":url", url.toEncoded()); q.exec(); if (!db_->CheckErrors(q) && q.next()) { @@ -285,11 +286,11 @@ PodcastEpisode PodcastBackend::GetEpisodeByUrlOrLocalUrl(const QUrl& url) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q("SELECT ROWID, " + PodcastEpisode::kColumnSpec + + QSqlQuery q(db); + q.prepare("SELECT ROWID, " + PodcastEpisode::kColumnSpec + " FROM podcast_episodes" " WHERE url = :url" - " OR local_url = :url", - db); + " OR local_url = :url"); q.bindValue(":url", url.toEncoded()); q.exec(); if (!db_->CheckErrors(q) && q.next()) { @@ -306,11 +307,11 @@ PodcastEpisodeList PodcastBackend::GetOldDownloadedEpisodes( QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q("SELECT ROWID, " + PodcastEpisode::kColumnSpec + + QSqlQuery q(db); + q.prepare("SELECT ROWID, " + PodcastEpisode::kColumnSpec + " FROM podcast_episodes" " WHERE downloaded = 'true'" - " AND listened_date <= :max_listened_date", - db); + " AND listened_date <= :max_listened_date"); q.bindValue(":max_listened_date", max_listened_date.toTime_t()); q.exec(); if (db_->CheckErrors(q)) return ret; @@ -330,12 +331,12 @@ PodcastEpisode PodcastBackend::GetOldestDownloadedListenedEpisode() { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q("SELECT ROWID, " + PodcastEpisode::kColumnSpec + + QSqlQuery q(db); + q.prepare("SELECT ROWID, " + PodcastEpisode::kColumnSpec + " FROM podcast_episodes" " WHERE downloaded = 'true'" " AND listened = 'true'" - " ORDER BY listened_date ASC", - db); + " ORDER BY listened_date ASC"); q.exec(); if (db_->CheckErrors(q)) return ret; q.next(); @@ -350,11 +351,11 @@ PodcastEpisodeList PodcastBackend::GetNewDownloadedEpisodes() { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q("SELECT ROWID, " + PodcastEpisode::kColumnSpec + + QSqlQuery q(db); + q.prepare("SELECT ROWID, " + PodcastEpisode::kColumnSpec + " FROM podcast_episodes" " WHERE downloaded = 'true'" - " AND listened = 'false'", - db); + " AND listened = 'false'"); q.exec(); if (db_->CheckErrors(q)) return ret; diff --git a/src/internet/podcasts/podcastparser.cpp b/src/internet/podcasts/podcastparser.cpp index 0476d5e9b..3e163448e 100644 --- a/src/internet/podcasts/podcastparser.cpp +++ b/src/internet/podcasts/podcastparser.cpp @@ -114,7 +114,7 @@ void PodcastParser::ParseChannel(QXmlStreamReader* reader, Podcast* ret) const { if (name == "title") { ret->set_title(reader->readElementText()); } else if (name == "link" && lower_namespace.isEmpty()) { - ret->set_link(QUrl::fromEncoded(reader->readElementText().toAscii())); + ret->set_link(QUrl::fromEncoded(reader->readElementText().toLatin1())); } else if (name == "description") { ret->set_description(reader->readElementText()); } else if (name == "owner" && lower_namespace == kItunesNamespace) { @@ -126,7 +126,7 @@ void PodcastParser::ParseChannel(QXmlStreamReader* reader, Podcast* ret) const { } else if (name == "link" && lower_namespace == kAtomNamespace && ret->url().isEmpty() && reader->attributes().value("rel") == "self") { - ret->set_url(QUrl::fromEncoded(reader->readElementText().toAscii())); + ret->set_url(QUrl::fromEncoded(reader->readElementText().toLatin1())); } else if (name == "item") { ParseItem(reader, ret); } else { @@ -152,7 +152,7 @@ void PodcastParser::ParseImage(QXmlStreamReader* reader, Podcast* ret) const { const QStringRef name = reader->name(); if (name == "url") { ret->set_image_url_large( - QUrl::fromEncoded(reader->readElementText().toAscii())); + QUrl::fromEncoded(reader->readElementText().toLatin1())); } else { Utilities::ConsumeCurrentElement(reader); } @@ -231,7 +231,7 @@ void PodcastParser::ParseItem(QXmlStreamReader* reader, Podcast* ret) const { const QString type = reader->attributes().value("type").toString(); if (type.startsWith("audio/") || type.startsWith("x-audio/")) { episode.set_url(QUrl::fromEncoded( - reader->attributes().value("url").toString().toAscii())); + reader->attributes().value("url").toString().toLatin1())); } Utilities::ConsumeCurrentElement(reader); } else if (name == "author" && lower_namespace == kItunesNamespace) { @@ -293,9 +293,9 @@ void PodcastParser::ParseOutline(QXmlStreamReader* reader, podcast.set_description(attributes.value("description").toString()); podcast.set_title(attributes.value("text").toString()); podcast.set_image_url_large(QUrl::fromEncoded( - attributes.value("imageHref").toString().toAscii())); + attributes.value("imageHref").toString().toLatin1())); podcast.set_url(QUrl::fromEncoded( - attributes.value("xmlUrl").toString().toAscii())); + attributes.value("xmlUrl").toString().toLatin1())); ret->feeds.append(podcast); // Consume any children and the EndElement. diff --git a/src/internet/podcasts/podcasturlloader.cpp b/src/internet/podcasts/podcasturlloader.cpp index b6509e4ad..c08265fd6 100644 --- a/src/internet/podcasts/podcasturlloader.cpp +++ b/src/internet/podcasts/podcasturlloader.cpp @@ -20,6 +20,7 @@ #include "podcasturlloader.h" #include +#include #include "podcastparser.h" #include "core/closure.h" @@ -73,14 +74,15 @@ QUrl PodcastUrlLoader::FixPodcastUrl(const QString& url_text) { QUrl PodcastUrlLoader::FixPodcastUrl(const QUrl& url_orig) { QUrl url(url_orig); + QUrlQuery url_query(url); // Replace schemes if (url.scheme().isEmpty() || url.scheme() == "feed" || url.scheme() == "itpc" || url.scheme() == "itms") { url.setScheme("http"); } else if (url.scheme() == "zune" && url.host() == "subscribe" && - !url.queryItems().isEmpty()) { - url = QUrl(url.queryItems()[0].second); + !url_query.queryItems().isEmpty()) { + url = QUrl(url_query.queryItems()[0].second); } return url; diff --git a/src/internet/soundcloud/soundcloudservice.cpp b/src/internet/soundcloud/soundcloudservice.cpp index 4883afa96..955f723d1 100644 --- a/src/internet/soundcloud/soundcloudservice.cpp +++ b/src/internet/soundcloud/soundcloudservice.cpp @@ -25,9 +25,11 @@ #include #include #include - -#include -#include +#include +#include +#include +#include +#include #include "internet/core/internetmodel.h" #include "internet/core/oauthenticator.h" @@ -217,7 +219,7 @@ void SoundCloudService::RetrieveUserData() { void SoundCloudService::RetrieveUserTracks() { QList parameters; parameters << Param("oauth_token", access_token_); - QNetworkReply* reply = CreateRequest("me/tracks", parameters); + QNetworkReply* reply = CreateRequest("/me/tracks", parameters); NewClosure(reply, SIGNAL(finished()), this, SLOT(UserTracksRetrieved(QNetworkReply*)), reply); } @@ -225,7 +227,7 @@ void SoundCloudService::RetrieveUserTracks() { void SoundCloudService::UserTracksRetrieved(QNetworkReply* reply) { reply->deleteLater(); - SongList songs = ExtractSongs(ExtractResult(reply)); + SongList songs = ExtractSongs(ExtractResult(reply).array()); // Fill results list for (const Song& song : songs) { QStandardItem* child = CreateSongItem(song); @@ -236,7 +238,7 @@ void SoundCloudService::UserTracksRetrieved(QNetworkReply* reply) { void SoundCloudService::RetrieveUserActivities() { QList parameters; parameters << Param("oauth_token", access_token_); - QNetworkReply* reply = CreateRequest("me/activities", parameters); + QNetworkReply* reply = CreateRequest("/me/activities", parameters); NewClosure(reply, SIGNAL(finished()), this, SLOT(UserActivitiesRetrieved(QNetworkReply*)), reply); } @@ -244,7 +246,7 @@ void SoundCloudService::RetrieveUserActivities() { void SoundCloudService::UserActivitiesRetrieved(QNetworkReply* reply) { reply->deleteLater(); - QList activities = ExtractActivities(ExtractResult(reply)); + QList activities = ExtractActivities(ExtractResult(reply).object()); // Fill results list for (QStandardItem* activity : activities) { user_activities_->appendRow(activity); @@ -254,7 +256,7 @@ void SoundCloudService::UserActivitiesRetrieved(QNetworkReply* reply) { void SoundCloudService::RetrieveUserPlaylists() { QList parameters; parameters << Param("oauth_token", access_token_); - QNetworkReply* reply = CreateRequest("me/playlists", parameters); + QNetworkReply* reply = CreateRequest("/me/playlists", parameters); NewClosure(reply, SIGNAL(finished()), this, SLOT(UserPlaylistsRetrieved(QNetworkReply*)), reply); } @@ -262,12 +264,12 @@ void SoundCloudService::RetrieveUserPlaylists() { void SoundCloudService::UserPlaylistsRetrieved(QNetworkReply* reply) { reply->deleteLater(); - QList playlists = ExtractResult(reply).toList(); - for (const QVariant& playlist : playlists) { - QMap playlist_map = playlist.toMap(); + QJsonArray json_playlists = ExtractResult(reply).array(); + for (const QJsonValue& playlist : json_playlists) { + QJsonObject json_playlist = playlist.toObject(); - QStandardItem* playlist_item = CreatePlaylistItem(playlist_map["title"].toString()); - SongList songs = ExtractSongs(playlist_map["tracks"]); + QStandardItem* playlist_item = CreatePlaylistItem(json_playlist["title"].toString()); + SongList songs = ExtractSongs(json_playlist["tracks"].toArray()); for (const Song& song : songs) { playlist_item->appendRow(CreateSongItem(song)); } @@ -299,7 +301,7 @@ void SoundCloudService::DoSearch() { QList parameters; parameters << Param("q", pending_search_); - QNetworkReply* reply = CreateRequest("tracks", parameters); + QNetworkReply* reply = CreateRequest("/tracks", parameters); const int id = next_pending_search_id_++; NewClosure(reply, SIGNAL(finished()), this, SLOT(SearchFinished(QNetworkReply*, int)), reply, id); @@ -308,7 +310,7 @@ void SoundCloudService::DoSearch() { void SoundCloudService::SearchFinished(QNetworkReply* reply, int task_id) { reply->deleteLater(); - SongList songs = ExtractSongs(ExtractResult(reply)); + SongList songs = ExtractSongs(ExtractResult(reply).array()); // Fill results list for (const Song& song : songs) { QStandardItem* child = CreateSongItem(song); @@ -328,7 +330,7 @@ void SoundCloudService::ClearSearchResults() { int SoundCloudService::SimpleSearch(const QString& text) { QList parameters; parameters << Param("q", text); - QNetworkReply* reply = CreateRequest("tracks", parameters); + QNetworkReply* reply = CreateRequest("/tracks", parameters); const int id = next_pending_search_id_++; NewClosure(reply, SIGNAL(finished()), this, SLOT(SimpleSearchFinished(QNetworkReply*, int)), reply, id); @@ -338,7 +340,7 @@ int SoundCloudService::SimpleSearch(const QString& text) { void SoundCloudService::SimpleSearchFinished(QNetworkReply* reply, int id) { reply->deleteLater(); - SongList songs = ExtractSongs(ExtractResult(reply)); + SongList songs = ExtractSongs(ExtractResult(reply).array()); emit SimpleSearchResults(id, songs); } @@ -372,12 +374,15 @@ QNetworkReply* SoundCloudService::CreateRequest(const QString& ressource_name, QUrl url(kUrl); url.setPath(ressource_name); + QUrlQuery url_query; - url.addQueryItem("client_id", kApiClientId); + url_query.addQueryItem("client_id", kApiClientId); for (const Param& param : params) { - url.addQueryItem(param.first, param.second); + url_query.addQueryItem(param.first, param.second); } + url.setQuery(url_query); + qLog(Debug) << "Request Url: " << url.toEncoded(); QNetworkRequest req(url); @@ -386,7 +391,7 @@ QNetworkReply* SoundCloudService::CreateRequest(const QString& ressource_name, return reply; } -QVariant SoundCloudService::ExtractResult(QNetworkReply* reply) { +QJsonDocument SoundCloudService::ExtractResult(QNetworkReply* reply) { if (reply->error() != QNetworkReply::NoError) { qLog(Error) << "Error when retrieving SoundCloud results:" << reply->errorString() << QString(" (%1)").arg(reply->error()); @@ -396,16 +401,16 @@ QVariant SoundCloudService::ExtractResult(QNetworkReply* reply) { reply->error() == QNetworkReply::AuthenticationRequiredError) { // In case of access denied errors (invalid token?) logout Logout(); - return QVariant(); + return QJsonDocument(); } } - QJson::Parser parser; - bool ok; - QVariant result = parser.parse(reply, &ok); - if (!ok) { + QJsonParseError error; + QJsonDocument document = QJsonDocument::fromJson(reply->readAll(), &error); + if (error.error != QJsonParseError::NoError) { qLog(Error) << "Error while parsing SoundCloud result"; } - return result; + + return document; } void SoundCloudService::RetrievePlaylist(int playlist_id, @@ -416,7 +421,7 @@ void SoundCloudService::RetrievePlaylist(int playlist_id, QList parameters; parameters << Param("oauth_token", access_token_); QNetworkReply* reply = - CreateRequest("playlists/" + QString::number(playlist_id), parameters); + CreateRequest("/playlists/" + QString::number(playlist_id), parameters); NewClosure(reply, SIGNAL(finished()), this, SLOT(PlaylistRetrieved(QNetworkReply*, int)), reply, request_id); } @@ -425,42 +430,41 @@ void SoundCloudService::PlaylistRetrieved(QNetworkReply* reply, int request_id) { if (!pending_playlists_requests_.contains(request_id)) return; PlaylistInfo playlist_info = pending_playlists_requests_.take(request_id); - QVariant res = ExtractResult(reply); - SongList songs = ExtractSongs(res.toMap()["tracks"]); + QJsonDocument res = ExtractResult(reply); + SongList songs = ExtractSongs(res.object()["tracks"].toArray()); for (const Song& song : songs) { QStandardItem* child = CreateSongItem(song); playlist_info.item_->appendRow(child); } } -QList SoundCloudService::ExtractActivities(const QVariant& result) { +QList SoundCloudService::ExtractActivities(const QJsonObject& result) { QList activities; - QVariantList q_variant_list = result.toMap()["collection"].toList(); - for (const QVariant& q : q_variant_list) { - QMap activity = q.toMap(); - const QString type = activity["type"].toString(); + QJsonArray q_list = result["collection"].toArray(); + for (const QJsonValue& q : q_list) { + QJsonObject json_activity = q.toObject(); + const QString type = json_activity["type"].toString(); if (type == "track") { - Song song = ExtractSong(activity["origin"].toMap()); + Song song = ExtractSong(json_activity["origin"].toObject()); if (song.is_valid()) { activities << CreateSongItem(song); } } else if (type == "playlist") { - QMap origin_map = activity["origin"].toMap(); + QJsonObject json_origin = json_activity["origin"].toObject(); QStandardItem* playlist_item = - CreatePlaylistItem(origin_map["title"].toString()); + CreatePlaylistItem(json_origin["title"].toString()); activities << playlist_item; - RetrievePlaylist(origin_map["id"].toInt(), playlist_item); + RetrievePlaylist(json_origin["id"].toInt(), playlist_item); } } return activities; } -SongList SoundCloudService::ExtractSongs(const QVariant& result) { +SongList SoundCloudService::ExtractSongs(const QJsonArray & result) { SongList songs; - QVariantList q_variant_list = result.toList(); - for (const QVariant& q : q_variant_list) { - Song song = ExtractSong(q.toMap()); + for (const QJsonValue& q : result) { + Song song = ExtractSong(q.toObject()); if (song.is_valid()) { songs << song; } @@ -468,14 +472,16 @@ SongList SoundCloudService::ExtractSongs(const QVariant& result) { return songs; } -Song SoundCloudService::ExtractSong(const QVariantMap& result_song) { +Song SoundCloudService::ExtractSong(const QJsonObject& result_song) { Song song; if (!result_song.isEmpty() && result_song["streamable"].toBool()) { - QUrl stream_url = result_song["stream_url"].toUrl(); - stream_url.addQueryItem("client_id", kApiClientId); + QUrl stream_url(result_song["stream_url"].toString()); + QUrlQuery stream_url_query; + stream_url_query.addQueryItem("client_id", kApiClientId); + stream_url.setQuery(stream_url_query); song.set_url(stream_url); - QString username = result_song["user"].toMap()["username"].toString(); + QString username = result_song["user"].toObject()["username"].toString(); // We don't have a real artist name, but username is the most similar thing // we have song.set_artist(username); @@ -486,7 +492,7 @@ Song SoundCloudService::ExtractSong(const QVariantMap& result_song) { QString genre = result_song["genre"].toString(); song.set_genre(genre); - float bpm = result_song["bpm"].toFloat(); + float bpm = result_song["bpm"].toDouble(); song.set_bpm(bpm); QVariant cover = result_song["artwork_url"]; diff --git a/src/internet/soundcloud/soundcloudservice.h b/src/internet/soundcloud/soundcloudservice.h index a806204b4..0063a291f 100644 --- a/src/internet/soundcloud/soundcloudservice.h +++ b/src/internet/soundcloud/soundcloudservice.h @@ -26,6 +26,7 @@ class NetworkAccessManager; class OAuthenticator; class SearchBoxWidget; +class QJsonDocument; class QMenu; class QNetworkReply; @@ -101,11 +102,11 @@ class SoundCloudService : public InternetService { QNetworkReply* CreateRequest(const QString& ressource_name, const QList>& params); // Convenient function for extracting result from reply - QVariant ExtractResult(QNetworkReply* reply); + QJsonDocument ExtractResult(QNetworkReply* reply); // Returns items directly, as activities can be playlists or songs - QList ExtractActivities(const QVariant& result); - SongList ExtractSongs(const QVariant& result); - Song ExtractSong(const QVariantMap& result_song); + QList ExtractActivities(const QJsonObject &result); + SongList ExtractSongs(const QJsonArray &result); + Song ExtractSong(const QJsonObject& result_song); QStandardItem* root_; QStandardItem* search_; diff --git a/src/internet/subsonic/subsonicservice.cpp b/src/internet/subsonic/subsonicservice.cpp index 91dc18eae..a55de21ef 100644 --- a/src/internet/subsonic/subsonicservice.cpp +++ b/src/internet/subsonic/subsonicservice.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include "core/application.h" #include "core/closure.h" @@ -209,10 +210,12 @@ void SubsonicService::Ping() { QUrl SubsonicService::BuildRequestUrl(const QString& view) const { QUrl url(working_server_ + "/rest/" + view + ".view"); - url.addQueryItem("v", kApiVersion); - url.addQueryItem("c", kApiClientName); - url.addQueryItem("u", username_); - url.addQueryItem("p", QString("enc:" + password_.toUtf8().toHex())); + QUrlQuery url_query; + url_query.addQueryItem("v", kApiVersion); + url_query.addQueryItem("c", kApiClientName); + url_query.addQueryItem("u", username_); + url_query.addQueryItem("p", QString("enc:" + password_.toUtf8().toHex())); + url.setQuery(url_query); return url; } @@ -496,9 +499,11 @@ void SubsonicLibraryScanner::OnGetAlbumFinished(QNetworkReply* reply) { void SubsonicLibraryScanner::GetAlbumList(int offset) { QUrl url = service_->BuildRequestUrl("getAlbumList2"); - url.addQueryItem("type", "alphabeticalByName"); - url.addQueryItem("size", QString::number(kAlbumChunkSize)); - url.addQueryItem("offset", QString::number(offset)); + QUrlQuery url_query; + url_query.addQueryItem("type", "alphabeticalByName"); + url_query.addQueryItem("size", QString::number(kAlbumChunkSize)); + url_query.addQueryItem("offset", QString::number(offset)); + url.setQuery(url_query); QNetworkReply* reply = service_->Send(url); NewClosure(reply, SIGNAL(finished()), this, SLOT(OnGetAlbumListFinished(QNetworkReply*, int)), reply, offset); @@ -506,7 +511,9 @@ void SubsonicLibraryScanner::GetAlbumList(int offset) { void SubsonicLibraryScanner::GetAlbum(const QString& id) { QUrl url = service_->BuildRequestUrl("getAlbum"); - url.addQueryItem("id", id); + QUrlQuery url_query; + url_query.addQueryItem("id", id); + url.setQuery(url_query); QNetworkReply* reply = service_->Send(url); NewClosure(reply, SIGNAL(finished()), this, SLOT(OnGetAlbumFinished(QNetworkReply*)), reply); diff --git a/src/internet/subsonic/subsonicurlhandler.cpp b/src/internet/subsonic/subsonicurlhandler.cpp index d133f291c..a9dcbda4a 100644 --- a/src/internet/subsonic/subsonicurlhandler.cpp +++ b/src/internet/subsonic/subsonicurlhandler.cpp @@ -17,6 +17,8 @@ along with Clementine. If not, see . */ +#include + #include "subsonicservice.h" #include "subsonicurlhandler.h" @@ -29,6 +31,8 @@ UrlHandler::LoadResult SubsonicUrlHandler::StartLoading(const QUrl& url) { return LoadResult(); QUrl newurl = service_->BuildRequestUrl("stream"); - newurl.addQueryItem("id", url.host()); + QUrlQuery url_query; + url_query.addQueryItem("id", url.host()); + newurl.setQuery(url_query); return LoadResult(url, LoadResult::TrackAvailable, newurl); } diff --git a/src/library/librarybackend.cpp b/src/library/librarybackend.cpp index 7efe0ee9b..0966346a5 100644 --- a/src/library/librarybackend.cpp +++ b/src/library/librarybackend.cpp @@ -111,8 +111,8 @@ void LibraryBackend::ChangeDirPath(int id, const QString& old_path, ScopedTransaction t(&db); // Do the dirs table - QSqlQuery q( - QString("UPDATE %1 SET path=:path WHERE ROWID=:id").arg(dirs_table_), db); + QSqlQuery q(db); + q.prepare(QString("UPDATE %1 SET path=:path WHERE ROWID=:id").arg(dirs_table_)); q.bindValue(":path", new_path); q.bindValue(":id", id); q.exec(); @@ -124,24 +124,24 @@ void LibraryBackend::ChangeDirPath(int id, const QString& old_path, const int path_len = old_url.length(); // Do the subdirs table - q = QSqlQuery(QString( + q = QSqlQuery(db); + q.prepare(QString( "UPDATE %1 SET path=:path || substr(path, %2)" " WHERE directory=:id") .arg(subdirs_table_) - .arg(path_len), - db); + .arg(path_len)); q.bindValue(":path", new_url); q.bindValue(":id", id); q.exec(); if (db_->CheckErrors(q)) return; // Do the songs table - q = QSqlQuery(QString( + q = QSqlQuery(db); + q.prepare(QString( "UPDATE %1 SET filename=:path || substr(filename, %2)" " WHERE directory=:id") .arg(songs_table_) - .arg(path_len), - db); + .arg(path_len)); q.bindValue(":path", new_url); q.bindValue(":id", id); q.exec(); @@ -156,7 +156,8 @@ DirectoryList LibraryBackend::GetAllDirectories() { DirectoryList ret; - QSqlQuery q(QString("SELECT ROWID, path FROM %1").arg(dirs_table_), db); + QSqlQuery q(db); + q.prepare(QString("SELECT ROWID, path FROM %1").arg(dirs_table_)); q.exec(); if (db_->CheckErrors(q)) return ret; @@ -177,10 +178,10 @@ SubdirectoryList LibraryBackend::SubdirsInDirectory(int id) { } SubdirectoryList LibraryBackend::SubdirsInDirectory(int id, QSqlDatabase& db) { - QSqlQuery q(QString( + QSqlQuery q(db); + q.prepare(QString( "SELECT path, mtime FROM %1" - " WHERE directory = :dir").arg(subdirs_table_), - db); + " WHERE directory = :dir").arg(subdirs_table_)); q.bindValue(":dir", id); q.exec(); if (db_->CheckErrors(q)) return SubdirectoryList(); @@ -201,9 +202,9 @@ void LibraryBackend::UpdateTotalSongCount() { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q(QString("SELECT COUNT(*) FROM %1 WHERE unavailable = 0") - .arg(songs_table_), - db); + QSqlQuery q(db); + q.prepare(QString("SELECT COUNT(*) FROM %1 WHERE unavailable = 0") + .arg(songs_table_)); q.exec(); if (db_->CheckErrors(q)) return; if (!q.next()) return; @@ -225,10 +226,10 @@ void LibraryBackend::AddDirectory(const QString& path) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q(QString( + QSqlQuery q(db); + q.prepare(QString( "INSERT INTO %1 (path, subdirs)" - " VALUES (:path, 1)").arg(dirs_table_), - db); + " VALUES (:path, 1)").arg(dirs_table_)); q.bindValue(":path", db_path); q.exec(); if (db_->CheckErrors(q)) return; @@ -250,15 +251,15 @@ void LibraryBackend::RemoveDirectory(const Directory& dir) { ScopedTransaction transaction(&db); // Delete the subdirs that were in this directory - QSqlQuery q( - QString("DELETE FROM %1 WHERE directory = :id").arg(subdirs_table_), db); + QSqlQuery q(db); + q.prepare(QString("DELETE FROM %1 WHERE directory = :id").arg(subdirs_table_)); q.bindValue(":id", dir.id); q.exec(); if (db_->CheckErrors(q)) return; // Now remove the directory itself - q = QSqlQuery(QString("DELETE FROM %1 WHERE ROWID = :id").arg(dirs_table_), - db); + q = QSqlQuery(db); + q.prepare(QString("DELETE FROM %1 WHERE ROWID = :id").arg(dirs_table_)); q.bindValue(":id", dir.id); q.exec(); if (db_->CheckErrors(q)) return; @@ -272,10 +273,10 @@ SongList LibraryBackend::FindSongsInDirectory(int id) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q( + QSqlQuery q(db); + q.prepare( QString("SELECT ROWID, " + Song::kColumnSpec + - " FROM %1 WHERE directory = :directory").arg(songs_table_), - db); + " FROM %1 WHERE directory = :directory").arg(songs_table_)); q.bindValue(":directory", id); q.exec(); if (db_->CheckErrors(q)) return SongList(); @@ -292,25 +293,22 @@ SongList LibraryBackend::FindSongsInDirectory(int id) { void LibraryBackend::AddOrUpdateSubdirs(const SubdirectoryList& subdirs) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery find_query( - QString( + QSqlQuery find_query(db); + find_query.prepare(QString( "SELECT ROWID FROM %1" - " WHERE directory = :id AND path = :path").arg(subdirs_table_), - db); - QSqlQuery add_query(QString( + " WHERE directory = :id AND path = :path").arg(subdirs_table_)); + QSqlQuery add_query(db); + add_query.prepare(QString( "INSERT INTO %1 (directory, path, mtime)" - " VALUES (:id, :path, :mtime)").arg(subdirs_table_), - db); - QSqlQuery update_query( - QString( + " VALUES (:id, :path, :mtime)").arg(subdirs_table_)); + QSqlQuery update_query(db); + update_query.prepare(QString( "UPDATE %1 SET mtime = :mtime" - " WHERE directory = :id AND path = :path").arg(subdirs_table_), - db); - QSqlQuery delete_query( - QString( + " WHERE directory = :id AND path = :path").arg(subdirs_table_)); + QSqlQuery delete_query(db); + delete_query.prepare(QString( "DELETE FROM %1" - " WHERE directory = :id AND path = :path").arg(subdirs_table_), - db); + " WHERE directory = :id AND path = :path").arg(subdirs_table_)); ScopedTransaction transaction(&db); for (const Subdirectory& subdir : subdirs) { @@ -349,25 +347,24 @@ void LibraryBackend::AddOrUpdateSongs(const SongList& songs) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery check_dir( - QString("SELECT ROWID FROM %1 WHERE ROWID = :id").arg(dirs_table_), db); - QSqlQuery add_song(QString("INSERT INTO %1 (" + Song::kColumnSpec + + QSqlQuery check_dir(db); + check_dir.prepare(QString("SELECT ROWID FROM %1 WHERE ROWID = :id").arg(dirs_table_)); + QSqlQuery add_song(db); + add_song.prepare(QString("INSERT INTO %1 (" + Song::kColumnSpec + ")" " VALUES (" + - Song::kBindSpec + ")").arg(songs_table_), - db); - QSqlQuery update_song(QString("UPDATE %1 SET " + Song::kUpdateSpec + - " WHERE ROWID = :id").arg(songs_table_), - db); - QSqlQuery add_song_fts( - QString("INSERT INTO %1 (ROWID, " + Song::kFtsColumnSpec + + Song::kBindSpec + ")").arg(songs_table_)); + QSqlQuery update_song(db); + update_song.prepare(QString("UPDATE %1 SET " + Song::kUpdateSpec + + " WHERE ROWID = :id").arg(songs_table_)); + QSqlQuery add_song_fts(db); + add_song_fts.prepare(QString("INSERT INTO %1 (ROWID, " + Song::kFtsColumnSpec + ")" " VALUES (:id, " + - Song::kFtsBindSpec + ")").arg(fts_table_), - db); - QSqlQuery update_song_fts(QString("UPDATE %1 SET " + Song::kFtsUpdateSpec + - " WHERE ROWID = :id").arg(fts_table_), - db); + Song::kFtsBindSpec + ")").arg(fts_table_)); + QSqlQuery update_song_fts(db); + update_song_fts.prepare(QString("UPDATE %1 SET " + Song::kFtsUpdateSpec + + " WHERE ROWID = :id").arg(fts_table_)); ScopedTransaction transaction(&db); @@ -440,9 +437,9 @@ void LibraryBackend::UpdateMTimesOnly(const SongList& songs) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q(QString("UPDATE %1 SET mtime = :mtime WHERE ROWID = :id") - .arg(songs_table_), - db); + QSqlQuery q(db); + q.prepare(QString("UPDATE %1 SET mtime = :mtime WHERE ROWID = :id") + .arg(songs_table_)); ScopedTransaction transaction(&db); for (const Song& song : songs) { @@ -458,10 +455,10 @@ void LibraryBackend::DeleteSongs(const SongList& songs) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery remove( - QString("DELETE FROM %1 WHERE ROWID = :id").arg(songs_table_), db); - QSqlQuery remove_fts( - QString("DELETE FROM %1 WHERE ROWID = :id").arg(fts_table_), db); + QSqlQuery remove(db); + remove.prepare(QString("DELETE FROM %1 WHERE ROWID = :id").arg(songs_table_)); + QSqlQuery remove_fts(db); + remove_fts.prepare(QString("DELETE FROM %1 WHERE ROWID = :id").arg(fts_table_)); ScopedTransaction transaction(&db); for (const Song& song : songs) { @@ -485,10 +482,10 @@ void LibraryBackend::MarkSongsUnavailable(const SongList& songs, QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery remove(QString("UPDATE %1 SET unavailable = %2 WHERE ROWID = :id") + QSqlQuery remove(db); + remove.prepare(QString("UPDATE %1 SET unavailable = %2 WHERE ROWID = :id") .arg(songs_table_) - .arg(int(unavailable)), - db); + .arg(int(unavailable))); ScopedTransaction transaction(&db); for (const Song& song : songs) { @@ -612,14 +609,14 @@ SongList LibraryBackend::GetSongsByForeignId(const QStringList& ids, QString in = ids.join(","); - QSqlQuery q( - QString( + QSqlQuery q(db); + q.prepare( + QString( "SELECT %2.ROWID, " + Song::kColumnSpec + ", %2.%3" " FROM %2, %1" " WHERE %2.%3 IN (%4) AND %1.ROWID = %2.ROWID AND unavailable = 0") - .arg(songs_table_, table, column, in), - db); + .arg(songs_table_, table, column, in)); q.exec(); if (db_->CheckErrors(q)) return SongList(); @@ -644,10 +641,10 @@ SongList LibraryBackend::GetSongsById(const QStringList& ids, QSqlDatabase& db) { QString in = ids.join(","); - QSqlQuery q(QString("SELECT ROWID, " + Song::kColumnSpec + + QSqlQuery q(db); + q.prepare(QString("SELECT ROWID, " + Song::kColumnSpec + " FROM %1" - " WHERE ROWID IN (%2)").arg(songs_table_, in), - db); + " WHERE ROWID IN (%2)").arg(songs_table_, in)); q.exec(); if (db_->CheckErrors(q)) return SongList(); @@ -722,11 +719,11 @@ void LibraryBackend::UpdateCompilations() { // in the same // directory - QSqlQuery q( + QSqlQuery q(db); + q.prepare( QString( "SELECT effective_albumartist, album, filename, sampler " - "FROM %1 WHERE unavailable = 0 ORDER BY album").arg(songs_table_), - db); + "FROM %1 WHERE unavailable = 0 ORDER BY album").arg(songs_table_)); q.exec(); if (db_->CheckErrors(q)) return; @@ -754,21 +751,21 @@ void LibraryBackend::UpdateCompilations() { } // Now mark the songs that we think are in compilations - QSqlQuery update( + QSqlQuery update(db); + update.prepare( QString( "UPDATE %1" " SET sampler = :sampler," " effective_compilation = ((compilation OR :sampler OR " "forced_compilation_on) AND NOT forced_compilation_off) + 0" - " WHERE album = :album AND unavailable = 0").arg(songs_table_), - db); - QSqlQuery find_songs( + " WHERE album = :album AND unavailable = 0").arg(songs_table_)); + QSqlQuery find_songs(db); + find_songs.prepare( QString( "SELECT ROWID, " + Song::kColumnSpec + " FROM %1" " WHERE album = :album AND sampler = :sampler AND unavailable = 0") - .arg(songs_table_), - db); + .arg(songs_table_)); SongList deleted_songs; SongList added_songs; @@ -932,7 +929,8 @@ void LibraryBackend::UpdateManualAlbumArt(const QString& artist, " WHERE album = :album AND unavailable = 0").arg(songs_table_)); if (!artist.isNull()) sql += " AND artist = :artist"; - QSqlQuery q(sql, db); + QSqlQuery q(db); + q.prepare(sql); q.bindValue(":art", art); q.bindValue(":album", album); if (!artist.isNull()) q.bindValue(":artist", artist); @@ -987,7 +985,8 @@ void LibraryBackend::ForceCompilation(const QString& album, " WHERE album = :album AND unavailable = 0").arg(songs_table_)); if (!artist.isEmpty()) sql += " AND artist = :artist"; - QSqlQuery q(sql, db); + QSqlQuery q(db); + q.prepare(sql); q.bindValue(":forced_compilation_on", on ? 1 : 0); q.bindValue(":forced_compilation_off", on ? 0 : 1); q.bindValue(":album", album); @@ -1025,7 +1024,8 @@ SongList LibraryBackend::FindSongs(const smart_playlists::Search& search) { // Run the query SongList ret; - QSqlQuery query(sql, db); + QSqlQuery query(db); + query.prepare(sql); query.exec(); if (db_->CheckErrors(query)) return ret; @@ -1052,13 +1052,13 @@ void LibraryBackend::IncrementPlayCount(int id) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q(QString( + QSqlQuery q(db); + q.prepare(QString( "UPDATE %1 SET playcount = playcount + 1," " lastplayed = :now," " score = " + QString(kNewScoreSql).arg("1.0") + - " WHERE ROWID = :id").arg(songs_table_), - db); + " WHERE ROWID = :id").arg(songs_table_)); q.bindValue(":now", QDateTime::currentDateTime().toTime_t()); q.bindValue(":id", id); q.exec(); @@ -1075,12 +1075,12 @@ void LibraryBackend::IncrementSkipCount(int id, float progress) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q(QString( + QSqlQuery q(db); + q.prepare(QString( "UPDATE %1 SET skipcount = skipcount + 1," " score = " + QString(kNewScoreSql).arg(progress) + - " WHERE ROWID = :id").arg(songs_table_), - db); + " WHERE ROWID = :id").arg(songs_table_)); q.bindValue(":id", id); q.exec(); if (db_->CheckErrors(q)) return; @@ -1095,11 +1095,11 @@ void LibraryBackend::ResetStatistics(int id) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q(QString( + QSqlQuery q(db); + q.prepare(QString( "UPDATE %1 SET playcount = 0, skipcount = 0," " lastplayed = -1, score = 0" - " WHERE ROWID = :id").arg(songs_table_), - db); + " WHERE ROWID = :id").arg(songs_table_)); q.bindValue(":id", id); q.exec(); if (db_->CheckErrors(q)) return; @@ -1128,10 +1128,10 @@ void LibraryBackend::UpdateSongsRating(const QList& id_list, id_str_list << QString::number(i); } QString ids = id_str_list.join(","); - QSqlQuery q(QString( + QSqlQuery q(db); + q.prepare(QString( "UPDATE %1 SET rating = :rating" - " WHERE ROWID IN (%2)").arg(songs_table_, ids), - db); + " WHERE ROWID IN (%2)").arg(songs_table_, ids)); q.bindValue(":rating", rating); q.exec(); if (db_->CheckErrors(q)) return; diff --git a/src/library/librarymodel.cpp b/src/library/librarymodel.cpp index 9d5e1e39f..73c92e228 100644 --- a/src/library/librarymodel.cpp +++ b/src/library/librarymodel.cpp @@ -151,7 +151,8 @@ void LibraryModel::Init(bool async) { new LibraryItem(LibraryItem::Type_LoadingIndicator, root_); loading->display_text = tr("Loading..."); loading->lazy_loaded = true; - reset(); + beginResetModel(); + endResetModel(); // Show a loading indicator in the status bar too. init_task_id_ = app_->task_manager()->StartTask(tr("Loading songs")); diff --git a/src/library/libraryquery.cpp b/src/library/libraryquery.cpp index 02177bf42..dd7bdc634 100644 --- a/src/library/libraryquery.cpp +++ b/src/library/libraryquery.cpp @@ -166,7 +166,8 @@ QSqlQuery LibraryQuery::Exec(QSqlDatabase db, const QString& songs_table, sql.replace("%fts_table_noprefix", fts_table.section('.', -1, -1)); sql.replace("%fts_table", fts_table); - query_ = QSqlQuery(sql, db); + query_ = QSqlQuery(db); + query_.prepare(sql); // Bind values for (const QVariant& value : bound_values_) { diff --git a/src/main.cpp b/src/main.cpp index eee7bbef2..4a90b0951 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -69,14 +69,14 @@ #include "tagreadermessages.pb.h" -#include "qtsingleapplication.h" -#include "qtsinglecoreapplication.h" +#include "singleapplication.h" +#include "singlecoreapplication.h" #include #include #include -#include +#include #ifdef HAVE_SPOTIFY_DOWNLOADER #include @@ -109,28 +109,18 @@ const QDBusArgument& operator>>(const QDBusArgument& arg, QImage& image); // Load sqlite plugin on windows and mac. #include -Q_IMPORT_PLUGIN(qsqlite) +Q_IMPORT_PLUGIN(QSQLiteDriverPlugin) namespace { void LoadTranslation(const QString& prefix, const QString& path, const QString& language) { -#if QT_VERSION < 0x040700 - // QTranslator::load will try to open and read "clementine" if it exists, - // without checking if it's a file first. - // This was fixed in Qt 4.7 - QFileInfo maybe_clementine_directory(path + "/clementine"); - if (maybe_clementine_directory.exists() && - !maybe_clementine_directory.isFile()) - return; -#endif QTranslator* t = new PoTranslator; if (t->load(prefix + "_" + language, path)) QCoreApplication::installTranslator(t); else delete t; - QTextCodec::setCodecForTr(QTextCodec::codecForLocale()); } void IncreaseFDLimit() { @@ -272,10 +262,10 @@ int main(int argc, char* argv[]) { } #endif - QCoreApplication::setApplicationName("Clementine"); + QCoreApplication::setApplicationName("Clementine-qt5"); QCoreApplication::setApplicationVersion(CLEMENTINE_VERSION_DISPLAY); - QCoreApplication::setOrganizationName("Clementine"); - QCoreApplication::setOrganizationDomain("clementine-player.org"); + QCoreApplication::setOrganizationName("Clementine-qt5"); + QCoreApplication::setOrganizationDomain("clementine-player-qt5.org"); // This makes us show up nicely in gnome-volume-control #if !GLIB_CHECK_VERSION(2, 36, 0) @@ -298,7 +288,7 @@ int main(int argc, char* argv[]) { // Clementine running without needing an X server. // This MUST be done before parsing the commandline options so QTextCodec // gets the right system locale for filenames. - QtSingleCoreApplication a(argc, argv); + SingleCoreApplication a(argc, argv); CheckPortable(); crash_reporting.SetApplicationPath(a.applicationFilePath()); @@ -307,16 +297,6 @@ int main(int argc, char* argv[]) { if (!options.Parse()) return 1; logging::SetLevels(options.log_levels()); - if (a.isRunning()) { - if (options.is_empty()) { - qLog(Info) - << "Clementine is already running - activating existing window"; - } - if (a.sendMessage(options.Serialize(), 5000)) { - return 0; - } - // Couldn't send the message so start anyway - } } #ifdef Q_OS_DARWIN @@ -335,7 +315,7 @@ int main(int argc, char* argv[]) { // Output the version, so when people attach log output to bug reports they // don't have to tell us which version they're using. - qLog(Info) << "Clementine" << CLEMENTINE_VERSION_DISPLAY; + qLog(Info) << "Clementine-qt5" << CLEMENTINE_VERSION_DISPLAY; // Seed the random number generators. time_t t = time(nullptr); @@ -344,7 +324,7 @@ int main(int argc, char* argv[]) { IncreaseFDLimit(); - QtSingleApplication a(argc, argv); + SingleApplication a(argc, argv); // A bug in Qt means the wheel_scroll_lines setting gets ignored and replaced // with the default value of 3 in QApplicationPrivate::initialize. @@ -363,11 +343,6 @@ int main(int argc, char* argv[]) { a.setQuitOnLastWindowClosed(false); - // Do this check again because another instance might have started by now - if (a.isRunning() && a.sendMessage(options.Serialize(), 5000)) { - return 0; - } - #ifndef Q_OS_DARWIN // Gnome on Ubuntu has menu icons disabled by default. I think that's a bad // idea, and makes some menus in Clementine look confusing. @@ -491,10 +466,8 @@ int main(int argc, char* argv[]) { #ifdef HAVE_DBUS QObject::connect(&mpris, SIGNAL(RaiseMainWindow()), &w, SLOT(Raise())); #endif - QObject::connect(&a, SIGNAL(messageReceived(QByteArray)), &w, - SLOT(CommandlineOptionsReceived(QByteArray))); - w.CommandlineOptionsReceived(options); + w.CommandlineOptionsReceived(options); int ret = a.exec(); #ifdef Q_OS_LINUX diff --git a/src/musicbrainz/acoustidclient.cpp b/src/musicbrainz/acoustidclient.cpp index ba29dc060..9f92ec8c6 100644 --- a/src/musicbrainz/acoustidclient.cpp +++ b/src/musicbrainz/acoustidclient.cpp @@ -20,8 +20,11 @@ #include #include #include - -#include +#include +#include +#include +#include +#include #include "core/closure.h" #include "core/logging.h" @@ -50,7 +53,9 @@ void AcoustidClient::Start(int id, const QString& fingerprint, << Param("fingerprint", fingerprint); QUrl url(kUrl); - url.setQueryItems(parameters); + QUrlQuery url_query; + url_query.setQueryItems(parameters); + url.setQuery(url_query); QNetworkRequest req(url); QNetworkReply* reply = network_->get(req); @@ -94,15 +99,17 @@ void AcoustidClient::RequestFinished(QNetworkReply* reply, int request_id) { return; } - QJson::Parser parser; - bool ok = false; - QVariantMap result = parser.parse(reply, &ok).toMap(); - if (!ok) { + QJsonParseError error; + QJsonDocument json_document = QJsonDocument::fromJson(reply->readAll(), &error); + + if (error.error != QJsonParseError::NoError) { emit Finished(request_id, QStringList()); return; } - QString status = result["status"].toString(); + QJsonObject json_object = json_document.object(); + + QString status = json_object["status"].toString(); if (status != "ok") { emit Finished(request_id, QStringList()); return; @@ -113,18 +120,18 @@ void AcoustidClient::RequestFinished(QNetworkReply* reply, int request_id) { // -then sort results by number of sources (the results are originally // unsorted but results with more sources are likely to be more accurate) // -keep only the ids, as sources where useful only to sort the results - QVariantList results = result["results"].toList(); + QJsonArray json_results = json_object["results"].toArray(); // List of pairs QList id_source_list; - for (const QVariant& v : results) { - QVariantMap r = v.toMap(); - if (r.contains("recordings")) { - QVariantList recordings = r["recordings"].toList(); - for (const QVariant& recording : recordings) { - QVariantMap o = recording.toMap(); - if (o.contains("id")) { + for (const QJsonValue& v : json_results) { + QJsonObject r = v.toObject(); + if (!r["recordings"].isUndefined()) { + QJsonArray json_recordings = r["recordings"].toArray(); + for (const QJsonValue& recording : json_recordings) { + QJsonObject o = recording.toObject(); + if (!o["id"].isUndefined()) { id_source_list << IdSource(o["id"].toString(), o["sources"].toInt()); } } diff --git a/src/musicbrainz/chromaprinter.cpp b/src/musicbrainz/chromaprinter.cpp index 212075835..dbb3ef0f0 100644 --- a/src/musicbrainz/chromaprinter.cpp +++ b/src/musicbrainz/chromaprinter.cpp @@ -44,7 +44,7 @@ Chromaprinter::~Chromaprinter() {} GstElement* Chromaprinter::CreateElement(const QString& factory_name, GstElement* bin) { GstElement* ret = gst_element_factory_make( - factory_name.toAscii().constData(), factory_name.toAscii().constData()); + factory_name.toLatin1().constData(), factory_name.toLatin1().constData()); if (ret && bin) gst_bin_add(GST_BIN(bin), ret); diff --git a/src/musicbrainz/musicbrainzclient.cpp b/src/musicbrainz/musicbrainzclient.cpp index 576af44d8..79c056827 100644 --- a/src/musicbrainz/musicbrainzclient.cpp +++ b/src/musicbrainz/musicbrainzclient.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "core/closure.h" #include "core/logging.h" @@ -50,7 +51,9 @@ void MusicBrainzClient::Start(int id, const QStringList& mbid_list) { parameters << Param("inc", "artists+releases+media"); QUrl url(kTrackUrl + mbid); - url.setQueryItems(parameters); + QUrlQuery url_query; + url_query.setQueryItems(parameters); + url.setQuery(url_query); QNetworkRequest req(url); QNetworkReply* reply = network_->get(req); @@ -74,7 +77,9 @@ void MusicBrainzClient::StartDiscIdRequest(const QString& discid) { parameters << Param("inc", "artists+recordings"); QUrl url(kDiscUrl + discid); - url.setQueryItems(parameters); + QUrlQuery url_query; + url_query.setQueryItems(parameters); + url.setQuery(url_query); QNetworkRequest req(url); QNetworkReply* reply = network_->get(req); diff --git a/src/networkremote/outgoingdatacreator.cpp b/src/networkremote/outgoingdatacreator.cpp index 55ec7c114..e65e8a529 100644 --- a/src/networkremote/outgoingdatacreator.cpp +++ b/src/networkremote/outgoingdatacreator.cpp @@ -180,7 +180,7 @@ void OutgoingDataCreator::SendClementineInfo() { QString version = QString("%1 %2").arg(QCoreApplication::applicationName(), QCoreApplication::applicationVersion()); - info->set_version(version.toAscii()); + info->set_version(version.toLatin1()); SendDataToClients(&msg); } diff --git a/src/playlist/playlistbackend.cpp b/src/playlist/playlistbackend.cpp index d8f3d3fd7..bb5d065a5 100644 --- a/src/playlist/playlistbackend.cpp +++ b/src/playlist/playlistbackend.cpp @@ -78,14 +78,13 @@ PlaylistBackend::PlaylistList PlaylistBackend::GetPlaylists( condition = " WHERE " + condition_list.join(" OR "); } - QSqlQuery q( - "SELECT ROWID, name, last_played, dynamic_playlist_type," + QSqlQuery q(db); + q.prepare("SELECT ROWID, name, last_played, dynamic_playlist_type," " dynamic_playlist_data, dynamic_playlist_backend," " special_type, ui_path, is_favorite" " FROM playlists" " " + - condition + " ORDER BY ui_order", - db); + condition + " ORDER BY ui_order"); q.exec(); if (db_->CheckErrors(q)) return ret; @@ -110,13 +109,12 @@ PlaylistBackend::Playlist PlaylistBackend::GetPlaylist(int id) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q( - "SELECT ROWID, name, last_played, dynamic_playlist_type," + QSqlQuery q(db); + q.prepare("SELECT ROWID, name, last_played, dynamic_playlist_type," " dynamic_playlist_data, dynamic_playlist_backend," " special_type, ui_path, is_favorite" " FROM playlists" - " WHERE ROWID=:id", - db); + " WHERE ROWID=:id"); q.bindValue(":id", id); q.exec(); if (db_->CheckErrors(q)) return Playlist(); @@ -293,23 +291,22 @@ void PlaylistBackend::SavePlaylist(int playlist, const PlaylistItemList& items, qLog(Debug) << "Saving playlist" << playlist; - QSqlQuery clear("DELETE FROM playlist_items WHERE playlist = :playlist", db); - QSqlQuery insert( - "INSERT INTO playlist_items" + QSqlQuery clear(db); + clear.prepare("DELETE FROM playlist_items WHERE playlist = :playlist"); + QSqlQuery insert(db); + insert.prepare("INSERT INTO playlist_items" " (playlist, type, library_id, radio_service, " + Song::kColumnSpec + ")" " VALUES (:playlist, :type, :library_id, :radio_service, " + - Song::kBindSpec + ")", - db); - QSqlQuery update( - "UPDATE playlists SET " + Song::kBindSpec + ")"); + QSqlQuery update(db); + update.prepare("UPDATE playlists SET " " last_played=:last_played," " dynamic_playlist_type=:dynamic_type," " dynamic_playlist_data=:dynamic_data," " dynamic_playlist_backend=:dynamic_backend" - " WHERE ROWID=:playlist", - db); + " WHERE ROWID=:playlist"); ScopedTransaction transaction(&db); @@ -350,10 +347,10 @@ int PlaylistBackend::CreatePlaylist(const QString& name, QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q( + QSqlQuery q(db); + q.prepare( "INSERT INTO playlists (name, special_type)" - " VALUES (:name, :special_type)", - db); + " VALUES (:name, :special_type)"); q.bindValue(":name", name); q.bindValue(":special_type", special_type); q.exec(); @@ -365,8 +362,10 @@ int PlaylistBackend::CreatePlaylist(const QString& name, void PlaylistBackend::RemovePlaylist(int id) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery delete_playlist("DELETE FROM playlists WHERE ROWID=:id", db); - QSqlQuery delete_items("DELETE FROM playlist_items WHERE playlist=:id", db); + QSqlQuery delete_playlist(db); + delete_playlist.prepare("DELETE FROM playlists WHERE ROWID=:id"); + QSqlQuery delete_items(db); + delete_items.prepare("DELETE FROM playlist_items WHERE playlist=:id"); delete_playlist.bindValue(":id", id); delete_items.bindValue(":id", id); @@ -385,7 +384,8 @@ void PlaylistBackend::RemovePlaylist(int id) { void PlaylistBackend::RenamePlaylist(int id, const QString& new_name) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q("UPDATE playlists SET name=:name WHERE ROWID=:id", db); + QSqlQuery q(db); + q.prepare("UPDATE playlists SET name=:name WHERE ROWID=:id"); q.bindValue(":name", new_name); q.bindValue(":id", id); @@ -396,8 +396,8 @@ void PlaylistBackend::RenamePlaylist(int id, const QString& new_name) { void PlaylistBackend::FavoritePlaylist(int id, bool is_favorite) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q("UPDATE playlists SET is_favorite=:is_favorite WHERE ROWID=:id", - db); + QSqlQuery q(db); + q.prepare("UPDATE playlists SET is_favorite=:is_favorite WHERE ROWID=:id"); q.bindValue(":is_favorite", is_favorite ? 1 : 0); q.bindValue(":id", id); @@ -410,11 +410,12 @@ void PlaylistBackend::SetPlaylistOrder(const QList& ids) { QSqlDatabase db(db_->Connect()); ScopedTransaction transaction(&db); - QSqlQuery q("UPDATE playlists SET ui_order=-1", db); + QSqlQuery q(db); + q.prepare("UPDATE playlists SET ui_order=-1"); q.exec(); if (db_->CheckErrors(q)) return; - q = QSqlQuery("UPDATE playlists SET ui_order=:index WHERE ROWID=:id", db); + q.prepare("UPDATE playlists SET ui_order=:index WHERE ROWID=:id"); for (int i = 0; i < ids.count(); ++i) { q.bindValue(":index", i); q.bindValue(":id", ids[i]); @@ -428,7 +429,8 @@ void PlaylistBackend::SetPlaylistOrder(const QList& ids) { void PlaylistBackend::SetPlaylistUiPath(int id, const QString& path) { QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); - QSqlQuery q("UPDATE playlists SET ui_path=:path WHERE ROWID=:id", db); + QSqlQuery q(db); + q.prepare("UPDATE playlists SET ui_path=:path WHERE ROWID=:id"); ScopedTransaction transaction(&db); diff --git a/src/playlist/playlistdelegates.cpp b/src/playlist/playlistdelegates.cpp index 76b15544c..580e78a40 100644 --- a/src/playlist/playlistdelegates.cpp +++ b/src/playlist/playlistdelegates.cpp @@ -220,7 +220,7 @@ bool PlaylistDelegateBase::helpEvent(QHelpEvent* event, QAbstractItemView* view, // Special case: we want newlines in the comment tooltip if (index.column() == Playlist::Column_Comment) { - text = Qt::escape(index.data(Qt::ToolTipRole).toString()); + text = index.data(Qt::ToolTipRole).toString().toHtmlEscaped(); text.replace("\\r\\n", "
"); text.replace("\\n", "
"); text.replace("\r\n", "
"); @@ -436,7 +436,7 @@ QString NativeSeparatorsDelegate::displayText(const QVariant& value, if (value.type() == QVariant::Url) { url = value.toUrl(); } else if (string_value.contains("://")) { - url = QUrl::fromEncoded(string_value.toAscii()); + url = QUrl::fromEncoded(string_value.toLatin1()); } else { return QDir::toNativeSeparators(string_value); } diff --git a/src/playlist/playlistview.cpp b/src/playlist/playlistview.cpp index fe4ec4562..c1cebc56c 100644 --- a/src/playlist/playlistview.cpp +++ b/src/playlist/playlistview.cpp @@ -27,7 +27,7 @@ #include "covers/currentartloader.h" #include "ui/qt_blurimage.h" -#include +#include #include #include #include @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -60,7 +61,7 @@ const int PlaylistView::kDefaultBlurRadius = 0; const int PlaylistView::kDefaultOpacityLevel = 40; PlaylistProxyStyle::PlaylistProxyStyle(QStyle* base) - : QProxyStyle(base), cleanlooks_(new QCleanlooksStyle) {} + : QProxyStyle(base), common_style_(new QCommonStyle) {} void PlaylistProxyStyle::drawControl(ControlElement element, const QStyleOption* option, @@ -85,7 +86,7 @@ void PlaylistProxyStyle::drawControl(ControlElement element, } if (element == CE_ItemViewItem) - cleanlooks_->drawControl(element, option, painter, widget); + common_style_->drawControl(element, option, painter, widget); else QProxyStyle::drawControl(element, option, painter, widget); } @@ -96,7 +97,7 @@ void PlaylistProxyStyle::drawPrimitive(PrimitiveElement element, const QWidget* widget) const { if (element == QStyle::PE_PanelItemViewRow || element == QStyle::PE_PanelItemViewItem) - cleanlooks_->drawPrimitive(element, option, painter, widget); + common_style_->drawPrimitive(element, option, painter, widget); else QProxyStyle::drawPrimitive(element, option, painter, widget); } @@ -132,7 +133,7 @@ PlaylistView::PlaylistView(QWidget* parent) drag_over_(false), dynamic_controls_(new DynamicPlaylistControls(this)) { setHeader(header_); - header_->setMovable(true); + header_->setSectionsMovable(true); setStyle(style_); setMouseTracking(true); diff --git a/src/playlist/playlistview.h b/src/playlist/playlistview.h index fedc207e0..d72312b8d 100644 --- a/src/playlist/playlistview.h +++ b/src/playlist/playlistview.h @@ -26,7 +26,7 @@ #include "playlist.h" -class QCleanlooksStyle; +class QCommonStyle; class Application; class DynamicPlaylistControls; @@ -40,7 +40,7 @@ class QTimeLine; // that uses Gtk to paint row backgrounds, ignoring any custom brush or palette // the caller set in the QStyleOption. That breaks our currently playing track // animation, which relies on the background painted by Qt to be transparent. -// This proxy style uses QCleanlooksStyle to paint the affected elements. +// This proxy style uses QCommonStyle to paint the affected elements. // This class is used by the global search view as well. class PlaylistProxyStyle : public QProxyStyle { public: @@ -51,7 +51,7 @@ class PlaylistProxyStyle : public QProxyStyle { QPainter* painter, const QWidget* widget) const; private: - std::unique_ptr cleanlooks_; + std::unique_ptr common_style_; }; class PlaylistView : public QTreeView { diff --git a/src/smartplaylists/searchtermwidget.cpp b/src/smartplaylists/searchtermwidget.cpp index 74bf64b07..9cf989475 100644 --- a/src/smartplaylists/searchtermwidget.cpp +++ b/src/smartplaylists/searchtermwidget.cpp @@ -118,7 +118,7 @@ SearchTermWidget::SearchTermWidget(LibraryBackend* library, QWidget* parent) // Set stylesheet QFile stylesheet_file(":/smartplaylistsearchterm.css"); stylesheet_file.open(QIODevice::ReadOnly); - QString stylesheet = QString::fromAscii(stylesheet_file.readAll()); + QString stylesheet = QString::fromLatin1(stylesheet_file.readAll()); const QColor base(222, 97, 97, 128); stylesheet.replace("%light2", Utilities::ColorToRgba(base.lighter(140))); stylesheet.replace("%light", Utilities::ColorToRgba(base.lighter(120))); diff --git a/src/songinfo/songinfobase.cpp b/src/songinfo/songinfobase.cpp index 35bd0c517..770b8d5a3 100644 --- a/src/songinfo/songinfobase.cpp +++ b/src/songinfo/songinfobase.cpp @@ -59,7 +59,7 @@ SongInfoBase::SongInfoBase(QWidget* parent) // Set stylesheet QFile stylesheet(":/songinfo.css"); stylesheet.open(QIODevice::ReadOnly); - setStyleSheet(QString::fromAscii(stylesheet.readAll())); + setStyleSheet(QString::fromLatin1(stylesheet.readAll())); connect(fetcher_, SIGNAL(ResultReady(int, SongInfoFetcher::Result)), SLOT(ResultReady(int, SongInfoFetcher::Result))); diff --git a/src/songinfo/songkickconcerts.cpp b/src/songinfo/songkickconcerts.cpp index 1b36e420e..0f21633cf 100644 --- a/src/songinfo/songkickconcerts.cpp +++ b/src/songinfo/songkickconcerts.cpp @@ -20,11 +20,12 @@ #include #include #include +#include +#include +#include #include -#include - #include "core/closure.h" #include "core/logging.h" #include "songkickconcertwidget.h" @@ -107,22 +108,23 @@ void SongkickConcerts::FetchSongkickCalendar(const QString& artist_id, int id) { } void SongkickConcerts::CalendarRequestFinished(QNetworkReply* reply, int id) { - QJson::Parser parser; - bool ok = false; - QVariant result = parser.parse(reply, &ok); + reply->deleteLater(); - if (!ok) { + QJsonParseError error; + QJsonDocument json_document = QJsonDocument::fromJson(reply->readAll(), &error); + + if (error.error != QJsonParseError::NoError) { qLog(Error) << "Error parsing Songkick reply"; emit Finished(id); return; } - QVariantMap root = result.toMap(); - QVariantMap results_page = root["resultsPage"].toMap(); - QVariantMap results = results_page["results"].toMap(); - QVariantList events = results["event"].toList(); + QJsonObject json_root = json_document.object(); + QJsonObject json_results_page = json_root["resultsPage"].toObject(); + QJsonObject json_results = json_results_page["results"].toObject(); + QJsonArray json_events = json_results["event"].toArray(); - if (events.isEmpty()) { + if (json_events.isEmpty()) { emit Finished(id); return; } @@ -130,21 +132,21 @@ void SongkickConcerts::CalendarRequestFinished(QNetworkReply* reply, int id) { QWidget* container = new QWidget; QVBoxLayout* layout = new QVBoxLayout(container); - for (const QVariant& v : events) { - QVariantMap event = v.toMap(); - QString display_name = event["displayName"].toString(); - QString start_date = event["start"].toMap()["date"].toString(); - QString city = event["location"].toMap()["city"].toString(); - QString uri = event["uri"].toString(); + for (const QJsonValue& v : json_events) { + QJsonObject json_event = v.toObject(); + QString display_name = json_event["displayName"].toString(); + QString start_date = json_event["start"].toObject()["date"].toString(); + QString city = json_event["location"].toObject()["city"].toString(); + QString uri = json_event["uri"].toString(); // Try to get the lat/lng coordinates of the venue. - QVariantMap venue = event["venue"].toMap(); - const bool valid_latlng = venue["lng"].isValid() && venue["lat"].isValid(); + QJsonObject json_venue = json_event["venue"].toObject(); + const bool valid_latlng = !json_venue["lng"].isUndefined() && !json_venue["lat"].isUndefined(); if (valid_latlng && latlng_.IsValid()) { static const int kFilterDistanceMetres = 250 * 1e3; // 250km - Geolocator::LatLng latlng(venue["lat"].toString(), - venue["lng"].toString()); + Geolocator::LatLng latlng(json_venue["lat"].toString(), + json_venue["lng"].toString()); if (latlng_.IsValid() && latlng.IsValid()) { int distance_metres = latlng_.Distance(latlng); if (distance_metres > kFilterDistanceMetres) { @@ -159,8 +161,8 @@ void SongkickConcerts::CalendarRequestFinished(QNetworkReply* reply, int id) { widget->Init(display_name, uri, start_date, city); if (valid_latlng) { - widget->SetMap(venue["lat"].toString(), venue["lng"].toString(), - venue["displayName"].toString()); + widget->SetMap(json_venue["lat"].toString(), json_venue["lng"].toString(), + json_venue["displayName"].toString()); } layout->addWidget(widget); diff --git a/src/songinfo/songkickconcertwidget.cpp b/src/songinfo/songkickconcertwidget.cpp index 691f9fb02..21655f1f0 100644 --- a/src/songinfo/songkickconcertwidget.cpp +++ b/src/songinfo/songkickconcertwidget.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "songinfotextview.h" #include "ui_songkickconcertwidget.h" @@ -58,7 +59,7 @@ void SongKickConcertWidget::ReloadSettings() { void SongKickConcertWidget::Init(const QString& title, const QString& url, const QString& date, const QString& location) { ui_->title->setText( - QString("%2").arg(Qt::escape(url), Qt::escape(title))); + QString("%2").arg(url.toHtmlEscaped(), title.toHtmlEscaped())); if (!location.isEmpty()) { ui_->location->setText(location); @@ -96,10 +97,12 @@ void SongKickConcertWidget::SetMap(const QString& lat, const QString& lng, ui_->map->show(); map_url_ = QUrl("https://maps.google.com/"); - map_url_.addQueryItem("ll", QString("%1,%2").arg(lat, lng)); + QUrlQuery map_url_query; + map_url_query.addQueryItem("ll", QString("%1,%2").arg(lat, lng)); if (!venue_name.isEmpty()) { - map_url_.addQueryItem("q", venue_name); + map_url_query.addQueryItem("q", venue_name); } + map_url_.setQuery(map_url_query); // Request the static map image const QUrl url(QString(kStaticMapUrl).arg(QString::number(kStaticMapWidth), diff --git a/src/songinfo/ultimatelyricsprovider.cpp b/src/songinfo/ultimatelyricsprovider.cpp index 586e5d239..915d62a00 100644 --- a/src/songinfo/ultimatelyricsprovider.cpp +++ b/src/songinfo/ultimatelyricsprovider.cpp @@ -37,7 +37,7 @@ UltimateLyricsProvider::UltimateLyricsProvider() void UltimateLyricsProvider::FetchInfo(int id, const Song& metadata) { // Get the text codec const QTextCodec* codec = - QTextCodec::codecForName(charset_.toAscii().constData()); + QTextCodec::codecForName(charset_.toLatin1().constData()); if (!codec) { qLog(Warning) << "Invalid codec" << charset_; emit Finished(id); @@ -100,7 +100,7 @@ void UltimateLyricsProvider::LyricsFetched() { } const QTextCodec* codec = - QTextCodec::codecForName(charset_.toAscii().constData()); + QTextCodec::codecForName(charset_.toLatin1().constData()); const QString original_content = codec->toUnicode(reply->readAll()); QString lyrics; diff --git a/src/transcoder/transcodedialog.cpp b/src/transcoder/transcodedialog.cpp index 49f2f8ef8..981e3178a 100644 --- a/src/transcoder/transcodedialog.cpp +++ b/src/transcoder/transcodedialog.cpp @@ -54,7 +54,7 @@ TranscodeDialog::TranscodeDialog(QWidget* parent) finished_success_(0), finished_failed_(0) { ui_->setupUi(this); - ui_->files->header()->setResizeMode(QHeaderView::ResizeToContents); + ui_->files->header()->setSectionResizeMode(QHeaderView::ResizeToContents); log_ui_->setupUi(log_dialog_); QPushButton* clear_button = diff --git a/src/transcoder/transcoder.cpp b/src/transcoder/transcoder.cpp index 973a161cc..a51b77bd6 100644 --- a/src/transcoder/transcoder.cpp +++ b/src/transcoder/transcoder.cpp @@ -47,9 +47,9 @@ TranscoderPreset::TranscoderPreset(Song::FileType type, const QString& name, GstElement* Transcoder::CreateElement(const QString& factory_name, GstElement* bin, const QString& name) { GstElement* ret = gst_element_factory_make( - factory_name.toAscii().constData(), - name.isNull() ? factory_name.toAscii().constData() - : name.toAscii().constData()); + factory_name.toLatin1().constData(), + name.isNull() ? factory_name.toLatin1().constData() + : name.toLatin1().constData()); if (ret && bin) gst_bin_add(GST_BIN(bin), ret); diff --git a/src/ui/albumcoverchoicecontroller.cpp b/src/ui/albumcoverchoicecontroller.cpp index 06a40f3c5..0fa6f15e0 100644 --- a/src/ui/albumcoverchoicecontroller.cpp +++ b/src/ui/albumcoverchoicecontroller.cpp @@ -39,6 +39,7 @@ #include #include #include +#include const char* AlbumCoverChoiceController::kLoadImageFileFilter = QT_TR_NOOP( "Images (*.png *.jpg *.jpeg *.bmp *.gif *.xpm *.pbm *.pgm *.ppm *.xbm)"); diff --git a/src/ui/edittagdialog.cpp b/src/ui/edittagdialog.cpp index a69c67fbe..d3075fec2 100644 --- a/src/ui/edittagdialog.cpp +++ b/src/ui/edittagdialog.cpp @@ -461,21 +461,20 @@ void EditTagDialog::UpdateSummaryTab(const Song& song) { app_->album_cover_loader()->LoadImageAsync(cover_options_, song); QString summary = - "" + Qt::escape(song.PrettyTitleWithArtist()) + "
"; + "" + song.PrettyTitleWithArtist().toHtmlEscaped() + "
"; bool art_is_set = true; if (song.has_manually_unset_cover()) { - summary += Qt::escape(tr("Cover art manually unset")); + summary += tr("Cover art manually unset").toHtmlEscaped(); art_is_set = false; } else if (!song.art_manual().isEmpty()) { - summary += Qt::escape(tr("Cover art set from %1").arg(song.art_manual())); + summary += tr("Cover art set from %1").arg(song.art_manual()).toHtmlEscaped(); } else if (song.has_embedded_cover()) { - summary += Qt::escape(tr("Cover art from embedded image")); + summary += tr("Cover art from embedded image"); } else if (!song.art_automatic().isEmpty()) { - summary += Qt::escape( - tr("Cover art loaded automatically from %1").arg(song.art_automatic())); + summary += tr("Cover art loaded automatically from %1").arg(song.art_automatic()).toHtmlEscaped(); } else { - summary += Qt::escape(tr("Cover art not set")); + summary += tr("Cover art not set").toHtmlEscaped(); art_is_set = false; } diff --git a/src/ui/flowlayout.cpp b/src/ui/flowlayout.cpp index cccb1a1c4..582ec92bd 100644 --- a/src/ui/flowlayout.cpp +++ b/src/ui/flowlayout.cpp @@ -38,7 +38,7 @@ ** ****************************************************************************/ -#include +#include #include "flowlayout.h" //! [1] diff --git a/src/ui/globalshortcutssettingspage.cpp b/src/ui/globalshortcutssettingspage.cpp index 8217594a0..8a25d27ae 100644 --- a/src/ui/globalshortcutssettingspage.cpp +++ b/src/ui/globalshortcutssettingspage.cpp @@ -39,7 +39,7 @@ GlobalShortcutsSettingsPage::GlobalShortcutsSettingsPage(SettingsDialog* dialog) grabber_(new GlobalShortcutGrabber) { ui_->setupUi(this); ui_->shortcut_options->setEnabled(false); - ui_->list->header()->setResizeMode(QHeaderView::ResizeToContents); + ui_->list->header()->setSectionResizeMode(QHeaderView::ResizeToContents); setWindowIcon(IconLoader::Load("input-keyboard")); settings_.beginGroup(GlobalShortcuts::kSettingsGroup); diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 736762b2a..cba1d91d9 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -951,7 +951,6 @@ MainWindow::~MainWindow() { void MainWindow::ReloadSettings() { #ifndef Q_OS_DARWIN bool show_tray = settings_.value("showtray", true).toBool(); - tray_icon_->SetVisible(show_tray); if (!show_tray && !isVisible()) show(); #endif diff --git a/src/ui/qtsystemtrayicon.cpp b/src/ui/qtsystemtrayicon.cpp index 39677bc21..436cdc395 100644 --- a/src/ui/qtsystemtrayicon.cpp +++ b/src/ui/qtsystemtrayicon.cpp @@ -57,7 +57,7 @@ QtSystemTrayIcon::QtSystemTrayIcon(QObject* parent) QFile pattern_file(":/now_playing_tooltip.txt"); pattern_file.open(QIODevice::ReadOnly); - pattern_ = QString::fromAscii(pattern_file.readAll()); + pattern_ = QString::fromLatin1(pattern_file.readAll()); connect(tray_, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), SLOT(Clicked(QSystemTrayIcon::ActivationReason))); @@ -216,7 +216,7 @@ void QtSystemTrayIcon::SetVisible(bool visible) { tray_->setVisible(visible); } void QtSystemTrayIcon::SetNowPlaying(const Song& song, const QString& image_path) { -#ifdef Q_WS_WIN +#ifdef Q_OS_WIN // Windows doesn't support HTML in tooltips, so just show something basic tray_->setToolTip(song.PrettyTitleWithArtist()); return; @@ -230,14 +230,14 @@ void QtSystemTrayIcon::SetNowPlaying(const Song& song, clone.replace("%appName", QCoreApplication::applicationName()); clone.replace("%titleKey", tr("Title") % ":"); - clone.replace("%titleValue", Qt::escape(song.PrettyTitle())); + clone.replace("%titleValue", song.PrettyTitle().toHtmlEscaped()); clone.replace("%artistKey", tr("Artist") % ":"); - clone.replace("%artistValue", Qt::escape(song.artist())); + clone.replace("%artistValue", song.artist().toHtmlEscaped()); clone.replace("%albumKey", tr("Album") % ":"); - clone.replace("%albumValue", Qt::escape(song.album())); + clone.replace("%albumValue", song.album().toHtmlEscaped()); clone.replace("%lengthKey", tr("Length") % ":"); - clone.replace("%lengthValue", Qt::escape(song.PrettyLength())); + clone.replace("%lengthValue", song.PrettyLength().toHtmlEscaped()); if (columns == 2) { QString final_path = diff --git a/src/widgets/errordialog.cpp b/src/widgets/errordialog.cpp index eb6e0bef8..1086305f3 100644 --- a/src/widgets/errordialog.cpp +++ b/src/widgets/errordialog.cpp @@ -53,7 +53,7 @@ void ErrorDialog::UpdateContent() { QString html; for (const QString& message : current_messages_) { if (!html.isEmpty()) html += "
"; - html += Qt::escape(message); + html += message.toHtmlEscaped(); } ui_->messages->setHtml(html); } diff --git a/src/widgets/fancytabwidget.cpp b/src/widgets/fancytabwidget.cpp index c61d3fe83..9f73584e7 100644 --- a/src/widgets/fancytabwidget.cpp +++ b/src/widgets/fancytabwidget.cpp @@ -47,7 +47,7 @@ #include #include #include -#include +#include using namespace Core; using namespace Internal; @@ -128,7 +128,7 @@ void FancyTabProxyStyle::drawControl(ControlElement element, p->drawText(text_rect, textFlags, text); p->setPen(selected ? QColor(60, 60, 60) : Utils::StyleHelper::panelTextColor()); -#ifndef Q_WS_MAC +#ifndef Q_OS_MAC if (widget) { const QString fader_key = "tab_" + text + "_fader"; const QString animation_key = "tab_" + text + "_animation"; @@ -253,7 +253,7 @@ void FancyTab::setFader(float value) { FancyTabBar::FancyTabBar(QWidget* parent) : QWidget(parent) { setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); - setStyle(new QWindowsStyle); + setStyle(new QCommonStyle); setMinimumWidth(qMax(2 * m_rounding, 40)); setAttribute(Qt::WA_Hover, true); setFocusPolicy(Qt::NoFocus); @@ -439,7 +439,7 @@ void FancyTabBar::paintTab(QPainter* painter, int tabIndex) const { painter->drawText(tabTextRect, textFlags, tabText); painter->setPen(selected ? QColor(60, 60, 60) : Utils::StyleHelper::panelTextColor()); -#ifndef Q_WS_MAC +#ifndef Q_OS_MAC if (!selected) { painter->save(); int fader = int(m_tabs[tabIndex]->fader()); diff --git a/src/widgets/forcescrollperpixel.cpp b/src/widgets/forcescrollperpixel.cpp index 065c1e47b..f7aea32c1 100644 --- a/src/widgets/forcescrollperpixel.cpp +++ b/src/widgets/forcescrollperpixel.cpp @@ -29,8 +29,7 @@ ForceScrollPerPixel::ForceScrollPerPixel(QAbstractItemView* item_view, bool ForceScrollPerPixel::eventFilter(QObject* object, QEvent* event) { if (object == item_view_ && event->type() != QEvent::Destroy && - event->type() != QEvent::WinIdChange && - event->type() != QEvent::AccessibilityPrepare) { + event->type() != QEvent::WinIdChange) { item_view_->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); item_view_->verticalScrollBar()->setSingleStep(20); } diff --git a/src/widgets/groupediconview.cpp b/src/widgets/groupediconview.cpp index ba0fef26b..60a53a85b 100644 --- a/src/widgets/groupediconview.cpp +++ b/src/widgets/groupediconview.cpp @@ -108,7 +108,7 @@ void GroupedIconView::rowsInserted(const QModelIndex& parent, int start, } void GroupedIconView::dataChanged(const QModelIndex& topLeft, - const QModelIndex& bottomRight) { + const QModelIndex& bottomRight, const QVector &) { QListView::dataChanged(topLeft, bottomRight); LayoutItems(); } diff --git a/src/widgets/groupediconview.h b/src/widgets/groupediconview.h index 42e08bf1f..025e5584d 100644 --- a/src/widgets/groupediconview.h +++ b/src/widgets/groupediconview.h @@ -72,7 +72,7 @@ class GroupedIconView : public QListView { void resizeEvent(QResizeEvent* e); // QAbstractItemView - void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); + void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector& = QVector()); QModelIndex indexAt(const QPoint& p) const; void rowsInserted(const QModelIndex& parent, int start, int end); void setSelection(const QRect& rect, diff --git a/src/widgets/nowplayingwidget.cpp b/src/widgets/nowplayingwidget.cpp index 10194e18a..588736599 100644 --- a/src/widgets/nowplayingwidget.cpp +++ b/src/widgets/nowplayingwidget.cpp @@ -290,8 +290,8 @@ void NowPlayingWidget::UpdateDetailsText() { // TODO: Make this configurable html += QString("%1
%2
%3").arg( - Qt::escape(metadata_.PrettyTitle()), Qt::escape(metadata_.artist()), - Qt::escape(metadata_.album())); + metadata_.PrettyTitle().toHtmlEscaped(), metadata_.artist().toHtmlEscaped(), + metadata_.album().toHtmlEscaped()); html += "

"; details_->setHtml(html); diff --git a/src/widgets/stylehelper.cpp b/src/widgets/stylehelper.cpp index 23ab4c697..87674af37 100644 --- a/src/widgets/stylehelper.cpp +++ b/src/widgets/stylehelper.cpp @@ -30,12 +30,12 @@ #include "stylehelper.h" #include -#include +#include #include #include -#include +#include #include -#include +#include #include // Clamps float color values within (0, 255) @@ -47,7 +47,7 @@ static int clamp(float x) { namespace Utils { qreal StyleHelper::sidebarFontSize() { -#if defined(Q_WS_MAC) +#if defined(Q_OS_MAC) return 10; #else return 7.5; diff --git a/src/widgets/stylehelper.h b/src/widgets/stylehelper.h index f73f4b442..77c62b9ec 100644 --- a/src/widgets/stylehelper.h +++ b/src/widgets/stylehelper.h @@ -30,8 +30,8 @@ #ifndef STYLEHELPER_H #define STYLEHELPER_H -#include -#include +#include +#include #include "ui/qt_blurimage.h" diff --git a/tests/scopedtransaction_test.cpp b/tests/scopedtransaction_test.cpp index 2a7fa98da..3261574b9 100644 --- a/tests/scopedtransaction_test.cpp +++ b/tests/scopedtransaction_test.cpp @@ -63,13 +63,15 @@ TEST_F(ScopedTransactionTest, RollbackOnDtor) { ScopedTransaction t(&database_); database_.exec("INSERT INTO foo (bar) VALUES (42)"); - QSqlQuery q("SELECT * FROM foo", database_); + QSqlQuery q(database_); + q.prepare("SELECT * FROM foo"); ASSERT_TRUE(q.exec()); ASSERT_TRUE(q.next()); EXPECT_EQ(42, q.value(0).toInt()); } - QSqlQuery q("SELECT * FROM foo", database_); + QSqlQuery q(database_); + q.prepare("SELECT * FROM foo"); ASSERT_TRUE(q.exec()); ASSERT_FALSE(q.next()); } @@ -83,7 +85,8 @@ TEST_F(ScopedTransactionTest, Commit) { t.Commit(); } - QSqlQuery q("SELECT * FROM foo", database_); + QSqlQuery q(database_); + q.prepare("SELECT * FROM foo"); ASSERT_TRUE(q.exec()); ASSERT_TRUE(q.next()); EXPECT_EQ(42, q.value(0).toInt()); diff --git a/tools/ultimate_lyrics_parser/main.cpp b/tools/ultimate_lyrics_parser/main.cpp index 19083ff43..a92d3ad5f 100644 --- a/tools/ultimate_lyrics_parser/main.cpp +++ b/tools/ultimate_lyrics_parser/main.cpp @@ -17,8 +17,6 @@ #include #include -#include -#include #include #include From 42aafd247a3a96f7a6c07d31b3a0881691a8daf2 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 15 Apr 2015 18:26:09 +0200 Subject: [PATCH 010/104] Update optional components to qt5 --- CMakeLists.txt | 51 ++++++------ src/CMakeLists.txt | 7 +- src/dbus/org.freedesktop.Avahi.EntryGroup.xml | 4 +- src/dbus/org.freedesktop.Avahi.Server.xml | 2 +- .../org.freedesktop.MediaPlayer.player.xml | 8 +- src/dbus/org.freedesktop.MediaPlayer.root.xml | 2 +- .../org.freedesktop.MediaPlayer.tracklist.xml | 2 +- src/dbus/org.freedesktop.Notifications.xml | 2 +- src/dbus/org.freedesktop.UDisks.Device.xml | 8 +- src/dbus/org.freedesktop.UDisks.xml | 2 +- src/dbus/org.mpris.MediaPlayer2.Player.xml | 2 +- src/dbus/org.mpris.MediaPlayer2.Playlists.xml | 8 +- src/dbus/org.mpris.MediaPlayer2.TrackList.xml | 6 +- src/devices/mtpconnection.cpp | 14 ++-- src/internet/box/boxservice.cpp | 73 +++++++++--------- src/internet/box/boxservice.h | 2 +- src/internet/dropbox/dropboxauthenticator.cpp | 20 ++--- src/internet/dropbox/dropboxservice.cpp | 50 ++++++------ .../googledrive/googledriveclient.cpp | 60 ++++++++------- .../googledrive/googledriveservice.cpp | 7 +- src/internet/lastfm/lastfmcompat.h | 28 +++---- src/internet/lastfm/lastfmservice.cpp | 2 +- src/internet/seafile/seafileservice.cpp | 77 ++++++++++--------- src/internet/skydrive/skydriveservice.cpp | 38 ++++----- src/internet/vk/vkconnection.cpp | 60 +++++++++------ src/internet/vk/vkmusiccache.cpp | 2 +- src/moodbar/moodbarpipeline.cpp | 2 +- src/ui/ripcd.cpp | 6 +- src/widgets/osd_x11.cpp | 2 +- src/wiimotedev/wiimotesettingspage.cpp | 2 +- tests/CMakeLists.txt | 8 +- 31 files changed, 298 insertions(+), 259 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fccae8aa..c108b2974 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,9 +87,9 @@ if (WIN32) find_library(QTSPARKLE_LIBRARIES qtsparkle) endif (WIN32) -find_library(LASTFM_LIBRARIES lastfm) -find_path(LASTFM_INCLUDE_DIRS lastfm/ws.h) -find_path(LASTFM1_INCLUDE_DIRS lastfm/Track.h) +find_library(LASTFM5_LIBRARIES lastfm5) +find_path(LASTFM5_INCLUDE_DIRS lastfm5/ws.h) +find_path(LASTFM51_INCLUDE_DIRS lastfm5/Track.h) find_path(SPARSEHASH_INCLUDE_DIRS google/sparsetable) @@ -115,7 +115,7 @@ else() set(CMAKE_REQUIRED_LIBRARIES) endif() -if(LASTFM_INCLUDE_DIRS AND LASTFM1_INCLUDE_DIRS) +if(LASTFM5_INCLUDE_DIRS AND LASTFM51_INCLUDE_DIRS) set(HAVE_LIBLASTFM1 ON) endif() @@ -192,85 +192,85 @@ endif(WIN32) optional_component(BREAKPAD OFF "Crash reporting") -optional_component(GOOGLE_DRIVE OFF "Google Drive support" +optional_component(GOOGLE_DRIVE ON "Google Drive support" DEPENDS "Google sparsehash" SPARSEHASH_INCLUDE_DIRS DEPENDS "Taglib 1.8" "TAGLIB_VERSION VERSION_GREATER 1.7.999" ) -optional_component(DROPBOX OFF "Dropbox support" +optional_component(DROPBOX ON "Dropbox support" DEPENDS "Google sparsehash" SPARSEHASH_INCLUDE_DIRS DEPENDS "Taglib 1.8" "TAGLIB_VERSION VERSION_GREATER 1.7.999" ) -optional_component(SKYDRIVE OFF "Skydrive support" +optional_component(SKYDRIVE ON "Skydrive support" DEPENDS "Google sparsehash" SPARSEHASH_INCLUDE_DIRS DEPENDS "Taglib 1.8" "TAGLIB_VERSION VERSION_GREATER 1.7.999" ) -optional_component(BOX OFF "Box support" +optional_component(BOX ON "Box support" DEPENDS "Google sparsehash" SPARSEHASH_INCLUDE_DIRS DEPENDS "Taglib 1.8" "TAGLIB_VERSION VERSION_GREATER 1.7.999" ) -optional_component(VK OFF "Vk.com support") +optional_component(VK ON "Vk.com support") -optional_component(SEAFILE OFF "Seafile support" +optional_component(SEAFILE ON "Seafile support" DEPENDS "Google sparsehash" SPARSEHASH_INCLUDE_DIRS DEPENDS "Taglib 1.8" "TAGLIB_VERSION VERSION_GREATER 1.7.999" ) -optional_component(AUDIOCD OFF "Devices: Audio CD support" +optional_component(AUDIOCD ON "Devices: Audio CD support" DEPENDS "libcdio" CDIO_FOUND ) -optional_component(LIBGPOD OFF "Devices: iPod classic support" +optional_component(LIBGPOD ON "Devices: iPod classic support" DEPENDS "libgpod" LIBGPOD_FOUND ) -optional_component(GIO OFF "Devices: GIO device backend" +optional_component(GIO ON "Devices: GIO device backend" DEPENDS "libgio" GIO_FOUND DEPENDS "Linux or Windows" "NOT APPLE" ) -optional_component(LIBMTP OFF "Devices: MTP support" +optional_component(LIBMTP ON "Devices: MTP support" DEPENDS "libmtp" LIBMTP_FOUND ) -optional_component(LIBLASTFM OFF "Last.fm support" - DEPENDS "liblastfm" LASTFM_LIBRARIES LASTFM_INCLUDE_DIRS +optional_component(LIBLASTFM ON "Last.fm support" + DEPENDS "liblastfm" LASTFM5_LIBRARIES LASTFM5_INCLUDE_DIRS ) -optional_component(DBUS OFF "D-Bus support" +optional_component(DBUS ON "D-Bus support" DEPENDS "Linux" LINUX ) -optional_component(WIIMOTEDEV OFF "Wiimote support" +optional_component(WIIMOTEDEV ON "Wiimote support" DEPENDS "D-Bus support" HAVE_DBUS ) -optional_component(DEVICEKIT OFF "Devices: DeviceKit backend" +optional_component(DEVICEKIT ON "Devices: DeviceKit backend" DEPENDS "D-Bus support" HAVE_DBUS ) -optional_component(SPOTIFY_BLOB OFF "Spotify support: non-GPL binary helper" +optional_component(SPOTIFY_BLOB ON "Spotify support: non-GPL binary helper" DEPENDS "protobuf" PROTOBUF_FOUND PROTOBUF_PROTOC_EXECUTABLE DEPENDS "libspotify" SPOTIFY_FOUND ) -optional_component(MOODBAR OFF "Moodbar support" +optional_component(MOODBAR ON "Moodbar support" DEPENDS "fftw3" FFTW3_FOUND ) -optional_component(SPARKLE OFF "Sparkle integration" +optional_component(SPARKLE ON "Sparkle integration" DEPENDS "Mac OS X" APPLE DEPENDS "Sparkle" SPARKLE ) -optional_component(LIBPULSE OFF "Pulse audio integration" +optional_component(LIBPULSE ON "Pulse audio integration" DEPENDS "libpulse" LIBPULSE_FOUND ) -optional_component(VISUALISATIONS OFF "Visualisations") +optional_component(VISUALISATIONS ON "Visualisations") if(NOT HAVE_SPOTIFY_BLOB AND NOT QCA_QT5_FOUND) message(FATAL_ERROR "Either QCA-qt5 must be available or the non-GPL Spotify " @@ -282,6 +282,7 @@ endif() # Find DBus if it's enabled if (HAVE_DBUS) find_package(Qt5 COMPONENTS DBus) + get_target_property(QT_DBUSXML2CPP_EXECUTABLE Qt5::qdbusxml2cpp LOCATION) endif () if (HAVE_VK) @@ -291,7 +292,7 @@ if (HAVE_VK) endif(HAVE_VK) # We can include the Qt definitions now -set(QT_LIBRARIES Qt5::Core Qt5::OpenGL Qt5::Sql Qt5::Network Qt5::Xml Qt5::Widgets Qt5::Concurrent Qt5::X11Extras) +set(QT_LIBRARIES Qt5::Core Qt5::OpenGL Qt5::Sql Qt5::Network Qt5::Xml Qt5::Widgets Qt5::Concurrent Qt5::X11Extras Qt5::DBus) # Remove GLU and GL from the link line - they're not really required # and don't exist on my mingw toolchain diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b9cc0d438..9d193c850 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -44,7 +44,7 @@ find_package(OpenGL) include_directories(${OPENGL_INCLUDE_DIR}) if(HAVE_LIBLASTFM) - include_directories(${LASTFM_INCLUDE_DIRS}) + include_directories(${LASTFM5_INCLUDE_DIRS}) endif(HAVE_LIBLASTFM) if(HAVE_BREAKPAD) @@ -1223,9 +1223,6 @@ add_library(clementine_lib STATIC ${OTHER_UIC_SOURCES} ) -add_dependencies(clementine_lib pot) - - target_link_libraries(clementine_lib clementine-spotifyblob-messages libclementine-common @@ -1261,7 +1258,7 @@ if(ENABLE_VISUALISATIONS) endif(ENABLE_VISUALISATIONS) if(HAVE_LIBLASTFM) - target_link_libraries(clementine_lib ${LASTFM_LIBRARIES}) + target_link_libraries(clementine_lib ${LASTFM5_LIBRARIES}) endif(HAVE_LIBLASTFM) if(HAVE_LIBGPOD) diff --git a/src/dbus/org.freedesktop.Avahi.EntryGroup.xml b/src/dbus/org.freedesktop.Avahi.EntryGroup.xml index 2930d7eeb..ec7f13742 100644 --- a/src/dbus/org.freedesktop.Avahi.EntryGroup.xml +++ b/src/dbus/org.freedesktop.Avahi.EntryGroup.xml @@ -51,7 +51,7 @@ -
@@ -73,7 +73,7 @@ - diff --git a/src/dbus/org.freedesktop.Avahi.Server.xml b/src/dbus/org.freedesktop.Avahi.Server.xml index f336f207c..49493b3e0 100644 --- a/src/dbus/org.freedesktop.Avahi.Server.xml +++ b/src/dbus/org.freedesktop.Avahi.Server.xml @@ -132,7 +132,7 @@ - diff --git a/src/dbus/org.freedesktop.MediaPlayer.player.xml b/src/dbus/org.freedesktop.MediaPlayer.player.xml index fc81b98a7..1523ec00d 100644 --- a/src/dbus/org.freedesktop.MediaPlayer.player.xml +++ b/src/dbus/org.freedesktop.MediaPlayer.player.xml @@ -26,7 +26,7 @@ - + @@ -47,7 +47,7 @@ - + @@ -56,12 +56,12 @@ - + - + diff --git a/src/dbus/org.freedesktop.MediaPlayer.root.xml b/src/dbus/org.freedesktop.MediaPlayer.root.xml index 593e99177..6b8976ed0 100644 --- a/src/dbus/org.freedesktop.MediaPlayer.root.xml +++ b/src/dbus/org.freedesktop.MediaPlayer.root.xml @@ -13,7 +13,7 @@ - +
diff --git a/src/dbus/org.freedesktop.MediaPlayer.tracklist.xml b/src/dbus/org.freedesktop.MediaPlayer.tracklist.xml index db8aabdae..d2db72f32 100644 --- a/src/dbus/org.freedesktop.MediaPlayer.tracklist.xml +++ b/src/dbus/org.freedesktop.MediaPlayer.tracklist.xml @@ -7,7 +7,7 @@ - + diff --git a/src/dbus/org.freedesktop.Notifications.xml b/src/dbus/org.freedesktop.Notifications.xml index 41f733009..00e85ea53 100644 --- a/src/dbus/org.freedesktop.Notifications.xml +++ b/src/dbus/org.freedesktop.Notifications.xml @@ -22,7 +22,7 @@ - + diff --git a/src/dbus/org.freedesktop.UDisks.Device.xml b/src/dbus/org.freedesktop.UDisks.Device.xml index 816dd6ffc..99d1c459f 100644 --- a/src/dbus/org.freedesktop.UDisks.Device.xml +++ b/src/dbus/org.freedesktop.UDisks.Device.xml @@ -636,7 +636,7 @@ - + An array of triples (pid, uid, command line for the process @@ -1355,9 +1355,9 @@ - - - + + + diff --git a/src/dbus/org.freedesktop.UDisks.xml b/src/dbus/org.freedesktop.UDisks.xml index 07daea04d..f046d64bf 100644 --- a/src/dbus/org.freedesktop.UDisks.xml +++ b/src/dbus/org.freedesktop.UDisks.xml @@ -1051,7 +1051,7 @@ - + An array of file systems known to the daemon and what features are supported. Each element in the array contains the following members: diff --git a/src/dbus/org.mpris.MediaPlayer2.Player.xml b/src/dbus/org.mpris.MediaPlayer2.Player.xml index 3c11567fa..711a74e47 100644 --- a/src/dbus/org.mpris.MediaPlayer2.Player.xml +++ b/src/dbus/org.mpris.MediaPlayer2.Player.xml @@ -27,7 +27,7 @@ - + diff --git a/src/dbus/org.mpris.MediaPlayer2.Playlists.xml b/src/dbus/org.mpris.MediaPlayer2.Playlists.xml index f94b31f2f..ef4c28a3c 100644 --- a/src/dbus/org.mpris.MediaPlayer2.Playlists.xml +++ b/src/dbus/org.mpris.MediaPlayer2.Playlists.xml @@ -6,7 +6,7 @@ - + @@ -17,12 +17,12 @@ - + - + - + diff --git a/src/dbus/org.mpris.MediaPlayer2.TrackList.xml b/src/dbus/org.mpris.MediaPlayer2.TrackList.xml index 5b609c7b3..a08888cb8 100644 --- a/src/dbus/org.mpris.MediaPlayer2.TrackList.xml +++ b/src/dbus/org.mpris.MediaPlayer2.TrackList.xml @@ -6,7 +6,7 @@ - + @@ -26,7 +26,7 @@ - + @@ -34,7 +34,7 @@ - + diff --git a/src/devices/mtpconnection.cpp b/src/devices/mtpconnection.cpp index 009aad5eb..0c55d2778 100644 --- a/src/devices/mtpconnection.cpp +++ b/src/devices/mtpconnection.cpp @@ -20,6 +20,7 @@ #include #include +#include MtpConnection::MtpConnection(const QUrl& url) : device_(nullptr) { QString hostname = url.host(); @@ -34,19 +35,20 @@ MtpConnection::MtpConnection(const QUrl& url) : device_(nullptr) { const unsigned int bus_location = host_re.cap(1).toInt(); const unsigned int device_num = host_re.cap(2).toInt(); - if (url.hasQueryItem("vendor")) { + QUrlQuery url_query(url); + if (url_query.hasQueryItem("vendor")) { LIBMTP_raw_device_t* raw_device = (LIBMTP_raw_device_t*)malloc(sizeof(LIBMTP_raw_device_t)); raw_device->device_entry.vendor = - url.queryItemValue("vendor").toAscii().data(); + url_query.queryItemValue("vendor").toLatin1().data(); raw_device->device_entry.product = - url.queryItemValue("product").toAscii().data(); + url_query.queryItemValue("product").toLatin1().data(); raw_device->device_entry.vendor_id = - url.queryItemValue("vendor_id").toUShort(); + url_query.queryItemValue("vendor_id").toUShort(); raw_device->device_entry.product_id = - url.queryItemValue("product_id").toUShort(); + url_query.queryItemValue("product_id").toUShort(); raw_device->device_entry.device_flags = - url.queryItemValue("quirks").toUInt(); + url_query.queryItemValue("quirks").toUInt(); raw_device->bus_location = bus_location; raw_device->devnum = device_num; diff --git a/src/internet/box/boxservice.cpp b/src/internet/box/boxservice.cpp index 3a39caaad..46fdec844 100644 --- a/src/internet/box/boxservice.cpp +++ b/src/internet/box/boxservice.cpp @@ -18,7 +18,10 @@ #include "boxservice.h" -#include +#include +#include +#include +#include #include "core/application.h" #include "core/player.h" @@ -122,10 +125,9 @@ void BoxService::AddAuthorizationHeader(QNetworkRequest* request) const { void BoxService::FetchUserInfoFinished(QNetworkReply* reply) { reply->deleteLater(); - QJson::Parser parser; - QVariantMap response = parser.parse(reply).toMap(); + QJsonObject json_response = QJsonDocument::fromJson(reply->readAll()).object(); - QString name = response["name"].toString(); + QString name = json_response["name"].toString(); if (!name.isEmpty()) { QSettings s; s.beginGroup(kSettingsGroup); @@ -160,7 +162,9 @@ void BoxService::UpdateFiles() { void BoxService::InitialiseEventsCursor() { QUrl url(kEvents); - url.addQueryItem("stream_position", "now"); + QUrlQuery url_query; + url_query.addQueryItem("stream_position", "now"); + url.setQuery(url_query); QNetworkRequest request(url); AddAuthorizationHeader(&request); QNetworkReply* reply = network_->get(request); @@ -170,12 +174,11 @@ void BoxService::InitialiseEventsCursor() { void BoxService::InitialiseEventsFinished(QNetworkReply* reply) { reply->deleteLater(); - QJson::Parser parser; - QVariantMap response = parser.parse(reply).toMap(); - if (response.contains("next_stream_position")) { + QJsonObject json_response = QJsonDocument::fromJson(reply->readAll()).object(); + if (json_response.contains("next_stream_position")) { QSettings s; s.beginGroup(kSettingsGroup); - s.setValue("cursor", response["next_stream_position"]); + s.setValue("cursor", json_response["next_stream_position"].toString()); } } @@ -189,9 +192,11 @@ void BoxService::FetchRecursiveFolderItems(const int folder_id, << "modified_at" << "name"; QString fields_list = fields.join(","); - url.addQueryItem("fields", fields_list); - url.addQueryItem("limit", "1000"); // Maximum according to API docs. - url.addQueryItem("offset", QString::number(offset)); + QUrlQuery url_query (url); + url_query.addQueryItem("fields", fields_list); + url_query.addQueryItem("limit", "1000"); // Maximum according to API docs. + url_query.addQueryItem("offset", QString::number(offset)); + url.setQuery(url_query); QNetworkRequest request(url); AddAuthorizationHeader(&request); QNetworkReply* reply = network_->get(request); @@ -204,21 +209,18 @@ void BoxService::FetchFolderItemsFinished(QNetworkReply* reply, const int folder_id) { reply->deleteLater(); - QByteArray data = reply->readAll(); + QJsonObject json_response = QJsonDocument::fromJson(reply->readAll()).object(); - QJson::Parser parser; - QVariantMap response = parser.parse(data).toMap(); - - QVariantList entries = response["entries"].toList(); - const int total_entries = response["total_count"].toInt(); - const int offset = response["offset"].toInt(); + QJsonArray entries = json_response["entries"].toArray(); + const int total_entries = json_response["total_count"].toInt(); + const int offset = json_response["offset"].toInt(); if (entries.size() + offset < total_entries) { // Fetch the next page if necessary. FetchRecursiveFolderItems(folder_id, offset + entries.size()); } - for (const QVariant& e : entries) { - QVariantMap entry = e.toMap(); + for (const QJsonValue& e : entries) { + QJsonObject entry = e.toObject(); if (entry["type"].toString() == "folder") { FetchRecursiveFolderItems(entry["id"].toInt()); } else { @@ -227,16 +229,16 @@ void BoxService::FetchFolderItemsFinished(QNetworkReply* reply, } } -void BoxService::MaybeAddFileEntry(const QVariantMap& entry) { +void BoxService::MaybeAddFileEntry(const QJsonObject &entry) { QString mime_type = GuessMimeTypeForFile(entry["name"].toString()); QUrl url; url.setScheme("box"); - url.setPath(entry["id"].toString()); + url.setPath("/" + entry["id"].toString()); Song song; song.set_url(url); - song.set_ctime(entry["created_at"].toDateTime().toTime_t()); - song.set_mtime(entry["modified_at"].toDateTime().toTime_t()); + song.set_ctime(QDateTime::fromString(entry["created_at"].toString()).toTime_t()); + song.set_mtime(QDateTime::fromString(entry["modified_at"].toString()).toTime_t()); song.set_filesize(entry["size"].toInt()); song.set_title(entry["name"].toString()); @@ -271,8 +273,10 @@ void BoxService::RedirectFollowed(QNetworkReply* reply, const Song& song, void BoxService::UpdateFilesFromCursor(const QString& cursor) { QUrl url(kEvents); - url.addQueryItem("stream_position", cursor); - url.addQueryItem("limit", "5000"); + QUrlQuery url_query; + url_query.addQueryItem("stream_position", cursor); + url_query.addQueryItem("limit", "5000"); + url.setQuery(url_query); QNetworkRequest request(url); AddAuthorizationHeader(&request); QNetworkReply* reply = network_->get(request); @@ -283,18 +287,17 @@ void BoxService::UpdateFilesFromCursor(const QString& cursor) { void BoxService::FetchEventsFinished(QNetworkReply* reply) { // TODO(John Maguire): Page through events. reply->deleteLater(); - QJson::Parser parser; - QVariantMap response = parser.parse(reply).toMap(); + QJsonObject json_response = QJsonDocument::fromJson(reply->readAll()).object(); QSettings s; s.beginGroup(kSettingsGroup); - s.setValue("cursor", response["next_stream_position"]); + s.setValue("cursor", json_response["next_stream_position"].toString()); - QVariantList entries = response["entries"].toList(); - for (const QVariant& e : entries) { - QVariantMap event = e.toMap(); + QJsonArray entries = json_response["entries"].toArray(); + for (const QJsonValue& e : entries) { + QJsonObject event = e.toObject(); QString type = event["event_type"].toString(); - QVariantMap source = event["source"].toMap(); + QJsonObject source = event["source"].toObject(); if (source["type"] == "file") { if (type == "ITEM_UPLOAD") { // Add file. @@ -303,7 +306,7 @@ void BoxService::FetchEventsFinished(QNetworkReply* reply) { // Delete file. QUrl url; url.setScheme("box"); - url.setPath(source["id"].toString()); + url.setPath("/" + source["id"].toString()); Song song = library_backend_->GetSongByUrl(url); if (song.is_valid()) { library_backend_->DeleteSongs(SongList() << song); diff --git a/src/internet/box/boxservice.h b/src/internet/box/boxservice.h index 9748f680e..a7fd990aa 100644 --- a/src/internet/box/boxservice.h +++ b/src/internet/box/boxservice.h @@ -64,7 +64,7 @@ class BoxService : public CloudFileService { void UpdateFilesFromCursor(const QString& cursor); QNetworkReply* FetchContentUrlForFile(const QString& file_id); void InitialiseEventsCursor(); - void MaybeAddFileEntry(const QVariantMap& entry); + void MaybeAddFileEntry(const QJsonObject& entry); void EnsureConnected(); QString access_token_; diff --git a/src/internet/dropbox/dropboxauthenticator.cpp b/src/internet/dropbox/dropboxauthenticator.cpp index 22284ff32..3bc67db77 100644 --- a/src/internet/dropbox/dropboxauthenticator.cpp +++ b/src/internet/dropbox/dropboxauthenticator.cpp @@ -20,11 +20,12 @@ #include -#include - #include #include #include +#include +#include +#include #include "core/closure.h" #include "core/logging.h" @@ -98,8 +99,10 @@ void DropboxAuthenticator::Authorise() { SLOT(RedirectArrived(LocalRedirectServer*)), server); QUrl url(kAuthoriseEndpoint); - url.addQueryItem("oauth_token", token_); - url.addQueryItem("oauth_callback", server->url().toString()); + QUrlQuery url_query; + url_query.addQueryItem("oauth_token", token_); + url_query.addQueryItem("oauth_callback", server->url().toString()); + url.setQuery(url_query); QDesktopServices::openUrl(url); } @@ -108,7 +111,7 @@ void DropboxAuthenticator::RedirectArrived(LocalRedirectServer* server) { server->deleteLater(); QUrl request_url = server->request_url(); qLog(Debug) << Q_FUNC_INFO << request_url; - uid_ = request_url.queryItemValue("uid"); + uid_ = QUrlQuery(request_url).queryItemValue("uid"); RequestAccessToken(); } @@ -126,7 +129,7 @@ void DropboxAuthenticator::RequestAccessToken() { void DropboxAuthenticator::RequestAccessTokenFinished(QNetworkReply* reply) { reply->deleteLater(); - QString result = QString::fromAscii(reply->readAll()); + QString result = QString::fromLatin1(reply->readAll()); qLog(Debug) << result; QMap params = ParseParamList(result); access_token_ = params["oauth_token"]; @@ -174,8 +177,7 @@ void DropboxAuthenticator::RequestAccountInformation() { void DropboxAuthenticator::RequestAccountInformationFinished( QNetworkReply* reply) { reply->deleteLater(); - QJson::Parser parser; - QVariantMap response = parser.parse(reply).toMap(); - name_ = response["display_name"].toString(); + QJsonDocument document = QJsonDocument::fromBinaryData(reply->readAll()); + name_ = document.object()["display_name"].toString(); emit Finished(); } diff --git a/src/internet/dropbox/dropboxservice.cpp b/src/internet/dropbox/dropboxservice.cpp index 666dbc6e7..8bbd4f611 100644 --- a/src/internet/dropbox/dropboxservice.cpp +++ b/src/internet/dropbox/dropboxservice.cpp @@ -21,8 +21,10 @@ #include #include - -#include +#include +#include +#include +#include #include "core/application.h" #include "core/logging.h" @@ -103,9 +105,11 @@ void DropboxService::RequestFileList() { s.beginGroup(kSettingsGroup); QUrl url = QUrl(QString(kDeltaEndpoint)); + QUrlQuery url_query; if (s.contains("cursor")) { - url.addQueryItem("cursor", s.value("cursor").toString()); + url_query.addQueryItem("cursor", s.value("cursor").toString()); } + url.setQuery(url_query); QNetworkRequest request(url); request.setRawHeader("Authorization", GenerateAuthorisationHeader()); @@ -117,21 +121,22 @@ void DropboxService::RequestFileList() { void DropboxService::RequestFileListFinished(QNetworkReply* reply) { reply->deleteLater(); - QJson::Parser parser; - QVariantMap response = parser.parse(reply).toMap(); - if (response.contains("reset") && response["reset"].toBool()) { + QJsonDocument document = QJsonDocument::fromBinaryData(reply->readAll()); + QJsonObject json_response = document.object(); + + if (json_response.contains("reset") && json_response["reset"].toBool()) { qLog(Debug) << "Resetting Dropbox DB"; library_backend_->DeleteAll(); } QSettings settings; settings.beginGroup(kSettingsGroup); - settings.setValue("cursor", response["cursor"].toString()); + settings.setValue("cursor", json_response["cursor"].toString()); - QVariantList contents = response["entries"].toList(); + QJsonArray contents = json_response["entries"].toArray(); qLog(Debug) << "Delta found:" << contents.size(); - for (const QVariant& c : contents) { - QVariantList item = c.toList(); + for (const QJsonValue& c : contents) { + QJsonArray item = c.toArray(); QString path = item[0].toString(); QUrl url; @@ -148,7 +153,7 @@ void DropboxService::RequestFileListFinished(QNetworkReply* reply) { continue; } - QVariantMap metadata = item[1].toMap(); + QJsonObject metadata = item[1].toObject(); if (metadata["is_dir"].toBool()) { continue; } @@ -168,7 +173,7 @@ void DropboxService::RequestFileListFinished(QNetworkReply* reply) { } } - if (response.contains("has_more") && response["has_more"].toBool()) { + if (json_response.contains("has_more") && json_response["has_more"].toBool()) { RequestFileList(); } else { // Long-poll wait for changes. @@ -181,9 +186,11 @@ void DropboxService::LongPollDelta() { s.beginGroup(kSettingsGroup); QUrl request_url = QUrl(QString(kLongPollEndpoint)); + QUrlQuery url_query; if (s.contains("cursor")) { - request_url.addQueryItem("cursor", s.value("cursor").toString()); + url_query.addQueryItem("cursor", s.value("cursor").toString()); } + request_url.setQuery(url_query); QNetworkRequest request(request_url); request.setRawHeader("Authorization", GenerateAuthorisationHeader()); QNetworkReply* reply = network_->get(request); @@ -193,15 +200,14 @@ void DropboxService::LongPollDelta() { void DropboxService::LongPollFinished(QNetworkReply* reply) { reply->deleteLater(); - QJson::Parser parser; - QVariantMap response = parser.parse(reply).toMap(); - if (response["changes"].toBool()) { + QJsonObject json_response = QJsonDocument::fromBinaryData(reply->readAll()).object(); + if (json_response["changes"].toBool()) { // New changes, we should request deltas again. qLog(Debug) << "Detected new dropbox changes; fetching..."; RequestFileList(); } else { bool ok = false; - int backoff_secs = response["backoff"].toInt(&ok); + int backoff_secs = json_response["backoff"].toString().toInt(&ok); backoff_secs = ok ? backoff_secs : 0; QTimer::singleShot(backoff_secs * 1000, this, SLOT(LongPollDelta())); @@ -219,8 +225,7 @@ QNetworkReply* DropboxService::FetchContentUrl(const QUrl& url) { void DropboxService::FetchContentUrlFinished(QNetworkReply* reply, const QVariantMap& data) { reply->deleteLater(); - QJson::Parser parser; - QVariantMap response = parser.parse(reply).toMap(); + QJsonObject json_response = QJsonDocument::fromBinaryData(reply->readAll()).object(); QFileInfo info(data["path"].toString()); QUrl url; @@ -236,7 +241,7 @@ void DropboxService::FetchContentUrlFinished(QNetworkReply* reply, song.set_ctime(0); MaybeAddFileToDatabase(song, data["mime_type"].toString(), - QUrl::fromEncoded(response["url"].toByteArray()), + QUrl::fromEncoded(json_response["url"].toString().toLatin1()), QString::null); } @@ -244,7 +249,6 @@ QUrl DropboxService::GetStreamingUrlFromSongId(const QUrl& url) { QNetworkReply* reply = FetchContentUrl(url); WaitForSignal(reply, SIGNAL(finished())); - QJson::Parser parser; - QVariantMap response = parser.parse(reply).toMap(); - return QUrl::fromEncoded(response["url"].toByteArray()); + QJsonObject json_response = QJsonDocument::fromJson(reply->readAll()).object(); + return QUrl::fromEncoded(json_response["url"].toString().toLatin1()); } diff --git a/src/internet/googledrive/googledriveclient.cpp b/src/internet/googledrive/googledriveclient.cpp index e93cae44f..66e9a3eba 100644 --- a/src/internet/googledrive/googledriveclient.cpp +++ b/src/internet/googledrive/googledriveclient.cpp @@ -19,7 +19,12 @@ #include "googledriveclient.h" -#include +#include +#include +#include +#include +#include +#include #include "internet/core/oauthenticator.h" #include "core/closure.h" @@ -114,16 +119,15 @@ void Client::FetchUserInfoFinished(ConnectResponse* response, if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) != 200) { qLog(Warning) << "Failed to get user info" << reply->readAll(); } else { - QJson::Parser parser; - bool ok = false; - QVariantMap result = parser.parse(reply, &ok).toMap(); - if (!ok) { + QJsonParseError error; + QJsonDocument document = QJsonDocument::fromJson(reply->readAll(), &error); + if (error.error != QJsonParseError::NoError) { qLog(Error) << "Failed to parse user info reply"; return; } - qLog(Debug) << result; - response->user_email_ = result["email"].toString(); + qLog(Debug) << document; + response->user_email_ = document.object()["email"].toString(); qLog(Debug) << response->user_email_; } emit response->Finished(); @@ -157,16 +161,15 @@ GetFileResponse* Client::GetFile(const QString& file_id) { void Client::GetFileFinished(GetFileResponse* response, QNetworkReply* reply) { reply->deleteLater(); - QJson::Parser parser; - bool ok = false; - QVariantMap result = parser.parse(reply, &ok).toMap(); - if (!ok) { + QJsonParseError error; + QJsonDocument document = QJsonDocument::fromJson(reply->readAll(), &error); + if (error.error != QJsonParseError::NoError) { qLog(Error) << "Failed to fetch file with ID" << response->file_id_; emit response->Finished(); return; } - response->file_ = File(result); + response->file_ = File(document.object().toVariantMap()); emit response->Finished(); } @@ -179,13 +182,16 @@ ListChangesResponse* Client::ListChanges(const QString& cursor) { void Client::MakeListChangesRequest(ListChangesResponse* response, const QString& page_token) { QUrl url(kGoogleDriveChanges); + QUrlQuery url_query; if (!response->cursor().isEmpty()) { - url.addQueryItem("startChangeId", response->cursor()); + url_query.addQueryItem("startChangeId", response->cursor()); } if (!page_token.isEmpty()) { - url.addQueryItem("pageToken", page_token); + url_query.addQueryItem("pageToken", page_token); } + url.setQuery(url_query); + qLog(Debug) << "Requesting changes at:" << response->cursor() << page_token; QNetworkRequest request(url); @@ -201,33 +207,33 @@ void Client::ListChangesFinished(ListChangesResponse* response, QNetworkReply* reply) { reply->deleteLater(); - QJson::Parser parser; - bool ok = false; + QJsonParseError error; + QJsonDocument document = QJsonDocument::fromJson(reply->readAll(), &error); // TODO(John Maguire): Put this on a separate thread as the response could be large. - QVariantMap result = parser.parse(reply, &ok).toMap(); - if (!ok) { + if (error.error != QJsonParseError::NoError) { qLog(Error) << "Failed to fetch changes" << response->cursor(); emit response->Finished(); return; } - if (result.contains("largestChangeId")) { - response->next_cursor_ = result["largestChangeId"].toString(); + QJsonObject json_result = document.object(); + if (json_result.contains("largestChangeId")) { + response->next_cursor_ = json_result["largestChangeId"].toString(); } // Emit the FilesFound signal for the files in the response. FileList files; QList files_deleted; - for (const QVariant& v : result["items"].toList()) { - QVariantMap change = v.toMap(); + for (const QJsonValue & v : json_result["items"].toArray()) { + QJsonObject change = v.toObject(); if (change["deleted"].toBool() || - change["file"].toMap()["labels"].toMap()["trashed"].toBool()) { + change["file"].toObject()["labels"].toObject()["trashed"].toBool()) { QUrl url; url.setScheme("googledrive"); - url.setPath(change["fileId"].toString()); + url.setPath("/" + change["fileId"].toString()); files_deleted << url; } else { - files << File(change["file"].toMap()); + files << File(change["file"].toObject().toVariantMap()); } } @@ -235,8 +241,8 @@ void Client::ListChangesFinished(ListChangesResponse* response, emit response->FilesDeleted(files_deleted); // Get the next page of results if there is one. - if (result.contains("nextPageToken")) { - MakeListChangesRequest(response, result["nextPageToken"].toString()); + if (json_result.contains("nextPageToken")) { + MakeListChangesRequest(response, json_result["nextPageToken"].toString()); } else { emit response->Finished(); } diff --git a/src/internet/googledrive/googledriveservice.cpp b/src/internet/googledrive/googledriveservice.cpp index d7b106677..cc1797b25 100644 --- a/src/internet/googledrive/googledriveservice.cpp +++ b/src/internet/googledrive/googledriveservice.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "core/application.h" #include "core/closure.h" @@ -163,7 +164,7 @@ void GoogleDriveService::FilesFound(const QList& files) { QUrl url; url.setScheme("googledrive"); - url.setPath(file.id()); + url.setPath("/" + file.id()); Song song; // Add some extra tags from the Google Drive metadata. @@ -204,7 +205,9 @@ QUrl GoogleDriveService::GetStreamingUrlFromSongId(const QString& id) { loop.exec(); QUrl url(response->file().download_url()); - url.addQueryItem("access_token", client_->access_token()); + QUrlQuery url_query(url); + url_query.addQueryItem("access_token", client_->access_token()); + url.setQuery(url_query); return url; } diff --git a/src/internet/lastfm/lastfmcompat.h b/src/internet/lastfm/lastfmcompat.h index 7ca9acf5d..c0681869f 100644 --- a/src/internet/lastfm/lastfmcompat.h +++ b/src/internet/lastfm/lastfmcompat.h @@ -24,21 +24,21 @@ #include "fixlastfm.h" #ifdef HAVE_LIBLASTFM1 -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #else -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #endif namespace lastfm { diff --git a/src/internet/lastfm/lastfmservice.cpp b/src/internet/lastfm/lastfmservice.cpp index 243e5858d..11d20c905 100644 --- a/src/internet/lastfm/lastfmservice.cpp +++ b/src/internet/lastfm/lastfmservice.cpp @@ -213,7 +213,7 @@ void LastFMService::UpdateSubscriberStatusFinished(QNetworkReply* reply) { QUrl LastFMService::FixupUrl(const QUrl& url) { QUrl ret; - ret.setEncodedUrl(url.toEncoded().replace( + ret.setUrl(url.toEncoded().replace( "USERNAME", QUrl::toPercentEncoding(lastfm::ws::Username))); return ret; } diff --git a/src/internet/seafile/seafileservice.cpp b/src/internet/seafile/seafileservice.cpp index 27a5b4bed..4ce2b802e 100644 --- a/src/internet/seafile/seafileservice.cpp +++ b/src/internet/seafile/seafileservice.cpp @@ -22,8 +22,11 @@ #include -#include #include +#include +#include +#include +#include #include "core/application.h" #include "core/player.h" @@ -80,7 +83,7 @@ bool SeafileService::has_credentials() const { void SeafileService::AddAuthorizationHeader(QNetworkRequest* request) const { request->setRawHeader("Authorization", - QString("Token %1").arg(access_token_).toAscii()); + QString("Token %1").arg(access_token_).toLatin1()); } void SeafileService::ForgetCredentials() { @@ -98,13 +101,15 @@ void SeafileService::ForgetCredentials() { bool SeafileService::GetToken(const QString& mail, const QString& password, const QString& server) { QUrl url(server + kAuthTokenUrl); + QUrlQuery url_query; + + url_query.addQueryItem("username", mail); + url_query.addQueryItem("password", password); + QNetworkRequest request(url); AddAuthorizationHeader(&request); - url.addQueryItem("username", mail); - url.addQueryItem("password", password); - - QNetworkReply* reply = network_->post(request, url.encodedQuery()); + QNetworkReply* reply = network_->post(request, url_query.toString().toLatin1()); WaitForSignal(reply, SIGNAL(finished())); if (!CheckReply(&reply)) { @@ -114,11 +119,10 @@ bool SeafileService::GetToken(const QString& mail, const QString& password, reply->deleteLater(); - QJson::Parser parser; - QVariantMap response = parser.parse(reply->readAll()).toMap(); + QJsonObject json_response = QJsonDocument::fromJson(reply->readAll()).object(); // Because the server responds "token" - access_token_ = response["token"].toString().replace("\"", ""); + access_token_ = json_response["token"].toString().replace("\"", ""); if (access_token_.isEmpty()) { return false; @@ -156,11 +160,11 @@ void SeafileService::GetLibrariesFinished(QNetworkReply* reply) { // key : id, value : name QMap libraries; QByteArray data = reply->readAll(); - QJson::Parser parser; - QList repos = parser.parse(data).toList(); - for (int i = 0; i < repos.size(); ++i) { - QVariantMap repo = repos.at(i).toMap(); + QJsonArray json_repos = QJsonDocument::fromJson(data).array(); + + for (const QJsonValue & json_repo: json_repos) { + QJsonObject repo = json_repo.toObject(); QString repo_name = repo["name"].toString(), repo_id = repo["id"].toString(); @@ -246,7 +250,9 @@ void SeafileService::UpdateLibrariesInProgress( QNetworkReply* SeafileService::PrepareFetchFolderItems(const QString& library, const QString& path) { QUrl url(server_ + QString(kFolderItemsUrl).arg(library)); - url.addQueryItem("p", path); + QUrlQuery url_query; + url_query.addQueryItem("p", path); + url.setQuery(url_query); QNetworkRequest request(url); AddAuthorizationHeader(&request); @@ -277,12 +283,11 @@ void SeafileService::FetchAndCheckFolderItemsFinished( QByteArray data = reply->readAll(); - QJson::Parser parser; - QList variant_entries = parser.parse(data).toList(); + QJsonArray json_entries = QJsonDocument::fromJson(data).array(); SeafileTree::Entries entries; - for (const QVariant& e : variant_entries) { - QVariantMap entry = e.toMap(); + for (const QJsonValue& e : json_entries) { + QJsonObject entry = e.toObject(); SeafileTree::Entry::Type entry_type = SeafileTree::Entry::StringToType(entry["type"].toString()); QString entry_name = entry["name"].toString(); @@ -322,14 +327,13 @@ void SeafileService::AddRecursivelyFolderItemsFinished(QNetworkReply* reply, reply->deleteLater(); QByteArray data = reply->readAll(); - QJson::Parser parser; - QList entries = parser.parse(data).toList(); + QJsonArray json_entries = QJsonDocument::fromJson(data).array(); - for (const QVariant& e : entries) { - QVariantMap entry_map = e.toMap(); + for (const QJsonValue& e : json_entries) { + QJsonObject json_entry = e.toObject(); SeafileTree::Entry::Type entry_type = - SeafileTree::Entry::StringToType(entry_map["type"].toString()); - QString entry_name = entry_map["name"].toString(); + SeafileTree::Entry::StringToType(json_entry["type"].toString()); + QString entry_name = json_entry["name"].toString(); // We just want libraries/directories and files which could be songs. if (entry_type == SeafileTree::Entry::NONE) { @@ -339,7 +343,7 @@ void SeafileService::AddRecursivelyFolderItemsFinished(QNetworkReply* reply, continue; } - SeafileTree::Entry entry(entry_name, entry_map["id"].toString(), + SeafileTree::Entry entry(entry_name, json_entry["id"].toString(), entry_type); // If AddEntry was not successful we stop @@ -360,7 +364,9 @@ void SeafileService::AddRecursivelyFolderItemsFinished(QNetworkReply* reply, QNetworkReply* SeafileService::PrepareFetchContentForFile( const QString& library, const QString& filepath) { QUrl content_url(server_ + QString(kFileContentUrl).arg(library)); - content_url.addQueryItem("p", filepath); + QUrlQuery content_url_query; + content_url_query.addQueryItem("p", filepath); + content_url.setQuery(content_url_query); QNetworkRequest request(content_url); AddAuthorizationHeader(&request); @@ -397,23 +403,22 @@ void SeafileService::MaybeAddFileEntryInProgress(QNetworkReply* reply, QByteArray data = reply->readAll(); - QJson::Parser parser; - QVariantMap entry_detail_map = parser.parse(data).toMap(); + QJsonObject json_entry_detail = QJsonDocument::fromJson(data).object(); QUrl url; url.setScheme("seafile"); - url.setPath("/" + library + path + entry_detail_map["name"].toString()); + url.setPath("/" + library + path + json_entry_detail["name"].toString()); Song song; song.set_url(url); song.set_ctime(0); - song.set_mtime(entry_detail_map["mtime"].toInt()); - song.set_filesize(entry_detail_map["size"].toInt()); - song.set_title(entry_detail_map["name"].toString()); + song.set_mtime(json_entry_detail["mtime"].toInt()); + song.set_filesize(json_entry_detail["size"].toInt()); + song.set_title(json_entry_detail["name"].toString()); // Get the download url of the entry reply = PrepareFetchContentUrlForFile( - library, path + entry_detail_map["name"].toString()); + library, path + json_entry_detail["name"].toString()); NewClosure( reply, SIGNAL(finished()), this, SLOT(FetchContentUrlForFileFinished(QNetworkReply*, Song, QString)), @@ -423,7 +428,9 @@ void SeafileService::MaybeAddFileEntryInProgress(QNetworkReply* reply, QNetworkReply* SeafileService::PrepareFetchContentUrlForFile( const QString& library, const QString& filepath) { QUrl content_url(server_ + QString(kFileUrl).arg(library)); - content_url.addQueryItem("p", filepath); + QUrlQuery content_url_query; + content_url_query.addQueryItem("p", filepath); + content_url.setQuery(content_url_query); QNetworkRequest request(content_url); AddAuthorizationHeader(&request); @@ -589,7 +596,7 @@ bool SeafileService::CheckReply(QNetworkReply** reply, int tries) { // Unknown, 404 ... (*reply)->deleteLater(); - qLog(Warning) << "Error for reply : " << status_code_variant.toInt(); + qLog(Warning) << "Error with the reply : " << status_code_variant.toInt(); return false; } diff --git a/src/internet/skydrive/skydriveservice.cpp b/src/internet/skydrive/skydriveservice.cpp index 91bfce90c..c8f001429 100644 --- a/src/internet/skydrive/skydriveservice.cpp +++ b/src/internet/skydrive/skydriveservice.cpp @@ -19,9 +19,12 @@ #include "skydriveservice.h" -#include +#include +#include +#include +#include -#include +#include #include "core/application.h" #include "core/player.h" @@ -107,10 +110,9 @@ void SkydriveService::AddAuthorizationHeader(QNetworkRequest* request) { void SkydriveService::FetchUserInfoFinished(QNetworkReply* reply) { reply->deleteLater(); - QJson::Parser parser; - QVariantMap response = parser.parse(reply).toMap(); + QJsonObject json_response = QJsonDocument::fromBinaryData(reply->readAll()).object(); - QString name = response["name"].toString(); + QString name = json_response["name"].toString(); if (!name.isEmpty()) { QSettings s; s.beginGroup(kSettingsGroup); @@ -124,7 +126,9 @@ void SkydriveService::FetchUserInfoFinished(QNetworkReply* reply) { void SkydriveService::ListFiles(const QString& folder) { QUrl url(QString(kSkydriveBase) + folder + "/files"); - url.addQueryItem("filter", "audio,folders"); + QUrlQuery url_query; + url_query.addQueryItem("filter", "audio,folders"); + url.setQuery(url_query); QNetworkRequest request(url); AddAuthorizationHeader(&request); @@ -135,27 +139,26 @@ void SkydriveService::ListFiles(const QString& folder) { void SkydriveService::ListFilesFinished(QNetworkReply* reply) { reply->deleteLater(); - QJson::Parser parser; - QVariantMap response = parser.parse(reply).toMap(); + QJsonObject json_response = QJsonDocument::fromBinaryData(reply->readAll()).object(); - QVariantList files = response["data"].toList(); - for (const QVariant& f : files) { - QVariantMap file = f.toMap(); + QJsonArray files = json_response["data"].toArray(); + for (const QJsonValue& f : files) { + QJsonObject file = f.toObject(); if (file["type"].toString() == "audio") { QString mime_type = GuessMimeTypeForFile(file["name"].toString()); QUrl url; url.setScheme("skydrive"); - url.setPath(file["id"].toString()); + url.setPath("/" + file["id"].toString()); Song song; song.set_url(url); - song.set_ctime(file["created_time"].toDateTime().toTime_t()); - song.set_mtime(file["updated_time"].toDateTime().toTime_t()); + song.set_ctime(QDateTime::fromString(file["created_time"].toString()).toTime_t()); + song.set_mtime(QDateTime::fromString(file["updated_time"].toString()).toTime_t()); song.set_comment(file["description"].toString()); song.set_filesize(file["size"].toInt()); song.set_title(file["name"].toString()); - QUrl download_url = file["source"].toUrl(); + QUrl download_url(file["source"].toString()); // HTTPS appears to be broken somehow between Qt & Skydrive downloads. // Fortunately, just changing the scheme to HTTP works. download_url.setScheme("http"); @@ -175,9 +178,8 @@ QUrl SkydriveService::GetStreamingUrlFromSongId(const QString& file_id) { std::unique_ptr reply(network_->get(request)); WaitForSignal(reply.get(), SIGNAL(finished())); - QJson::Parser parser; - QVariantMap response = parser.parse(reply.get()).toMap(); - return response["source"].toUrl(); + QJsonObject json_response = QJsonDocument::fromBinaryData(reply.get()->readAll()).object(); + return QUrl(json_response["source"].toString()); } void SkydriveService::EnsureConnected() { diff --git a/src/internet/vk/vkconnection.cpp b/src/internet/vk/vkconnection.cpp index d44a65e65..3fd8353ea 100644 --- a/src/internet/vk/vkconnection.cpp +++ b/src/internet/vk/vkconnection.cpp @@ -21,8 +21,10 @@ #include #include - -#include +#include +#include +#include +#include #include "core/closure.h" #include "core/logging.h" @@ -95,18 +97,22 @@ bool VkConnection::hasAccount() { QNetworkRequest VkConnection::makeRequest(const QString& method, const QVariantMap& args) { QUrl url = kApiUrl; - url.setPath(url.path() % QLatin1Literal("/") % method); + url.setPath(url.path() + "/" + method); + QUrlQuery url_query; for (auto it = args.constBegin(); it != args.constEnd(); ++it) { - url.addEncodedQueryItem(QUrl::toPercentEncoding(it.key()), + url_query.addQueryItem(QUrl::toPercentEncoding(it.key()), QUrl::toPercentEncoding(it.value().toString())); } - url.addEncodedQueryItem("access_token", access_token_); + url_query.addQueryItem("access_token", access_token_); + url.setQuery(url_query); return QNetworkRequest(url); } void VkConnection::decorateRequest(QNetworkRequest& request) { QUrl url = request.url(); - url.addEncodedQueryItem("access_token", access_token_); + QUrlQuery url_query(url); + url_query.addQueryItem("access_token", access_token_); + url.setQuery(url_query); request.setUrl(url); } @@ -115,11 +121,13 @@ void VkConnection::requestAccessToken() { server->Listen(); QUrl url = kVkOAuthEndpoint; - url.addQueryItem("client_id", kAppID); - url.addQueryItem("scope", + QUrlQuery url_query; + url_query.addQueryItem("client_id", kAppID); + url_query.addQueryItem("scope", Vreen::flagsToStrList(kScopes, kScopeNames).join(",")); - url.addQueryItem("redirect_uri", server->url().toString()); - url.addQueryItem("response_type", "code"); + url_query.addQueryItem("redirect_uri", server->url().toString()); + url_query.addQueryItem("response_type", "code"); + url.setQuery(url_query); qLog(Debug) << "Try to login to Vk.com" << url; @@ -130,13 +138,16 @@ void VkConnection::requestAccessToken() { } void VkConnection::codeRecived(LocalRedirectServer* server, QUrl redirect_uri) { - if (server->request_url().hasQueryItem("code")) { - code_ = server->request_url().queryItemValue("code").toUtf8(); + QUrlQuery url_query_server(server->request_url()); + if (url_query_server.hasQueryItem("code")) { + code_ = url_query_server.queryItemValue("code").toUtf8(); QUrl url = kVkOAuthTokenEndpoint; - url.addQueryItem("client_id", kAppID); - url.addQueryItem("client_secret", kAppSecret); - url.addQueryItem("code", QString::fromUtf8(code_)); - url.addQueryItem("redirect_uri", redirect_uri.toString()); + QUrlQuery url_query; + url_query.addQueryItem("client_id", kAppID); + url_query.addQueryItem("client_secret", kAppSecret); + url_query.addQueryItem("code", QString::fromUtf8(code_)); + url_query.addQueryItem("redirect_uri", redirect_uri.toString()); + url.setQuery(url_query); qLog(Debug) << "Getting access token" << url; QNetworkRequest request(url); @@ -159,21 +170,22 @@ void VkConnection::accessTokenRecived(QNetworkReply* reply) { return; } - QJson::Parser parser; - bool ok = false; QByteArray reply_data = reply->readAll(); - QVariantMap result = parser.parse(reply_data, &ok).toMap(); - if (!ok) { + QJsonParseError error; + QJsonDocument document = QJsonDocument::fromJson(reply_data, &error); + if (error.error != QJsonParseError::NoError) { qLog(Error) << "Failed to parse oauth reply" << reply_data; emit setConnectionState(Vreen::Client::StateOffline); clear(); return; } - qLog(Debug) << result; - access_token_ = result["access_token"].toByteArray(); - expires_in_ = result["expires_in"].toUInt(); - uid_ = result["user_id"].toInt(); + QJsonObject json_result = document.object(); + qLog(Debug) << json_result; + + access_token_ = json_result["access_token"].toString().toLatin1(); + expires_in_ = json_result["expires_in"].toString().toUInt(); + uid_ = json_result["user_id"].toInt(); if (expires_in_) { expires_in_ += QDateTime::currentDateTime().toTime_t(); diff --git a/src/internet/vk/vkmusiccache.cpp b/src/internet/vk/vkmusiccache.cpp index 62033948c..c802818e3 100644 --- a/src/internet/vk/vkmusiccache.cpp +++ b/src/internet/vk/vkmusiccache.cpp @@ -130,7 +130,7 @@ void VkMusicCache::DownloadNext() { void VkMusicCache::DownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { if (bytesTotal) { - int progress = qRound(100 * bytesReceived / bytesTotal); + int progress = qRound(100. * bytesReceived / bytesTotal); app_->task_manager()->SetTaskProgress(task_id, progress, 100); } } diff --git a/src/moodbar/moodbarpipeline.cpp b/src/moodbar/moodbarpipeline.cpp index 7163efda1..d5409211d 100644 --- a/src/moodbar/moodbarpipeline.cpp +++ b/src/moodbar/moodbarpipeline.cpp @@ -57,7 +57,7 @@ bool MoodbarPipeline::IsAvailable() { GstElement* MoodbarPipeline::CreateElement(const QString& factory_name) { GstElement* ret = - gst_element_factory_make(factory_name.toAscii().constData(), nullptr); + gst_element_factory_make(factory_name.toLatin1().constData(), nullptr); if (ret) { gst_bin_add(GST_BIN(pipeline_), ret); diff --git a/src/ui/ripcd.cpp b/src/ui/ripcd.cpp index bf8a329a8..cbcd62670 100644 --- a/src/ui/ripcd.cpp +++ b/src/ui/ripcd.cpp @@ -75,11 +75,11 @@ RipCD::RipCD(QWidget* parent) ui_->setupUi(this); // Set column widths in the QTableWidget. - ui_->tableWidget->horizontalHeader()->setResizeMode( + ui_->tableWidget->horizontalHeader()->setSectionResizeMode( kCheckboxColumn, QHeaderView::ResizeToContents); - ui_->tableWidget->horizontalHeader()->setResizeMode( + ui_->tableWidget->horizontalHeader()->setSectionResizeMode( kTrackNumberColumn, QHeaderView::ResizeToContents); - ui_->tableWidget->horizontalHeader()->setResizeMode(kTrackTitleColumn, + ui_->tableWidget->horizontalHeader()->setSectionResizeMode(kTrackTitleColumn, QHeaderView::Stretch); // Add a rip button diff --git a/src/widgets/osd_x11.cpp b/src/widgets/osd_x11.cpp index a79bc841c..d5e10436b 100644 --- a/src/widgets/osd_x11.cpp +++ b/src/widgets/osd_x11.cpp @@ -66,7 +66,7 @@ QDBusArgument& operator<<(QDBusArgument& arg, const QImage& image) { int channels = i.isGrayscale() ? 1 : (i.hasAlphaChannel() ? 4 : 3); arg << i.depth() / channels; arg << channels; - arg << QByteArray(reinterpret_cast(i.bits()), i.numBytes()); + arg << QByteArray(reinterpret_cast(i.bits()), i.byteCount()); arg.endStructure(); return arg; } diff --git a/src/wiimotedev/wiimotesettingspage.cpp b/src/wiimotedev/wiimotesettingspage.cpp index 3c9adfcf3..77f780aab 100644 --- a/src/wiimotedev/wiimotesettingspage.cpp +++ b/src/wiimotedev/wiimotesettingspage.cpp @@ -26,7 +26,7 @@ WiimoteSettingsPage::WiimoteSettingsPage(SettingsDialog* dialog) : SettingsPage(dialog), ui_(new Ui_WiimoteSettingsPage) { ui_->setupUi(this); - ui_->list->header()->setResizeMode(QHeaderView::ResizeToContents); + ui_->list->header()->setSectionResizeMode(QHeaderView::ResizeToContents); setWindowIcon(QIcon(":/icons/32x32/wiimotedev.png")); text_buttons_.insert(WIIMOTE_BTN_1, "Wiiremote 1"); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7c46c02d2..95c954d00 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -74,14 +74,14 @@ qt5_wrap_cpp(TESTUTILS-SOURCES-MOC ${TESTUTILS-MOC-HEADERS}) add_library(test_utils STATIC EXCLUDE_FROM_ALL ${TESTUTILS-SOURCES} ${TESTUTILS-SOURCES-MOC}) target_link_libraries(test_utils ${GMOCK_LIBRARIES} ${QT_LIBRARIES} ${QT_QTTEST_LIBRARY}) -add_custom_target(test - echo "Running tests" +add_custom_target(clementine_test + echo "Running Clementine tests" WORKING_DIRECTORY ${CURRENT_BINARY_DIR} ) add_custom_target(build_tests WORKING_DIRECTORY ${CURRENT_BINARY_DIR} ) -add_dependencies(test build_tests) +add_dependencies(clementine_test build_tests) qt5_add_resources(TEST-RESOURCE-SOURCES data/testdata.qrc) @@ -112,7 +112,7 @@ macro(add_test_file test_source gui_required) set_target_properties(${TEST_NAME} PROPERTIES COMPILE_FLAGS "-Wno-bool-conversions") endif (SUPPORTS_NOBOOL) - add_custom_command(TARGET test POST_BUILD + add_custom_command(TARGET clementine_test POST_BUILD COMMAND ./${TEST_NAME}${CMAKE_EXECUTABLE_SUFFIX}) add_dependencies(build_tests ${TEST_NAME}) endmacro (add_test_file) From 4d0e413fb96b20f8c445c49e03c5e10c3d16f660 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 16 Apr 2015 15:06:00 +0200 Subject: [PATCH 011/104] Finally use of qtsingleapplication adapted to qt5 --- 3rdparty/qtsingleapplication/CMakeLists.txt | 28 + 3rdparty/qtsingleapplication/LICENSE.LGPL | 504 ++++++++++++++++++ 3rdparty/qtsingleapplication/qtlocalpeer.cpp | 200 +++++++ 3rdparty/qtsingleapplication/qtlocalpeer.h | 76 +++ 3rdparty/qtsingleapplication/qtlockedfile.cpp | 192 +++++++ 3rdparty/qtsingleapplication/qtlockedfile.h | 96 ++++ .../qtsingleapplication/qtlockedfile_unix.cpp | 114 ++++ .../qtsingleapplication/qtlockedfile_win.cpp | 214 ++++++++ .../qtsingleapplication.cpp | 331 ++++++++++++ .../qtsingleapplication/qtsingleapplication.h | 101 ++++ .../qtsinglecoreapplication.cpp | 148 +++++ .../qtsinglecoreapplication.h | 70 +++ 3rdparty/singleapplication/CMakeLists.txt | 20 - 3rdparty/singleapplication/LICENSE | 21 - .../singleapplication/singleapplication.cpp | 48 -- .../singleapplication/singleapplication.h | 32 -- .../singlecoreapplication.cpp | 48 -- .../singleapplication/singlecoreapplication.h | 32 -- CMakeLists.txt | 15 +- src/CMakeLists.txt | 7 +- src/main.cpp | 26 +- src/ui/mainwindow.cpp | 4 +- src/ui/mainwindow.h | 2 +- 23 files changed, 2113 insertions(+), 216 deletions(-) create mode 100644 3rdparty/qtsingleapplication/CMakeLists.txt create mode 100644 3rdparty/qtsingleapplication/LICENSE.LGPL create mode 100644 3rdparty/qtsingleapplication/qtlocalpeer.cpp create mode 100644 3rdparty/qtsingleapplication/qtlocalpeer.h create mode 100644 3rdparty/qtsingleapplication/qtlockedfile.cpp create mode 100644 3rdparty/qtsingleapplication/qtlockedfile.h create mode 100644 3rdparty/qtsingleapplication/qtlockedfile_unix.cpp create mode 100644 3rdparty/qtsingleapplication/qtlockedfile_win.cpp create mode 100644 3rdparty/qtsingleapplication/qtsingleapplication.cpp create mode 100644 3rdparty/qtsingleapplication/qtsingleapplication.h create mode 100644 3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp create mode 100644 3rdparty/qtsingleapplication/qtsinglecoreapplication.h delete mode 100644 3rdparty/singleapplication/CMakeLists.txt delete mode 100644 3rdparty/singleapplication/LICENSE delete mode 100644 3rdparty/singleapplication/singleapplication.cpp delete mode 100644 3rdparty/singleapplication/singleapplication.h delete mode 100644 3rdparty/singleapplication/singlecoreapplication.cpp delete mode 100644 3rdparty/singleapplication/singlecoreapplication.h diff --git a/3rdparty/qtsingleapplication/CMakeLists.txt b/3rdparty/qtsingleapplication/CMakeLists.txt new file mode 100644 index 000000000..975881adb --- /dev/null +++ b/3rdparty/qtsingleapplication/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 2.6) + +set(SINGLEAPP-SOURCES + qtlocalpeer.cpp + qtsingleapplication.cpp + qtsinglecoreapplication.cpp +) + +set(SINGLEAPP-MOC-HEADERS + qtlocalpeer.h + qtsingleapplication.h + qtsinglecoreapplication.h +) + +if(WIN32) + set(SINGLEAPP-SOURCES ${SINGLEAPP-SOURCES} qtlockedfile_win.cpp) +elseif(WIN32) + set(SINGLEAPP-SOURCES ${SINGLEAPP-SOURCES} qtlockedfile_unix.cpp) +endif(WIN32) + +QT5_WRAP_CPP(SINGLEAPP-SOURCES-MOC ${SINGLEAPP-MOC-HEADERS}) + +ADD_LIBRARY(qtsingleapplication STATIC + ${SINGLEAPP-SOURCES} + ${SINGLEAPP-SOURCES-MOC} +) + +QT5_USE_MODULES(qtsingleapplication Core Widgets Network) diff --git a/3rdparty/qtsingleapplication/LICENSE.LGPL b/3rdparty/qtsingleapplication/LICENSE.LGPL new file mode 100644 index 000000000..5ab7695ab --- /dev/null +++ b/3rdparty/qtsingleapplication/LICENSE.LGPL @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 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. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +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 and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + + 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 Library or any portion +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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 with +this License. + + 11. 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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +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. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser 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 Library +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. 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. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; 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. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/3rdparty/qtsingleapplication/qtlocalpeer.cpp b/3rdparty/qtsingleapplication/qtlocalpeer.cpp new file mode 100644 index 000000000..1c89e3c00 --- /dev/null +++ b/3rdparty/qtsingleapplication/qtlocalpeer.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "qtlocalpeer.h" +#include +#include +#include + +#if defined(Q_OS_WIN) +#include +#include +typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); +static PProcessIdToSessionId pProcessIdToSessionId = 0; +#endif +#if defined(Q_OS_UNIX) +#include +#endif + +namespace QtLP_Private { +#include "qtlockedfile.cpp" +#if defined(Q_OS_WIN) +#include "qtlockedfile_win.cpp" +#else +#include "qtlockedfile_unix.cpp" +#endif +} + +const char* QtLocalPeer::ack = "ack"; + +QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId) + : QObject(parent), id(appId) +{ + QString prefix = id; + if (id.isEmpty()) { + id = QCoreApplication::applicationFilePath(); +#if defined(Q_OS_WIN) + id = id.toLower(); +#endif + prefix = id.section(QLatin1Char('/'), -1); + } + prefix.remove(QRegExp("[^a-zA-Z]")); + prefix.truncate(6); + + QByteArray idc = id.toUtf8(); + quint16 idNum = qChecksum(idc.constData(), idc.size()); + socketName = QLatin1String("qtsingleapp-") + prefix + + QLatin1Char('-') + QString::number(idNum, 16); + +#if defined(Q_OS_WIN) + if (!pProcessIdToSessionId) { + QLibrary lib("kernel32"); + pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); + } + if (pProcessIdToSessionId) { + DWORD sessionId = 0; + pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); + socketName += QLatin1Char('-') + QString::number(sessionId, 16); + } +#else + socketName += QLatin1Char('-') + QString::number(::getuid(), 16); +#endif + + server = new QLocalServer(this); + QString lockName = QDir(QDir::tempPath()).absolutePath() + + QLatin1Char('/') + socketName + + QLatin1String("-lockfile"); + lockFile.setFileName(lockName); + lockFile.open(QIODevice::ReadWrite); +} + + + +bool QtLocalPeer::isClient() +{ + if (lockFile.isLocked()) + return false; + + if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) + return true; + + bool res = server->listen(socketName); +#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0)) + // ### Workaround + if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { + QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); + res = server->listen(socketName); + } +#endif + if (!res) + qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); + QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection())); + return false; +} + + +bool QtLocalPeer::sendMessage(const QString &message, int timeout) +{ + if (!isClient()) + return false; + + QLocalSocket socket; + bool connOk = false; + for(int i = 0; i < 2; i++) { + // Try twice, in case the other instance is just starting up + socket.connectToServer(socketName); + connOk = socket.waitForConnected(timeout/2); + if (connOk || i) + break; + int ms = 250; +#if defined(Q_OS_WIN) + Sleep(DWORD(ms)); +#else + struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; + nanosleep(&ts, NULL); +#endif + } + if (!connOk) + return false; + + QByteArray uMsg(message.toUtf8()); + QDataStream ds(&socket); + ds.writeBytes(uMsg.constData(), uMsg.size()); + bool res = socket.waitForBytesWritten(timeout); + if (res) { + res &= socket.waitForReadyRead(timeout); // wait for ack + if (res) + res &= (socket.read(qstrlen(ack)) == ack); + } + return res; +} + + +void QtLocalPeer::receiveConnection() +{ + QLocalSocket* socket = server->nextPendingConnection(); + if (!socket) + return; + + while (socket->bytesAvailable() < (int)sizeof(quint32)) + socket->waitForReadyRead(); + QDataStream ds(socket); + QByteArray uMsg; + quint32 remaining; + ds >> remaining; + uMsg.resize(remaining); + int got = 0; + char* uMsgBuf = uMsg.data(); + do { + got = ds.readRawData(uMsgBuf, remaining); + remaining -= got; + uMsgBuf += got; + } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); + if (got < 0) { + qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); + delete socket; + return; + } + QString message(QString::fromUtf8(uMsg)); + socket->write(ack, qstrlen(ack)); + socket->waitForBytesWritten(1000); + delete socket; + emit messageReceived(message); //### (might take a long time to return) +} diff --git a/3rdparty/qtsingleapplication/qtlocalpeer.h b/3rdparty/qtsingleapplication/qtlocalpeer.h new file mode 100644 index 000000000..7b3fa8159 --- /dev/null +++ b/3rdparty/qtsingleapplication/qtlocalpeer.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#ifndef QTLOCALPEER_H +#define QTLOCALPEER_H + +#include +#include +#include + +#include "qtlockedfile.h" + +class QtLocalPeer : public QObject +{ + Q_OBJECT + +public: + QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); + bool isClient(); + bool sendMessage(const QString &message, int timeout); + QString applicationId() const + { return id; } + +Q_SIGNALS: + void messageReceived(const QString &message); + +protected Q_SLOTS: + void receiveConnection(); + +protected: + QString id; + QString socketName; + QLocalServer* server; + QtLP_Private::QtLockedFile lockFile; + +private: + static const char* ack; +}; + +#endif // QTLOCALPEER_H diff --git a/3rdparty/qtsingleapplication/qtlockedfile.cpp b/3rdparty/qtsingleapplication/qtlockedfile.cpp new file mode 100644 index 000000000..3e73ba652 --- /dev/null +++ b/3rdparty/qtsingleapplication/qtlockedfile.cpp @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "qtlockedfile.h" + +/*! + \class QtLockedFile + + \brief The QtLockedFile class extends QFile with advisory locking + functions. + + A file may be locked in read or write mode. Multiple instances of + \e QtLockedFile, created in multiple processes running on the same + machine, may have a file locked in read mode. Exactly one instance + may have it locked in write mode. A read and a write lock cannot + exist simultaneously on the same file. + + The file locks are advisory. This means that nothing prevents + another process from manipulating a locked file using QFile or + file system functions offered by the OS. Serialization is only + guaranteed if all processes that access the file use + QLockedFile. Also, while holding a lock on a file, a process + must not open the same file again (through any API), or locks + can be unexpectedly lost. + + The lock provided by an instance of \e QtLockedFile is released + whenever the program terminates. This is true even when the + program crashes and no destructors are called. +*/ + +/*! \enum QtLockedFile::LockMode + + This enum describes the available lock modes. + + \value ReadLock A read lock. + \value WriteLock A write lock. + \value NoLock Neither a read lock nor a write lock. +*/ + +/*! + Constructs an unlocked \e QtLockedFile object. This constructor + behaves in the same way as \e QFile::QFile(). + + \sa QFile::QFile() +*/ +QtLockedFile::QtLockedFile() + : QFile() +{ +#ifdef Q_OS_WIN + wmutex = 0; + rmutex = 0; +#endif + m_lock_mode = NoLock; +} + +/*! + Constructs an unlocked QtLockedFile object with file \a name. This + constructor behaves in the same way as \e QFile::QFile(const + QString&). + + \sa QFile::QFile() +*/ +QtLockedFile::QtLockedFile(const QString &name) + : QFile(name) +{ +#ifdef Q_OS_WIN + wmutex = 0; + rmutex = 0; +#endif + m_lock_mode = NoLock; +} + +/*! + Opens the file in OpenMode \a mode. + + This is identical to QFile::open(), with the one exception that the + Truncate mode flag is disallowed. Truncation would conflict with the + advisory file locking, since the file would be modified before the + write lock is obtained. If truncation is required, use resize(0) + after obtaining the write lock. + + Returns true if successful; otherwise false. + + \sa QFile::open(), QFile::resize() +*/ +bool QtLockedFile::open(OpenMode mode) +{ + if (mode & QIODevice::Truncate) { + qWarning("QtLockedFile::open(): Truncate mode not allowed."); + return false; + } + return QFile::open(mode); +} + +/*! + Returns \e true if this object has a in read or write lock; + otherwise returns \e false. + + \sa lockMode() +*/ +bool QtLockedFile::isLocked() const +{ + return m_lock_mode != NoLock; +} + +/*! + Returns the type of lock currently held by this object, or \e + QtLockedFile::NoLock. + + \sa isLocked() +*/ +QtLockedFile::LockMode QtLockedFile::lockMode() const +{ + return m_lock_mode; +} + +/*! + \fn bool QtLockedFile::lock(LockMode mode, bool block = true) + + Obtains a lock of type \a mode. The file must be opened before it + can be locked. + + If \a block is true, this function will block until the lock is + aquired. If \a block is false, this function returns \e false + immediately if the lock cannot be aquired. + + If this object already has a lock of type \a mode, this function + returns \e true immediately. If this object has a lock of a + different type than \a mode, the lock is first released and then a + new lock is obtained. + + This function returns \e true if, after it executes, the file is + locked by this object, and \e false otherwise. + + \sa unlock(), isLocked(), lockMode() +*/ + +/*! + \fn bool QtLockedFile::unlock() + + Releases a lock. + + If the object has no lock, this function returns immediately. + + This function returns \e true if, after it executes, the file is + not locked by this object, and \e false otherwise. + + \sa lock(), isLocked(), lockMode() +*/ + +/*! + \fn QtLockedFile::~QtLockedFile() + + Destroys the \e QtLockedFile object. If any locks were held, they + are released. +*/ diff --git a/3rdparty/qtsingleapplication/qtlockedfile.h b/3rdparty/qtsingleapplication/qtlockedfile.h new file mode 100644 index 000000000..2af3e3ea2 --- /dev/null +++ b/3rdparty/qtsingleapplication/qtlockedfile.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#ifndef QTLOCKEDFILE_H +#define QTLOCKEDFILE_H + +#include +#ifdef Q_OS_WIN +#include +#endif + +#if defined(Q_WS_WIN) || defined(Q_OS_WIN) +# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) +# define QT_QTLOCKEDFILE_EXPORT +# elif defined(QT_QTLOCKEDFILE_IMPORT) +# if defined(QT_QTLOCKEDFILE_EXPORT) +# undef QT_QTLOCKEDFILE_EXPORT +# endif +# define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) +# elif defined(QT_QTLOCKEDFILE_EXPORT) +# undef QT_QTLOCKEDFILE_EXPORT +# define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) +# endif +#else +# define QT_QTLOCKEDFILE_EXPORT +#endif + +namespace QtLP_Private { + +class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile +{ +public: + enum LockMode { NoLock = 0, ReadLock, WriteLock }; + + QtLockedFile(); + QtLockedFile(const QString &name); + ~QtLockedFile(); + + bool open(OpenMode mode); + + bool lock(LockMode mode, bool block = true); + bool unlock(); + bool isLocked() const; + LockMode lockMode() const; + +private: +#ifdef Q_OS_WIN + Qt::HANDLE wmutex; + Qt::HANDLE rmutex; + QVector rmutexes; + QString mutexname; + + Qt::HANDLE getMutexHandle(int idx, bool doCreate); + bool waitMutex(Qt::HANDLE mutex, bool doBlock); + +#endif + LockMode m_lock_mode; +}; +} +#endif diff --git a/3rdparty/qtsingleapplication/qtlockedfile_unix.cpp b/3rdparty/qtsingleapplication/qtlockedfile_unix.cpp new file mode 100644 index 000000000..715c7d9b1 --- /dev/null +++ b/3rdparty/qtsingleapplication/qtlockedfile_unix.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include +#include +#include +#include + +#include "qtlockedfile.h" + +bool QtLockedFile::lock(LockMode mode, bool block) +{ + if (!isOpen()) { + qWarning("QtLockedFile::lock(): file is not opened"); + return false; + } + + if (mode == NoLock) + return unlock(); + + if (mode == m_lock_mode) + return true; + + if (m_lock_mode != NoLock) + unlock(); + + struct flock fl; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; + int cmd = block ? F_SETLKW : F_SETLK; + int ret = fcntl(handle(), cmd, &fl); + + if (ret == -1) { + if (errno != EINTR && errno != EAGAIN) + qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); + return false; + } + + + m_lock_mode = mode; + return true; +} + + +bool QtLockedFile::unlock() +{ + if (!isOpen()) { + qWarning("QtLockedFile::unlock(): file is not opened"); + return false; + } + + if (!isLocked()) + return true; + + struct flock fl; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_type = F_UNLCK; + int ret = fcntl(handle(), F_SETLKW, &fl); + + if (ret == -1) { + qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); + return false; + } + + m_lock_mode = NoLock; + return true; +} + +QtLockedFile::~QtLockedFile() +{ + if (isOpen()) + unlock(); +} + diff --git a/3rdparty/qtsingleapplication/qtlockedfile_win.cpp b/3rdparty/qtsingleapplication/qtlockedfile_win.cpp new file mode 100644 index 000000000..ed2995f3f --- /dev/null +++ b/3rdparty/qtsingleapplication/qtlockedfile_win.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#include "qtlockedfile.h" +#include +#include + +#define MUTEX_PREFIX "QtLockedFile mutex " +// Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS +#define MAX_READERS MAXIMUM_WAIT_OBJECTS + +Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) +{ + if (mutexname.isEmpty()) { + QFileInfo fi(*this); + mutexname = QString::fromLatin1(MUTEX_PREFIX) + + fi.absoluteFilePath().toLower(); + } + QString mname(mutexname); + if (idx >= 0) + mname += QString::number(idx); + + Qt::HANDLE mutex; + if (doCreate) { +#if (QT_VERSION < 0x050000) + QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); }, + { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } ); +#else + mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); +#endif + if (!mutex) { + qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); + return 0; + } + } + else { +#if (QT_VERSION < 0x050000) + QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); }, + { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } ); +#else + mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); +#endif + if (!mutex) { + if (GetLastError() != ERROR_FILE_NOT_FOUND) + qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); + return 0; + } + } + return mutex; +} + +bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock) +{ + Q_ASSERT(mutex); + DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); + switch (res) { + case WAIT_OBJECT_0: + case WAIT_ABANDONED: + return true; + break; + case WAIT_TIMEOUT: + break; + default: + qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); + } + return false; +} + + + +bool QtLockedFile::lock(LockMode mode, bool block) +{ + if (!isOpen()) { + qWarning("QtLockedFile::lock(): file is not opened"); + return false; + } + + if (mode == NoLock) + return unlock(); + + if (mode == m_lock_mode) + return true; + + if (m_lock_mode != NoLock) + unlock(); + + if (!wmutex && !(wmutex = getMutexHandle(-1, true))) + return false; + + if (!waitMutex(wmutex, block)) + return false; + + if (mode == ReadLock) { + int idx = 0; + for (; idx < MAX_READERS; idx++) { + rmutex = getMutexHandle(idx, false); + if (!rmutex || waitMutex(rmutex, false)) + break; + CloseHandle(rmutex); + } + bool ok = true; + if (idx >= MAX_READERS) { + qWarning("QtLockedFile::lock(): too many readers"); + rmutex = 0; + ok = false; + } + else if (!rmutex) { + rmutex = getMutexHandle(idx, true); + if (!rmutex || !waitMutex(rmutex, false)) + ok = false; + } + if (!ok && rmutex) { + CloseHandle(rmutex); + rmutex = 0; + } + ReleaseMutex(wmutex); + if (!ok) + return false; + } + else { + Q_ASSERT(rmutexes.isEmpty()); + for (int i = 0; i < MAX_READERS; i++) { + Qt::HANDLE mutex = getMutexHandle(i, false); + if (mutex) + rmutexes.append(mutex); + } + if (rmutexes.size()) { + DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), + TRUE, block ? INFINITE : 0); + if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { + if (res != WAIT_TIMEOUT) + qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); + m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky + unlock(); + return false; + } + } + } + + m_lock_mode = mode; + return true; +} + +bool QtLockedFile::unlock() +{ + if (!isOpen()) { + qWarning("QtLockedFile::unlock(): file is not opened"); + return false; + } + + if (!isLocked()) + return true; + + if (m_lock_mode == ReadLock) { + ReleaseMutex(rmutex); + CloseHandle(rmutex); + rmutex = 0; + } + else { + foreach(Qt::HANDLE mutex, rmutexes) { + ReleaseMutex(mutex); + CloseHandle(mutex); + } + rmutexes.clear(); + ReleaseMutex(wmutex); + } + + m_lock_mode = QtLockedFile::NoLock; + return true; +} + +QtLockedFile::~QtLockedFile() +{ + if (isOpen()) + unlock(); + if (wmutex) + CloseHandle(wmutex); +} diff --git a/3rdparty/qtsingleapplication/qtsingleapplication.cpp b/3rdparty/qtsingleapplication/qtsingleapplication.cpp new file mode 100644 index 000000000..48c2e45f2 --- /dev/null +++ b/3rdparty/qtsingleapplication/qtsingleapplication.cpp @@ -0,0 +1,331 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "qtsingleapplication.h" +#include "qtlocalpeer.h" +#include + +/*! + \class QtSingleApplication qtsingleapplication.h + \brief The QtSingleApplication class provides an API to detect and + communicate with running instances of an application. + + This class allows you to create applications where only one + instance should be running at a time. I.e., if the user tries to + launch another instance, the already running instance will be + activated instead. Another usecase is a client-server system, + where the first started instance will assume the role of server, + and the later instances will act as clients of that server. + + By default, the full path of the executable file is used to + determine whether two processes are instances of the same + application. You can also provide an explicit identifier string + that will be compared instead. + + The application should create the QtSingleApplication object early + in the startup phase, and call isRunning() to find out if another + instance of this application is already running. If isRunning() + returns false, it means that no other instance is running, and + this instance has assumed the role as the running instance. In + this case, the application should continue with the initialization + of the application user interface before entering the event loop + with exec(), as normal. + + The messageReceived() signal will be emitted when the running + application receives messages from another instance of the same + application. When a message is received it might be helpful to the + user to raise the application so that it becomes visible. To + facilitate this, QtSingleApplication provides the + setActivationWindow() function and the activateWindow() slot. + + If isRunning() returns true, another instance is already + running. It may be alerted to the fact that another instance has + started by using the sendMessage() function. Also data such as + startup parameters (e.g. the name of the file the user wanted this + new instance to open) can be passed to the running instance with + this function. Then, the application should terminate (or enter + client mode). + + If isRunning() returns true, but sendMessage() fails, that is an + indication that the running instance is frozen. + + Here's an example that shows how to convert an existing + application to use QtSingleApplication. It is very simple and does + not make use of all QtSingleApplication's functionality (see the + examples for that). + + \code + // Original + int main(int argc, char **argv) + { + QApplication app(argc, argv); + + MyMainWidget mmw; + mmw.show(); + return app.exec(); + } + + // Single instance + int main(int argc, char **argv) + { + QtSingleApplication app(argc, argv); + + if (app.isRunning()) + return !app.sendMessage(someDataString); + + MyMainWidget mmw; + app.setActivationWindow(&mmw); + mmw.show(); + return app.exec(); + } + \endcode + + Once this QtSingleApplication instance is destroyed (normally when + the process exits or crashes), when the user next attempts to run the + application this instance will not, of course, be encountered. The + next instance to call isRunning() or sendMessage() will assume the + role as the new running instance. + + For console (non-GUI) applications, QtSingleCoreApplication may be + used instead of this class, to avoid the dependency on the QtGui + library. + + \sa QtSingleCoreApplication +*/ + + +void QtSingleApplication::sysInit(const QString &appId) +{ + actWin = 0; + peer = new QtLocalPeer(this, appId); + connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); +} + + +/*! + Creates a QtSingleApplication object. The application identifier + will be QCoreApplication::applicationFilePath(). \a argc, \a + argv, and \a GUIenabled are passed on to the QAppliation constructor. + + If you are creating a console application (i.e. setting \a + GUIenabled to false), you may consider using + QtSingleCoreApplication instead. +*/ + +QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled) + : QApplication(argc, argv, GUIenabled) +{ + sysInit(); +} + + +/*! + Creates a QtSingleApplication object with the application + identifier \a appId. \a argc and \a argv are passed on to the + QAppliation constructor. +*/ + +QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv) + : QApplication(argc, argv) +{ + sysInit(appId); +} + + +#if defined(Q_WS_X11) +/*! + Special constructor for X11, ref. the documentation of + QApplication's corresponding constructor. The application identifier + will be QCoreApplication::applicationFilePath(). \a dpy, \a visual, + and \a cmap are passed on to the QApplication constructor. +*/ +QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap) + : QApplication(dpy, visual, cmap) +{ + sysInit(); +} + +/*! + Special constructor for X11, ref. the documentation of + QApplication's corresponding constructor. The application identifier + will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a + argv, \a visual, and \a cmap are passed on to the QApplication + constructor. +*/ +QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) + : QApplication(dpy, argc, argv, visual, cmap) +{ + sysInit(); +} + +/*! + Special constructor for X11, ref. the documentation of + QApplication's corresponding constructor. The application identifier + will be \a appId. \a dpy, \a argc, \a + argv, \a visual, and \a cmap are passed on to the QApplication + constructor. +*/ +QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) + : QApplication(dpy, argc, argv, visual, cmap) +{ + sysInit(appId); +} +#endif + + +/*! + Returns true if another instance of this application is running; + otherwise false. + + This function does not find instances of this application that are + being run by a different user (on Windows: that are running in + another session). + + \sa sendMessage() +*/ + +bool QtSingleApplication::isRunning() +{ + return peer->isClient(); +} + + +/*! + Tries to send the text \a message to the currently running + instance. The QtSingleApplication object in the running instance + will emit the messageReceived() signal when it receives the + message. + + This function returns true if the message has been sent to, and + processed by, the current instance. If there is no instance + currently running, or if the running instance fails to process the + message within \a timeout milliseconds, this function return false. + + \sa isRunning(), messageReceived() +*/ +bool QtSingleApplication::sendMessage(const QString &message, int timeout) +{ + return peer->sendMessage(message, timeout); +} + + +/*! + Returns the application identifier. Two processes with the same + identifier will be regarded as instances of the same application. +*/ +QString QtSingleApplication::id() const +{ + return peer->applicationId(); +} + + +/*! + Sets the activation window of this application to \a aw. The + activation window is the widget that will be activated by + activateWindow(). This is typically the application's main window. + + If \a activateOnMessage is true (the default), the window will be + activated automatically every time a message is received, just prior + to the messageReceived() signal being emitted. + + \sa activateWindow(), messageReceived() +*/ + +void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage) +{ + actWin = aw; + if (activateOnMessage) + connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); + else + disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); +} + + +/*! + Returns the applications activation window if one has been set by + calling setActivationWindow(), otherwise returns 0. + + \sa setActivationWindow() +*/ +QWidget* QtSingleApplication::activationWindow() const +{ + return actWin; +} + + +/*! + De-minimizes, raises, and activates this application's activation window. + This function does nothing if no activation window has been set. + + This is a convenience function to show the user that this + application instance has been activated when he has tried to start + another instance. + + This function should typically be called in response to the + messageReceived() signal. By default, that will happen + automatically, if an activation window has been set. + + \sa setActivationWindow(), messageReceived(), initialize() +*/ +void QtSingleApplication::activateWindow() +{ + if (actWin) { + actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); + actWin->raise(); + actWin->activateWindow(); + } +} + + +/*! + \fn void QtSingleApplication::messageReceived(const QString& message) + + This signal is emitted when the current instance receives a \a + message from another instance of this application. + + \sa sendMessage(), setActivationWindow(), activateWindow() +*/ + + +/*! + \fn void QtSingleApplication::initialize(bool dummy = true) + + \obsolete +*/ diff --git a/3rdparty/qtsingleapplication/qtsingleapplication.h b/3rdparty/qtsingleapplication/qtsingleapplication.h new file mode 100644 index 000000000..42e977281 --- /dev/null +++ b/3rdparty/qtsingleapplication/qtsingleapplication.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#ifndef QTSINGLEAPPLICATION_H +#define QTSINGLEAPPLICATION_H + +#include + +class QtLocalPeer; + +#if defined(Q_WS_WIN) || defined(Q_OS_WIN32) +# if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) +# define QT_QTSINGLEAPPLICATION_EXPORT +# elif defined(QT_QTSINGLEAPPLICATION_IMPORT) +# if defined(QT_QTSINGLEAPPLICATION_EXPORT) +# undef QT_QTSINGLEAPPLICATION_EXPORT +# endif +# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport) +# elif defined(QT_QTSINGLEAPPLICATION_EXPORT) +# undef QT_QTSINGLEAPPLICATION_EXPORT +# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport) +# endif +#else +# define QT_QTSINGLEAPPLICATION_EXPORT +#endif + +class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication +{ + Q_OBJECT + +public: + QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); + QtSingleApplication(const QString &id, int &argc, char **argv); +#if defined(Q_WS_X11) + QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); + QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); + QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); +#endif + + bool isRunning(); + QString id() const; + + void setActivationWindow(QWidget* aw, bool activateOnMessage = true); + QWidget* activationWindow() const; + + // Obsolete: + void initialize(bool dummy = true) + { isRunning(); Q_UNUSED(dummy) } + +public Q_SLOTS: + bool sendMessage(const QString &message, int timeout = 5000); + void activateWindow(); + + +Q_SIGNALS: + void messageReceived(const QString &message); + + +private: + void sysInit(const QString &appId = QString()); + QtLocalPeer *peer; + QWidget *actWin; +}; + +#endif // QTSINGLEAPPLICATION_H diff --git a/3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp b/3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp new file mode 100644 index 000000000..cf607710e --- /dev/null +++ b/3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + + +#include "qtsinglecoreapplication.h" +#include "qtlocalpeer.h" + +/*! + \class QtSingleCoreApplication qtsinglecoreapplication.h + \brief A variant of the QtSingleApplication class for non-GUI applications. + + This class is a variant of QtSingleApplication suited for use in + console (non-GUI) applications. It is an extension of + QCoreApplication (instead of QApplication). It does not require + the QtGui library. + + The API and usage is identical to QtSingleApplication, except that + functions relating to the "activation window" are not present, for + obvious reasons. Please refer to the QtSingleApplication + documentation for explanation of the usage. + + A QtSingleCoreApplication instance can communicate to a + QtSingleApplication instance if they share the same application + id. Hence, this class can be used to create a light-weight + command-line tool that sends commands to a GUI application. + + \sa QtSingleApplication +*/ + +/*! + Creates a QtSingleCoreApplication object. The application identifier + will be QCoreApplication::applicationFilePath(). \a argc and \a + argv are passed on to the QCoreAppliation constructor. +*/ + +QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv) + : QCoreApplication(argc, argv) +{ + peer = new QtLocalPeer(this); + connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); +} + + +/*! + Creates a QtSingleCoreApplication object with the application + identifier \a appId. \a argc and \a argv are passed on to the + QCoreAppliation constructor. +*/ +QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv) + : QCoreApplication(argc, argv) +{ + peer = new QtLocalPeer(this, appId); + connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); +} + + +/*! + Returns true if another instance of this application is running; + otherwise false. + + This function does not find instances of this application that are + being run by a different user (on Windows: that are running in + another session). + + \sa sendMessage() +*/ + +bool QtSingleCoreApplication::isRunning() +{ + return peer->isClient(); +} + + +/*! + Tries to send the text \a message to the currently running + instance. The QtSingleCoreApplication object in the running instance + will emit the messageReceived() signal when it receives the + message. + + This function returns true if the message has been sent to, and + processed by, the current instance. If there is no instance + currently running, or if the running instance fails to process the + message within \a timeout milliseconds, this function return false. + + \sa isRunning(), messageReceived() +*/ + +bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout) +{ + return peer->sendMessage(message, timeout); +} + + +/*! + Returns the application identifier. Two processes with the same + identifier will be regarded as instances of the same application. +*/ + +QString QtSingleCoreApplication::id() const +{ + return peer->applicationId(); +} + + +/*! + \fn void QtSingleCoreApplication::messageReceived(const QString& message) + + This signal is emitted when the current instance receives a \a + message from another instance of this application. + + \sa sendMessage() +*/ diff --git a/3rdparty/qtsingleapplication/qtsinglecoreapplication.h b/3rdparty/qtsingleapplication/qtsinglecoreapplication.h new file mode 100644 index 000000000..549d49f53 --- /dev/null +++ b/3rdparty/qtsingleapplication/qtsinglecoreapplication.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of a Qt Solutions component. +** +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +****************************************************************************/ + +#ifndef QTSINGLECOREAPPLICATION_H +#define QTSINGLECOREAPPLICATION_H + +#include + +class QtLocalPeer; + +class QtSingleCoreApplication : public QCoreApplication +{ + Q_OBJECT + +public: + QtSingleCoreApplication(int &argc, char **argv); + QtSingleCoreApplication(const QString &id, int &argc, char **argv); + + bool isRunning(); + QString id() const; + +public Q_SLOTS: + bool sendMessage(const QString &message, int timeout = 5000); + + +Q_SIGNALS: + void messageReceived(const QString &message); + + +private: + QtLocalPeer* peer; +}; + +#endif // QTSINGLECOREAPPLICATION_H diff --git a/3rdparty/singleapplication/CMakeLists.txt b/3rdparty/singleapplication/CMakeLists.txt deleted file mode 100644 index f4711c0f5..000000000 --- a/3rdparty/singleapplication/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -cmake_minimum_required(VERSION 2.6) - -set(SINGLEAPP-SOURCES - singleapplication.cpp - singlecoreapplication.cpp -) - -set(SINGLEAPP-MOC-HEADERS - singleapplication.h - singlecoreapplication.h -) - -QT5_WRAP_CPP(SINGLEAPP-SOURCES-MOC ${SINGLEAPP-MOC-HEADERS}) - -ADD_LIBRARY(singleapplication STATIC - ${SINGLEAPP-SOURCES} - ${SINGLEAPP-SOURCES-MOC} -) - -QT5_USE_MODULES(singleapplication Core Network Widgets) diff --git a/3rdparty/singleapplication/LICENSE b/3rdparty/singleapplication/LICENSE deleted file mode 100644 index 5c0006b9a..000000000 --- a/3rdparty/singleapplication/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Itay Grudev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/3rdparty/singleapplication/singleapplication.cpp b/3rdparty/singleapplication/singleapplication.cpp deleted file mode 100644 index 9f71a62cb..000000000 --- a/3rdparty/singleapplication/singleapplication.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "singleapplication.h" -#include - -/** - * @brief Constructor. Checks and fires up LocalServer or closes the program - * if another instance already exists - * @param argc - * @param argv - */ -SingleApplication::SingleApplication(int &argc, char **argv) - : QApplication(argc, argv) -{ - QString serverName = QApplication::organizationName() + QApplication::applicationName(); - serverName.replace(QRegExp("[^\\w\\-. ]"), ""); - - // Attempt to connect to the LocalServer - socket = new QLocalSocket(); - socket->connectToServer(serverName); - if(socket->waitForConnected(1000)){ - socket->close(); - ::exit(EXIT_SUCCESS); // Terminate the program using STDLib's exit function - } else { - // If the connection is insuccessful, this is the main process - // So we create a Local Server - server = new QLocalServer(); - server->removeServer(serverName); - server->listen(serverName); - QObject::connect(server, SIGNAL(newConnection()), this, SLOT(slotConnectionEstablished())); - } -} - -/** - * @brief Destructor - */ -SingleApplication::~SingleApplication() -{ - server->close(); -} - -/** - * @brief Executed when the showUp command is sent to LocalServer - */ -void SingleApplication::slotConnectionEstablished() -{ - server->nextPendingConnection(); - emit showUp(); -} - diff --git a/3rdparty/singleapplication/singleapplication.h b/3rdparty/singleapplication/singleapplication.h deleted file mode 100644 index 3550eace0..000000000 --- a/3rdparty/singleapplication/singleapplication.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SINGLE_APPLICATION_H -#define SINGLE_APPLICATION_H - -#include -#include -#include - -/** - * @brief The SingleApplication class handles multipe instances of the same Application - * @see QApplication - */ -class SingleApplication : public QApplication -{ - Q_OBJECT -public: - explicit SingleApplication(int &, char **); - ~SingleApplication(); - -signals: - void showUp(); - -private slots: - void slotConnectionEstablished(); - -private: - QLocalSocket *socket; - QLocalServer *server; - -}; - -#endif // SINGLE_APPLICATION_H - diff --git a/3rdparty/singleapplication/singlecoreapplication.cpp b/3rdparty/singleapplication/singlecoreapplication.cpp deleted file mode 100644 index 587b3fa53..000000000 --- a/3rdparty/singleapplication/singlecoreapplication.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "singlecoreapplication.h" -#include - -/** - * @brief Constructor. Checks and fires up LocalServer or closes the program - * if another instance already exists - * @param argc - * @param argv - */ -SingleCoreApplication::SingleCoreApplication(int &argc, char **argv) - : QCoreApplication(argc, argv) -{ - QString serverName = QCoreApplication::organizationName() + QCoreApplication::applicationName(); - serverName.replace(QRegExp("[^\\w\\-. ]"), ""); - - // Attempt to connect to the LocalServer - socket = new QLocalSocket(); - socket->connectToServer(serverName); - if(socket->waitForConnected(1000)){ - socket->close(); - ::exit(EXIT_SUCCESS); // Terminate the program using STDLib's exit function - } else { - // If the connection is insuccessful, this is the main process - // So we create a Local Server - server = new QLocalServer(); - server->removeServer(serverName); - server->listen(serverName); - QObject::connect(server, SIGNAL(newConnection()), this, SLOT(slotConnectionEstablished())); - } -} - -/** - * @brief Destructor - */ -SingleCoreApplication::~SingleCoreApplication() -{ - server->close(); -} - -/** - * @brief Executed when the showUp command is sent to LocalServer - */ -void SingleCoreApplication::slotConnectionEstablished() -{ - server->nextPendingConnection(); - emit showUp(); -} - diff --git a/3rdparty/singleapplication/singlecoreapplication.h b/3rdparty/singleapplication/singlecoreapplication.h deleted file mode 100644 index b3a404d03..000000000 --- a/3rdparty/singleapplication/singlecoreapplication.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SINGLE_CORE_APPLICATION_H -#define SINGLE_CORE_APPLICATION_H - -#include -#include -#include - -/** - * @brief The SingleCoreApplication class handles multipe instances of the same Application - * @see QApplication - */ -class SingleCoreApplication : public QCoreApplication -{ - Q_OBJECT -public: - explicit SingleCoreApplication(int &, char **); - ~SingleCoreApplication(); - -signals: - void showUp(); - -private slots: - void slotConnectionEstablished(); - -private: - QLocalSocket *socket; - QLocalServer *server; - -}; - -#endif // SINGLE_CORE_APPLICATION_H - diff --git a/CMakeLists.txt b/CMakeLists.txt index c108b2974..9c2323507 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -322,9 +322,18 @@ endif(ENABLE_VISUALISATIONS) add_subdirectory(3rdparty/qsqlite) include_directories("3rdparty/qsqlite") -add_subdirectory(3rdparty/singleapplication) -set(SINGLEAPPLICATION_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/singleapplication) -set(SINGLEAPPLICATION_LIBRARIES singleapplication) +# When/if upstream accepts our patches then these options can be used to link +# to system installed qtsingleapplication instead. +option(USE_SYSTEM_QTSINGLEAPPLICATION "Don't set this option unless your system QtSingleApplication library has been compiled with the Clementine patches in 3rdparty" OFF) +if(USE_SYSTEM_QTSINGLEAPPLICATION) + find_path(QTSINGLEAPPLICATION_INCLUDE_DIRS qtsingleapplication.h PATH_SUFFIXES QtSolutions) + find_library(QTSINGLEAPPLICATION_LIBRARIES QtSolutions_SingleApplication-2.6) + find_library(QTSINGLECOREAPPLICATION_LIBRARIES QtSolutions_SingleCoreApplication-2.6) +else(USE_SYSTEM_QTSINGLEAPPLICATION) + add_subdirectory(3rdparty/qtsingleapplication) + set(QTSINGLEAPPLICATION_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/qtsingleapplication) + set(QTSINGLEAPPLICATION_LIBRARIES qtsingleapplication) +endif(USE_SYSTEM_QTSINGLEAPPLICATION) # QtIoCompressor isn't patched, so we can use a system version if it's # available diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9d193c850..86b4940e4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,7 +32,7 @@ include_directories(${GLIB_INCLUDE_DIRS}) include_directories(${LIBXML_INCLUDE_DIRS}) include_directories(${GOBJECT_INCLUDE_DIRS}) include_directories(${LIBPROJECTM_INCLUDE_DIRS}) -include_directories(${SINGLEAPPLICATION_INCLUDE_DIRS}) +include_directories(${QTSINGLEAPPLICATION_INCLUDE_DIRS}) include_directories(${QTIOCOMPRESSOR_INCLUDE_DIRS}) include_directories(${QXT_INCLUDE_DIRS}) include_directories(${ECHONEST5_INCLUDE_DIRS}) @@ -1240,8 +1240,7 @@ target_link_libraries(clementine_lib ${GSTREAMER_LIBRARIES} ${GSTREAMER_APP_LIBRARIES} ${GSTREAMER_TAG_LIBRARIES} - ${SINGLEAPPLICATION_LIBRARIES} - ${QTSINGLECOREAPPLICATION_LIBRARIES} + ${QTSINGLEAPPLICATION_LIBRARIES} ${QTIOCOMPRESSOR_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${SQLITE_LIBRARIES} @@ -1349,7 +1348,7 @@ if (UNIX AND NOT APPLE) endif () endif () -add_dependencies(clementine_lib singleapplication) +add_dependencies(clementine_lib qtsingleapplication) ############################################################################### diff --git a/src/main.cpp b/src/main.cpp index 4a90b0951..2c3fb1c3e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -69,8 +69,8 @@ #include "tagreadermessages.pb.h" -#include "singleapplication.h" -#include "singlecoreapplication.h" +#include "qtsingleapplication.h" +#include "qtsinglecoreapplication.h" #include #include @@ -288,7 +288,7 @@ int main(int argc, char* argv[]) { // Clementine running without needing an X server. // This MUST be done before parsing the commandline options so QTextCodec // gets the right system locale for filenames. - SingleCoreApplication a(argc, argv); + QtSingleCoreApplication a(argc, argv); CheckPortable(); crash_reporting.SetApplicationPath(a.applicationFilePath()); @@ -297,6 +297,16 @@ int main(int argc, char* argv[]) { if (!options.Parse()) return 1; logging::SetLevels(options.log_levels()); + if (a.isRunning()) { + if (options.is_empty()) { + qLog(Info) + << "Clementine is already running - activating existing window"; + } + if (a.sendMessage(options.Serialize(), 5000)) { + return 0; + } + // Couldn't send the message so start anyway + } } #ifdef Q_OS_DARWIN @@ -324,7 +334,7 @@ int main(int argc, char* argv[]) { IncreaseFDLimit(); - SingleApplication a(argc, argv); + QtSingleApplication a(argc, argv); // A bug in Qt means the wheel_scroll_lines setting gets ignored and replaced // with the default value of 3 in QApplicationPrivate::initialize. @@ -342,6 +352,10 @@ int main(int argc, char* argv[]) { #endif a.setQuitOnLastWindowClosed(false); + // Do this check again because another instance might have started by now + if (a.isRunning() && a.sendMessage(options.Serialize(), 5000)) { + return 0; + } #ifndef Q_OS_DARWIN // Gnome on Ubuntu has menu icons disabled by default. I think that's a bad @@ -466,8 +480,10 @@ int main(int argc, char* argv[]) { #ifdef HAVE_DBUS QObject::connect(&mpris, SIGNAL(RaiseMainWindow()), &w, SLOT(Raise())); #endif - + QObject::connect(&a, SIGNAL(messageReceived(QString)), &w, + SLOT(CommandlineOptionsReceived(QString))); w.CommandlineOptionsReceived(options); + int ret = a.exec(); #ifdef Q_OS_LINUX diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index cba1d91d9..626134219 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -1943,14 +1943,14 @@ void MainWindow::PlaylistEditFinished(const QModelIndex& index) { } void MainWindow::CommandlineOptionsReceived( - const QByteArray& serialized_options) { + const QString& serialized_options) { if (serialized_options == "wake up!") { // Old versions of Clementine sent this - just ignore it return; } CommandlineOptions options; - options.Load(serialized_options); + options.Load(serialized_options.toLatin1()); if (options.is_empty()) { show(); diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h index 71e286259..50672ac26 100644 --- a/src/ui/mainwindow.h +++ b/src/ui/mainwindow.h @@ -222,7 +222,7 @@ signals: void AddCDTracks(); void AddPodcast(); - void CommandlineOptionsReceived(const QByteArray& serialized_options); + void CommandlineOptionsReceived(const QString &serialized_options); void CheckForUpdates(); From 8bafaced14df086e6b0f1446db7a3e02b4ceb9ed Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 16 Apr 2015 17:45:23 +0200 Subject: [PATCH 012/104] Fix error message log in metatypes (declared twice) --- src/core/metatypes.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/metatypes.cpp b/src/core/metatypes.cpp index 9c5deb00c..d6196cca3 100644 --- a/src/core/metatypes.cpp +++ b/src/core/metatypes.cpp @@ -56,7 +56,6 @@ class QNetworkReply; void RegisterMetaTypes() { qRegisterMetaType("CollapsibleInfoPane::Data"); - qRegisterMetaType("ColumnAlignmentMap"); qRegisterMetaType("const char*"); qRegisterMetaType("CoverSearchResult"); qRegisterMetaType("CoverSearchResults"); From 32fe732f645e00632cb8b795db35f6ad41018711 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 16 Apr 2015 18:54:42 +0200 Subject: [PATCH 013/104] Adapt clementine tests to qt5 --- CMakeLists.txt | 2 +- tests/CMakeLists.txt | 1 + tests/main.cpp | 2 +- tests/mock_networkaccessmanager.cpp | 6 ++++-- tests/zeroconf_test.cpp | 4 ++-- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d0b2aa1b8..675143b6b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ endif (UNIX AND NOT APPLE) set(QT_MIN_VERSION 5.0.0) -find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core OpenGL Sql Network Xml Widgets Concurrent) +find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core OpenGL Sql Network Xml Widgets Concurrent Test) find_package(X11) if(X11_FOUND) find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS X11Extras) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 95c954d00..617704241 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -100,6 +100,7 @@ macro(add_test_file test_source gui_required) ${test_source} ) target_link_libraries(${TEST_NAME} ${GMOCK_LIBRARIES} clementine_lib test_utils) + qt5_use_modules (${TEST_NAME} Test) set(GUI_REQUIRED ${gui_required}) if (GUI_REQUIRED) target_link_libraries(${TEST_NAME} test_gui_main) diff --git a/tests/main.cpp b/tests/main.cpp index eb058fbc6..036e02111 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -25,7 +25,7 @@ #ifndef Q_WS_X11 # include - Q_IMPORT_PLUGIN(qsqlite) + Q_IMPORT_PLUGIN(QSQLiteDriverPlugin) #endif int main(int argc, char** argv) { diff --git a/tests/mock_networkaccessmanager.cpp b/tests/mock_networkaccessmanager.cpp index 64d6d5f68..bb0224d39 100644 --- a/tests/mock_networkaccessmanager.cpp +++ b/tests/mock_networkaccessmanager.cpp @@ -18,6 +18,7 @@ #include "mock_networkaccessmanager.h" #include +#include #include using std::min; @@ -44,10 +45,11 @@ class RequestForUrlMatcher : public MatcherInterface { return false; } + QUrlQuery url_query(url); for (QMap::const_iterator it = expected_params_.constBegin(); it != expected_params_.constEnd(); ++it) { - if (!url.hasQueryItem(it.key()) || - url.queryItemValue(it.key()) != it.value()) { + if (!url_query.hasQueryItem(it.key()) || + url_query.queryItemValue(it.key()) != it.value()) { return false; } } diff --git a/tests/zeroconf_test.cpp b/tests/zeroconf_test.cpp index 3448f8221..973953e25 100644 --- a/tests/zeroconf_test.cpp +++ b/tests/zeroconf_test.cpp @@ -21,7 +21,7 @@ static const char kLongMultiByteString[] = TEST(ZeroconfTest, TruncatesAscii) { QByteArray truncated = Zeroconf::TruncateName( - QString::fromAscii(k64CharAscii)); + QString::fromLatin1(k64CharAscii)); EXPECT_EQ(63, truncated.size()); EXPECT_TRUE(truncated.endsWith('\0')); } @@ -34,7 +34,7 @@ TEST(ZeroconfTest, DoesNotTruncateShortMultiByteUTF8) { TEST(ZeroconfTest, TruncatesLongMultiByteUTF8) { QByteArray truncated = Zeroconf::TruncateName( - QString::fromAscii(kLongMultiByteString)); + QString::fromLatin1(kLongMultiByteString)); EXPECT_LE(63, truncated.size()); EXPECT_TRUE(truncated.endsWith('\0')); } From 1c6d164219aa700485075d048fa1eb1623282b1a Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 16 Apr 2015 20:21:19 +0200 Subject: [PATCH 014/104] Avoid warning message with dbus inialized before a QApplication --- src/main.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 2c3fb1c3e..6b63ea648 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -317,12 +317,6 @@ int main(int argc, char* argv[]) { 1); #endif -#ifdef HAVE_LIBLASTFM - lastfm::ws::ApiKey = LastFMService::kApiKey; - lastfm::ws::SharedSecret = LastFMService::kSecret; - lastfm::setNetworkAccessManager(new NetworkAccessManager); -#endif - // Output the version, so when people attach log output to bug reports they // don't have to tell us which version they're using. qLog(Info) << "Clementine-qt5" << CLEMENTINE_VERSION_DISPLAY; @@ -336,6 +330,12 @@ int main(int argc, char* argv[]) { QtSingleApplication a(argc, argv); +#ifdef HAVE_LIBLASTFM + lastfm::ws::ApiKey = LastFMService::kApiKey; + lastfm::ws::SharedSecret = LastFMService::kSecret; + lastfm::setNetworkAccessManager(new NetworkAccessManager); +#endif + // A bug in Qt means the wheel_scroll_lines setting gets ignored and replaced // with the default value of 3 in QApplicationPrivate::initialize. { From 4a9224c04e7984bc0d5f4bd1ea0cc8021f8430f7 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 16 Apr 2015 20:37:31 +0200 Subject: [PATCH 015/104] Remove boring libpng warnings --- data/icons/32x32/internet-services.png | Bin 5196 -> 2562 bytes data/playstore/fr_generic_rgb_wo_45.png | Bin 7115 -> 5980 bytes data/providers/skydrive.png | Bin 3469 -> 1261 bytes data/providers/wikipedia.png | Bin 3203 -> 525 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/data/icons/32x32/internet-services.png b/data/icons/32x32/internet-services.png index 464115e4a54cfb48ab51d625762016d2c9e49f06..c6fe3e20dbaf3da31559cbf66a1a24da3874c082 100644 GIT binary patch delta 2454 zcmV;H32FAsD1sD_B$IjyW`AQzL_t(o!_}92a8%VD$G>;??jw)gWV3l}vYW?lLPB1o zF$y{{4KUV95Ja$`t<<3cj#^(-#E#RM+Nqri79xTr2@p)8A%>TtyaEWQs3ejQNrEK1 zA;~_I-M#y~`?$OJ^bZX_!U%NiAN|hUxo6J({m$=m=l47FI|ulg)qio~_)Xc<*E86@ zeLGgJT!{(0HThq!y}opK_)0ayFeQG!KO+?6Vg&+WOz%W zF1!l>x-VY*>EMk`EdYQ;i|#)+y?Qz(fhN!j|xRgcHq=nvFxSPuZGC@d~ZPgLkt z$*E*|K_Pkm#TVCJ%U&=!&|6H%%+hGK)HR%~S+evtDiYaIl&8xyIvo%B{I0-_0zA9+ z1pvUf#d5*oVt;ZIVx$WTOG>^jEvr~xx3lqY0C1tNe=0z3x*7tS?v0bl?(q9PH3Ryg zmDTsmGXlV_cUo^ag_9a{IROB3?|b0j{=Mzf9gOopqC)YP&%3*8%ZiJBXngqSF#tfz zyKP@LwzaRg>1fx{yZhb)05r9?f6}&Z&$=Ic?CS0X0Drt$U$=h!#@fe!?%fQX&1kZG zQv<1KDUX`16VT@B#{Sy?l<>wjN{TAoY_wRwxR|Fk>U7YX->8*(ydG_Ga!SBt8ZQN4 zx|X9@eSa^)rVju>gv7@lyyedPs_cx!-_Z&hA@#X3?sKzjLlWP+|pEKlV*C`r>>yI9~Xr)8m3NB?*K51N-$OqY#eStoZcI zS$`)b7CkaLY^XeQ;>5&?m8;6t>a6Geevkds+pjVYJpQ!tl|R)a1Vd3!0KEPXf*}rO zn;W5U1dKZXp+JCGsRUB72$dCizkIJVhImGfo-QdZyGNIszhKQXPkoWE&C=g8^Y%1a zEGk^{DyFICki;aNoZ7zq)N!Wh?9V$pfqpGJkne z?CoXw_lrbASnXa6U70}NkOgL&2VED(@U>wA2aff@;|oD5p`l8V!)EuwWc8r3T!&#Z zwML~l|i zjM&C8GREMO^9JZg9SDbc*z7(SEq`uUCVa3?c#)rzf<(C#G%Y}Ck{t4QDXy3p6l7LUz~=N~ z@ z87EjafIMvuDy#13nk@9I%_vD0-&avl0j;hO5srhH7QyXy!{rWui$qbs`z+Fwa@<+2 z!*eUDF>G|gZ1aE?2=RIM7!1{cMaA9cF83=I{?y0GP z5I8yoz-%@)J@xz=T)fx|fq#Gk0YSjeLM*010GMnZFs>jNPZ063QZ)YaLEK%Hj}=QR zFk)hGaQUE>sh^0M;vjLQji zh7$6`L%8 zjQgNSkfKPJ0k4Yz4<25R4|C?+f$sBN9krWk?Na~%VAE@x9IlWJq8JIda1a5P4RLW& z&_V%v`pt-mp<#1)5eh}oueZU+hVYL!KZ4I6f<~2qP&fj=p92U5%Y+*O!ouxzA{q@t zC?PPrt$1P0y05+;^M3~bUv>9fK6UyyC=vx9;Sly)K@koKvKVlYD8?)6M;L?Jv8(vZ87tQD- z6d$ZdFksde0iG-W&_v4F|qL0qf^0EI}DptL}RyDIZgJyVBhgy2ZWna^O}wT$O+ znG(`aYqB=AHSb97?Ce^1>eQ+09~vHc^qUSgZ{GaU$$vR%T*|D<1uyr#w4sCS*xgCG zdW~e@vW*-*d5OHezniq|?;%T8H}YAf4{ih?o%EYOfBsAWXlZM|W~}R8&3+_Fs;0E2 zvU>5ud3m~0MS@($agnIeY%!ke>NsO1;%^@wK=9l5|DXN?^v7`T UMg72`01E&B07*qoM6N<$f_C|#Z~y=R delta 5104 zcmVFOw0}eAZu_2-Y5k*7< z6+wa`28@Oxu_B6vfMCHMkRYJMU=&eNc{8$Bbmir}mzUokXMcTbpS|}zXYYO1x&V;8 z{kgn!SPFnNo`4_Xg z0)Qfk?E(%fNyMfiCh@~U+(f(-030dtD~|t)1)Lm#_)>1^8M%CJVv>Na%hIEp+1fJb z-kj`IjzC}(#AKx~`E0sddRhjPmkYq+oj*%PTwA)R$bZ&mw$|20=Ei1U73#lk{!NK{ zyGXBsKlcox^?kAZm0x;20E}5tZFYRI#qR~6V>1Bq_rKUQ4+0=5>RbE3SNEZb=OsxX z$gndp$L{!k0Z0NWPyi}G1Ly)HU=D16J#Ypdz<(D6f-n#TRsj}B0%?E`vOzxB2#P=n z*a3EfYETOrKoe*ICqM@{4K9Go;5xVgZi5G41dM~{UdP6d+Yd3o?Mr zAqM0Kc|iV92owdyL5UC#5<>aVCa44|hpM4Es0sQWIt5*Tu0n&*J!lk~f_{hI!w5`* zseiCCtPPvM4A=$sgTvsJa3Z`K&Vvi#?Qj)b4_yPPlex4vr&>=Vw!hZ7&wDr6*;uGTJg8GHjVbnL{!c zWyUB7MT6o-VNo_w8Yq`2<5Ub)hw4L3rj}5@qxMs0WMyP6Wy582WNT#4$d1qunl{ac zmP#w5ouJ*Jy_Zv#bCKi7ZIf$}8dZN`iSTS4ifZ`>^=_S-9_DfhxikF;Na$gBn(pL&mTBCGGsZVKESw-1PIYW7`@mn$4Q`weVUDtt72ITD@9x+B(`1+FP_cv?q1s zb$oR4beeS@>XLPxbXV)v>)z7C=rQzC^!DrB(1-P{^po^!^al)J18W1W!G425L$sl- zAyeeqo|%5^b{6q}Sw=sg-G}X@7(112Y*jU$X+U zF0n%DhURoMhax4#6-nF7w1z2sd>bCl5ZDY;1Zn2)S(X@%P z*=IA%pfZ9OrHm`KXj@m?^|q&N-`QE)3G7bT{bp}upJIR1esZbKQqIzbrDG224ortS zhY?4*W1Qnb#}OwrCx50>z0(tC4QIAWs!l zhetO?&#v%Tv3tdMj8#lg%$=1wD|1#}U8T4xb=8?z$yjFW$vAXeMBLH156nPjJ##kR zCw^c249ktRhkx~)?aZ!VPjMVL<(!EGhlKKk$wY_5U5QgkPDzzX(_A-hHTPw*cXDm= zTuNZd;gp5ch}70JTv}Y(DV_{3h1Zj=lAe=3m|>7nlrgf}ZuRcfGkiaOVpAd!m-U>o12Ryiugst zTkN;gZbfb7ZtdS@v2E|RPsQxwYbB;7l_eiaS*6#$G5e-n=E9e!)6|Z;4?!H=SSy{V>ut&IOq{_dlbFb#!9eY1iCsp6B zajj|Hr?hX|zPbJE{X++w546-O*Ot`2Kgd0Jx6Z4sy~-lqcg5k# z>3^$sS5IAITJ{_=u0ch3gRK7Nz-W`3^tt-{+Q?-=iT-$%Tkn9u%z z{ZRE$?_<{|zfTVr(iRr}1p}D#{3Ul5b&(-ye^*IFK~z}7)t7m26m=HIzdh4)WRjU= zGC3xhgk&ZmAs5*g1+AD3SgtEU5WxlAm9G$;|YeJx9;N-jY>7XbIjg5_1v0}ydKA-v_fVbM3b3WLA=*^))V~x#bM=ZtxJOLkzf$&if z076;>iV}hnP@qL(Xmz>BpQ_u^P~Y(Qf2>)v$jOr@Zw#QNr3FiuF2%xyifk*J3PVUki)#=Rc5lthut^U;(@ByuNDsD!s=`J3$82-Rx`4vWMyrtZ#-SQXz?vnG`g)gUzcri zIUn=~+`;PwcxLtU0Dy6;^_tXV;o<-R#!)0s!7@VV(0HbFdfA1+ z;gNKc*?Kt#($Z5OvDhY{&C`wj*bOM*^%Y90I>TbJTEV!Pr?NB|pf|o=C-wTg+LV;k zpxHcL2EcqRp;&VdBIfr2e?Ww!M<2N9_JZo1%%qfPjF0vW+6RoM^zQ<@&#IP;z}cQN zNk3>D##EgaiHamT##4yKqW1uJ5dcvCX7k0CUAxHfPd+6!i&OYrv3%w>0Km)zb(@-Y zbrG*WM7}Ye5JHGy#7Q>p_;^J1t2NaCAWABk1aai#M}OVld5rvbfBO#7wr}6+t7Ryr z={B)cj1h~)sm@fzt_Yf2+mTw^1>fg8)la>&&vBq> z&A2t47K@5jJ@NSJjddF!Ty+0p6qXbh(;~?-MZBUu93^+Sf1S*3^QdWdUUBIkjBG{4 zroS(m&hrEWK>v^(!)7O>ViDZlAj*p~(cNo;Hd_V8!@}ne0~7_ZNIE+!uTVN_=-*;B zn|^z)??R$hn>+F7<4=Y~G`*x{`?i+=Kydr5Gcar%t~_$!pm5Kg_rAPkW>p&-@GF9> zA96*q?AG#vfBQrtA#4sGhAvH@Z^#OZ-HYz?WBAHAfqh5%;Pro(lM5ER7qmc#&-7#1`9TlP^p3&n4TJH7piW7I)!_x}_an+hkfq5)n4@ra zZ7qbr;Yk1%i>dj^=T_nT`CbSF6bJ}{0TyC0e+>e_Z1;k3hroD4NRUa<^zR37S9JlF zEw03fnZcnGgJ|2Yhm#3{@C2uO3>X|8M=%%!MJR;BL1=QdC@w9+)`t3~NdOh)6>Ax{ z3z|$76iG=4vH=8rF2qSh=)GV?^(|VozSjkhH-un_10N$Wj5@)`2;$?UpgN3PclrfG_nu7f+l#e+r7kz(+Ym0ya>DL!vwmTr`F;s~b~uQ&5<% zLLeB1!^MK8DX^gkY)&uiE(V7_8oRV= z6Y>6m4|i)5EmIknLzJb}Xrl5Fw z7oh+tjRPLzdy8%3ZltRcAdvxPs~7Py2>=Sw7(rQ~8h2LZqh^K^9+niD5Z{P585@FSNy*qk|Y%dT9L#;4A#n)g!Qev9im$+n$c zq`TKd1}@sk!Q&UmTYL4Sb#D(@w6ckxQue@l0MaYExpU{v0D#u^jvx1H_8pU?WtG)d z)hv7{KVMg-OjO7@E*djgtfn*F-N(;;(!3Rb@rEX;pD^Z$zdm>Xp|8*XfA&B0$8hh- SxU2yH0000tewvy+uQvuD|R?~!nfWcwZ; z=Xm{IFP`VQulpKz*fR|k5<*%+2!coua78U}4FqpKd|dD~>@9vLxG-75wbUWVhYf-P z-a*jW4Y+PYkcS`y{Wgan$z%wkaz>eTDuZWnEmTz$p_|*!%%=Q!aEHJJZr~0eCLv{!*?4iT5`4 z_LKECCnBny_}p%%U)bz^`%#t_AT$czX9jU%hW~uWB*Idlwux-^U-D)=Xc>3n{&%u^ zB)t>pwO{qm)OY{yUek%`&SMtT8;B56#W=+n!Ws&4x~x%fiy6Q?rELkm5K$uIY<+HR zZS7A+M%G=Zo&U_tjEtT>tz=J5>>8%SeNU0)?)ks{n3fi~w}wXvb~2etUa(Bv%z7{4^VzRZCl&>wZLoaha1( zJtZBTDr&V8vO(Tl{d-n4zSVVOHdX7&3aQ0^)%p6w)zwwg1frv(6PJ{1>*>K~V`GDB zYEm6Opr;?6n)*N|<^(~PS69Oowwe#bT_Et|q4DwH_;?ClUf#_7{7|0fB}?ajcjUd@ z-Q7`#E8>VWU8TS^Nh@i5ns^Ii=1~+$i49KnS!P8vw=cT5>2?_UzNl4-{GRTaK zj5rgX_N=?jHThB{@td^m&epuJw8R1*S<(0dT??wwQ++d33(Xyz`y_}AK$$wUCLqM;VZvV#0-p$)ld(Ft?+$M{vc4i z0s^-7_FRaO!NC|v{6!l!%1TKIXXp3tH#-x2C)=Z;P_65#GRkVP*^eMVpy`+#p~amb z%*puyY=s3%m-a@%J|!k9qZ(b7F);+e{kpok-E$%DLo1ZklP4HQM@I&xrW(%9`<~Lw z%*>5`7orsv6$sRR^94T!dZO3}`FH#|PIHs*KVebPL@4>=M@3Yl=PoV6?dtq*j34Qm zn?yg@RVR5^jxI}_v?rf0H6i>qs3O^sLx8DsSC-wuH) zSgNY34<9~knV+YRj*c#?u2z2fG(2{HVe+`nJVIM%5&Kr3@KAhMfoSTrD^ZbzcYySNxJ+g3X;k=;7f31^oP} zrj{;Ev)UaK3Wv#?n9!@Kskv;AuzgHQV&&o@0F`{=1OorC^o7Y8XLoogJV}2 zlKe_T7#Pqj`0Vg~GpN9o^4e2GBBkHnTzTmm7!XL)j*X4U@h4gKC-O~IzoKJdWqo05 z%duu_W5XgLL9@KP{2?kT7!GTjuCRS!XNQk^R;YvN{PJZH+TYTWRa#mag7)_Ipn%yL zXW6*AJ2z+C*M4)QNIpKk*j}rl;o(5T;*d|DXdtkDi}k()Y5-JWVPSL^oih^;4-tf( z_gY-;OW+ZF^eFhp582lq9?WrYuyokiELcD4wr`F3Ra{+#kbZtbz9){nX3YwUy-Xk;|2 zetA`-rmK6;=4UbnO25hHQCAdQXj@wwhsfQ8ganDaygbc$c5(k}>32av_yOnV=Z&tb zxD*r=1OdIhy~G3rFJc%Ti+lXm$x?H36SlOl*jia>OH90fvcH%Cyb1;4cPEzFQF>4gtxuz4bpkw8k`l`&Q<8i7^8D2#3LXYZiPWBJT59 z=;`S-ylp%hkoxxRTTXPeM(9;#O^vObTmTwu#zs$9_dghUd0t*fis&oy!>>g}b+2Yc zG0hPO0xEvvo-hgytz50)g@x<#!N9^oF3<(;^=bssjItW2$cTt+!(yBN{<{l~iy#0X z=<={%V0&u|j^gF#w*gy09ClKf<)oz0Ax1_=wTl)2kE5)Vm2rs(3E`;b=H?(FS}H0I zG=r39q@&Ry4LNyRW#vOmb9s48#BH1F>gqZ=I_8v=@PnnmQED0*HUMvnZ!ca&Gd%tb z^9Fm)%gGTG5s3#RKr!R;`n8q2y9j8$U#F*UP?VI81E~^07>3%~?G0Z0BVAn~kUsc6 zM)q1iHovS49mW+{@cp}RzSsVOhM4mLQdm`;V{7q;EH3E-d`nBqwY9aSp)7?qEh&o* z{JBPNiX;KEkhC=Vjh~;e0KbD$FaaFf*x1}cZ)IhrGTH)KT3!w`sIbW@FTV@KLJ=Gy zWZn{h0T3(hd%_z~&AJ+Zf#tH)f^kbpZEcu8Zmy+piK!t00Rd_nnyk7y8ay(Fj=wvT z%S%fESqhfg$?v&<$#tD!2Ua*|UH@e;lW#ra$k9Z)ih_u4?R}7%kIyc?*oxkD z`TVf9$oewoJrJ~EBU$8dUw!$J3dXNa-Y}zQi^M87;>kq5z)s9{?#y9K zY@M1o48s?8-%#u5=wRaJCM?J;`kEw`-7Lu`(bZpMQHK;4GJu z&vI@{vD_Xin>OI_TJa-o$|&FI^OLJZ?brGg3Y%4UXZ9O1d*&>YdW>0%UnRzdC;fQ4 zDM49nY;7y5s}tQf2XZSaM4}=i3!ZUO-?_u|hAbi?qVO4K{iS~Hfsdqw#N%Pl=8HY4 zR^PLnEi;C@N)~c?93hG-K@9g6rcl?FCJ0iQPq`YR~-z z52F!BC6x#ceoRXXz9Ky@W1VKlckAKze>Fa9)g**5uGH5q0^agGIXTE_7G(DfF<5a-TWGO2r zXTiLj1NwZYbagYszpLD`yUc6f6dMnZm4yX!zv&+XWY>!U0V4!pk0-C7;Cg;+51QG$ z_plEMRV>B&l|OiUENwQ$*#81g(`~9W zU;Mm>%SS0=+5JbCP`!gxsT)tsgo)!?_ra z{sBoyMwSnV`QmuHomC||7UqXU;#Yb<(oB<7f`Z!roF1%#a_1Bm^W|%1XrM07HZuqU z076H@eMW{7`Hb{UOy&#Khsw#5ja*KbwU5spe`1YE-Pp3s-=?7Jrqb+mMIs;IrHXe` zX{0Up8pVBEvSD{2(=Mw1F7e0GZIJe`rj(|9D&~G(NSekPs5SxxY}IA^(^#;%pdifR zWBbv(I2f>W*w)OwOH1Z_3nX-+v9RnfU+@FW-kz}`MkXfomOhC&GawF^THnbV0$YO^ zX>ARJ^o@*oYV#jeT67Yk)=EqoDrZRW@tJx(`Q1o%XR0EA#$&e#G@r^p3j)SVgpExp z!XLOm7{bKF1W0*2OeKnTJX%FlGlqnO#JJLKnDHU85)1qPVl)%Z)+xM)hk z3cZ5kzi8b=5&jn3XfLPi!GYI3hADxGw3&qr&I9yebfJk$5!3BVdzts5y3yC1sVc1i zj==Q<&Nq0yT;H9pz?+_)20pM0_-6D*iZdp3eKzRtaNxAqOb;z>ZsKupaGai>f2pdf zN=tH@EHSaOvkNFK72xHYWsEBN`gLi0n?PGzTTw{~1CqJ;Ba$lNj+>sIPW{M%GEXz3 zWV{4Ki^Idi+tw&<1d7t$)rITn=~=s2L`O?Y={TWG zAi#c>UeR3!hK229PbZ442 zf)LXyjKc`#s>$v?zQE-3FDZHy_wL<;0^(RzJh@Zj;_l*-&|(M6V<;#nK(8*OpkjU5 zO!aaLOUqy%aO@bF?I}%waI-QqA+18nLD?JW-#a_Z2~U9tGND1vA;OxUnwly>zI@4( znmWTjG&eVg-fP%z16~?9;?7F@Q5S%0(hJ4!+U*b7*l>X7+L|oQ(DO}9Oq{B;r$C`l zv9YlMz!h8m+ncv@a3FsJjF_Oq7$-A@xAL2mNWCBShl19XaNl54}S^JOgYmYK;7RWR; zHFb1!%%{p;fEQL!P*B<1D<8+j=B8KU&G~B}?x=u>c3;4h7(yQ$1cI2_e04JG&-YA4 zG%!7Z?Misi^>-A{@u18gm-nVb6;qgY1nNu{XLGw9Il!s5lJLY`e^)a26IQ;k|B}8a zqrPJGdlZ|Q+pMISp@9d0#?}@-^Axb>lYKSczgvJ^^H1{qo0dSV>A5*IFhO8`1%d!C z7Z)?MH(jAp#v}P9bPC&UmhgCg8plTq^zhI)j)RXu>xmDEO!{}MuJK=-)sNo&)W^ju z6ta@N$7JLFV9u1ZeYT%8>&us;t*MO-8zj0F51J{7eAG=(0vy%*mZ!hES-}E1IXPQ~ zvsIYmd&|sQF^hdR2ht*d<6{EoyE*Na&D1Isv>$*vx>)v%+&q&^OFbyH9kHL zB2yM{;-JU8_U5MdDvz)JEfP(373md|%NTA0tHPoF`4%MKD=R-bRDB+lxo~U{)hjhs zM@5E(dFQ-bB~55)=?WJq(w0c^Mjm-`+dj%2$-qfXN$QJVFcax~%T=m=`dMATzq2C? z1DTuOo>AWpM0DfxqnG-+x=N_VHwP@)+1Yiz|D3uyI?yT3&C3PNE3;<;-G$n51fAl$)Mv(-X;d{IC~S6koVNr2SJ*Zkxit}93{#H6G)%E}>` z(z4g5tbx^b8=#Q5I5@8R3r&F7*#oOTto^v!b^h7cX8~AHz_hUk&}1quE-t+jURYSz zYj<}`EiH1;a|Sv(9VireG>wSz5)m=6m7QGy`T+=5z+{>>`6Nh4NEn0E2u_)dL7H=p z&#ngqGu6PGT5`^B;zcrPfxK(Rf32IlkORM(ewsBkTZgRrB&vs-AAVR*wH6EbA}e&3 zMzFE6A`iG{W@_pgjQnwBqz<>=TIttZE&EUpWo2a)41i>NXGgWpcmQDg2zYf^@7d9& zY~r=w@vsUnH#d1Ym`*WBq#Cow56{h|Y86(RoWJw)zxq3Aprr+(giJm8l%eauE-}9q zvzaZw?YgOj+Ttr-kHzjI%Nm#RQAJv~RgA}B0}4cJILfj+dc1FEwnhLU%*?zT#@QO5 z+14iSw9t4KXIcwJU8$rBmWq%flLON`*I~Y&-o+RpUOr4e(PEBKvr&h6hL^fb@x6k! z0}sX~CRWyZ;|eIA+GOkZZ_llY(~7e4^43tsw;uq4TRJ+hGmwY9tVs!= zISf=)FBbF2clw}r=`IcSL3g#eT}8$2XRTyBi#0+|1@Aimr_033iUmmS&1#g`|NXC7 z)-&^^mcV2Y+W|}aeL!G60|RgWT!Dck8jY3%Dc;oYukP4{%%xJ37Y8%2uBgGCzDIMD;T3#hM`1Y;|eaI>8*e|})MZpTo$T47+y zU~#b036i`KWX_s-RZ$HIlD2#UBaj&I84pF3UHNBYz4xX+uL$P-t&-Z*ypGa3D!TLm+T+Z)Rz1WdHzp+MSknR8-d% zhtIutdZEoQ0#b(FyTAa_dy`&8VVD_UC<6{NG_fI~0ue<-nj%P0#DLLIBvwSR5EN9f z2P6n6F&ITuEN@2Ei>|D^_ww@l3o6c zm;e!*vpE?o5f_L!B}k0Z0NWkO#^@ z9q0f3Xv3lIchAu>dPU)xk0{A5EKc;LJ1HL z5<+>u$9dISw03U@r;Pdb`_%=KWKZEBGfDjQHqKX(I48#TTN1~8;gpaI8ijWGV z0cl0Lkv`-mGK$O~Z&4T&1w}_0qHIx~s8AFOwFb2wRf4KU9Y%GadQmq~W2jlwM>H9& zh}K8jpuNx$=mc~Yx)5D~ZbG-CFQRXwCx6hdF&GRDqm8k`cw!#HrxSaPGJ$91oX|tH2$>oxu&^ zCUFaRDZD1$2Jeq&<8$z(_(ps;{yKgFzd(>CXcO!RA%rBtCPF2lm2i>pfbfz?B!8+A zt%-p|E^#BVl6Z`GnK(v#OOhe!kz7d8Bq3=B=@980=`QIdnM~FqJCdWw0`d-WGx-Af z5&4Y-MZ!qJOM)%2L83;YLt;qcxg=gvQ_@LtwPdbjh2#mz>yk54cquI@7b&LHdZ`+z zlTss6bJ7%PQ)z$cROu4wBhpu-r+;LyGFmcjGHjUwnS(MHWX357MV;b8VNo_y8Yvek z6I2XUo9abPq83xXqYhAKWo2ZS$%e^h%ht%AmK~)bG%cDJErnJ}J5C#>y<4KR#Ayj< z$@V3!ONN%r%Pp02l;g-1$+gMdmU|~pmv@s-mft1cDgRIbrJ$z}sF0Amz>RYg@#RiSFV>VWEknzmY~TE1GF+Cz1MIzv5PyLvhF_J8+x#wgi;89Ete8nzgY z8PSY1jmyXF)a;mc^>(B7bo*HQ1NNg1st!zt z28YLv>W*y3CdWx9U4N$}r=w2KolTti&h5_gE;cUfT+X>7t{$#Mt^;l|ZlP|~Zjap6 z+!Nee+-E&3Jl1-g^F(|4c<%BX@lx_)c{O{@dRuv~^X~N_`2_n^`#kp5^X2 zj2>R4y()XvmDLKXQ&yjjk&I!+oQOrohQ}U>eb4k~HZbSnyy9x(W?3$*y{u`s_YbV#g7oZ-4~tGO?dJd^5@=9B%C4<&y}2~TND#ihok zp5)2!l6k#p%4ykYgX#L|h3TVfY}V{qGt2kkH)TK>t1`L-RMF2=zfecGML3pepIMXn zCMzuKM7DG`FS|cSFK2tsWUhPew`);rS!;XpRP#3Fjeo6kT35dwS|7K*XM_5Nf(;WJ zJvJWRMA($P>8E^?{IdL4o5MGE7bq2MEEwP7v8AO@qL5!WvekBL-8R%V?zVyL=G&{b ze=K4bT`e{#t|)$A!YaA?jp;X)-+bB;zhj`(vULAW%ue3U;av{94wp%n<(7@__S@Z2 zPA@Mie}AQwPOQFN<6P5Lt600ec77jw-_U-? z{jGIMb;Wh>4sZ|LsrRVwXwYh?IEXozdGJYNSYzL}jBlHp6q<^gJ{;m58a*6zxVPD= zx%r6Vkr^j5!`X2{BzCX?yfA&kpFYhM` zo{*nZOsY&aPnk`fns%SQ@pR?WiD&807FT8pf0h2V_PNgUAAWQEt$#LRcH#y9#i!p( zUdq2b^lI6wp1FXzN3T;~FU%Lck$-deE#qz9yYP3D3t8{6?<+s(e(3(_^YOu_)K8!O z1p}D#{E@&~+mRtJkzy2o5e!L0K~#9!?VJgik5%8thwLOfk&-2neXQ9+hU~isQ9?xu zkwS}?Y{`>^^2TJ3$MV``Y-1R+7{l0=v1Ki5$X0!y`*W`M{I7fd{-cqt#{919cg=m@ z|8phZO6uCRt72keoN3m79M0ei1VPiMPuD{aJ>*>VOX5V# z{rdF-2s<3kRX?qD70UTD58l2nf()k3AOW{;XNEs&nVgYS*rv(xy%8xz7Cs3Ka01 zXULF2Pe1*%InI$Ihk37UhcWg1^UoW@Dt-F&o^N*F52s6imrf;0lu*^GRrTC+L# z>U#L$hi~X_jT$x7vu95gE?n50V|#JzZc9HNfBbQCoHuXYc*o~XG5x)I^=gdYi4!Ld zF&Ot61Pd1~1clnYd$;+!di840Z>T40qs*H(Pv_2^(~m#?Xxd@r=E{}J9G^USQpb)R zGsle@H8Smg>(;Gn&VTypC!IfkUcdbEivbM3efi~==C|U-i<|QoUUhWy==5|Ni?bRjQP^UbbvmbG>21hI-Rl({}};zaG=zh4nvi zrHVO!XH|as>8GCSOy-CYBg`>U5@Myl`|i8uH+MgfI2SHlh$C^_Z2Lw#&XE*I86*h6 zaDxEAuUogy93MS;)L8KxH)+zuJi~(dPI0D8ndHp>K0vUKlY0$<@bGZYK*Ox$%a<=J zS+Zmb4i5Gp-$AMwfH`yKcm}~v-b*jNWW*+afLgqGv0i@pWi#QZ3;SHeH-zXNHf)$y zty*Oy&A4&nj2ORi<%&lVaGiU?!otjZY0tCQuU~Jjj~X?~fX&^HX3d(J=g*iiLz5>@ z*3_v}Z%|KmRkO-b8C=VrJ-aSmyl5uawwpbBwg&`A99(vnOJ^29q5}Z~Z_g3Uj(uW( zCXm6JG-;B#o-$=hefZ&rI&$QQ8Hl!R+Zz21p(a>`h*>5QF^d{-zlRAyYB1qneDQ^m z5&(zEXV95cUm##54jnpF8#it=l8NiXhY#1jefxZZVA`~43JeVNJm0&&UAlD9&Ye3= zTfjxX`2GeB8hF|ObPIxrhzMEw{rBI0Rl9cWJ3a^Z9R!GJ3j#zbE11FOJSr;6=+VrX zGpj|57M^>!zI^#|qXw>Dzi!k8*R6ZYbqG~r@0l`Xihlj|S98oNwK}(V@7|^@(#Pt1 zw>tRfqmMiWoRvB~di2ou-+v#cAFsUf3InNBsZ#muCx%}8_U%3A6DCa1sZ*zajKn*0 z=8Q)r!lzH4HqykZgYMnCtA73Z1_ah%OjIC1EJGn7A!el>K781SNPc6*pue$RA&f!* z0M)8h%cEy~STspGbPz^`4qX7vAt4I4~b3oz^iYk&d>0BOA<&fj_G9nbe1 zI&>)Ufq+%aAiVwd+r}Pn2di-X>_8&U2M!!)M7cE(vt-F)R){ZG41VUBXN;lu@y8!~ z+)5aO5~IxRGFqTn|>mFWyzgJlXHc2fg^>izW~RfBWsXCZR+$FDNKT_3G8T?*m3ai`)fq z1BmjwyZJucTd`(xFhM!)4p+V2Jj3fV*qQ};rF|Lk4fZEg;N%-K|bZpJEAS{SYhvsS6%oYkuQ zf2&n=W{AqnS*t0>W@y9ZK+QQbT^qGRyA`Uyh>BT=V{6csL3R(MRf8f`dBGZ0S-e(NmIkZFieQyo7^(_OL$vVJG-vWB zDd@sfgTC#+|LO=;4i44YU#99OO>m^a9L1cPq-$f}k>(7O zz8k73JsT-oru6YnB&!x85p=5{VDiWidS7QHKxFtVSRerB-FE!=@#Z%s-d%O%7Uv{| zAPQEzZ32=>oUE?Kf9PQ6`1nd};5SDu@H z$wZRxx6*(NB}65XcUx)|A?gya^eG(S*j*-uok7tGWYgRh1k~rTDj};XkT#*Ap{7`c zGBRJ^PaQ*iE0)?sYa=o7zH9thpW-faJAgIQH3sl9#xyrRno_fh@0(9{@lLO0_X42KGKq&(qTs` zIF4nj+C^^o0IG1HnKNg`+es#YR4WFZt@s@=SJ%KzV|h-dle;1exv2up+g5VfD~N# zs-2@FOybg|OYQzSldC7s55?zyG9vaM_EXyGV!Kkk*;W;^qKE*RB76s&Zc$2Aj~l2K z1gtE;1=)(IgfJkuS%C=E%9PrDUbRe&Q)s{b65FvS$l& zZw&-Fva8Xa2(>uA%S?K+{gG;MaFbdbj?%vlMye(NIJ8N-%5~Q1!p*dQr)&!yC|g_C z7C94eeYA9RuqKaa;J7~V+XT3Lwgj8{JYTMp1&1}7u=3Hx7CgS(G3pWR#9BZsTC~XL zH&}34_tUO=yaDbeG|kp5-b|(36a;C1b7oibgHdX8Zm(J%*{oK_qV=y6(Q0=xN&z~k_CIdcR{tJ4 zlD~tt*6gg=wr94e!}%?$ z??`}-hocoly-AM!^HZ5V9b1z`RWx}_P&jrOugzymTbyhz*+g1!? z9Fj@2^^X9KDrww6Vi<3|^_I^Z3B>yWK1Lv_50&HgmMA&1VPjOAHKLJ@Oe|7@$)-ND zbm`J@-a%O%L>}fZM-0UcFqO&tk;&}Dy&)|MHn=*RnLZ{4A~ zT5pKLo^7utx$@ms_>vXGpxWdNmO2weaEFdiFNpqiM-4IT*bIW6L^9AGkHOa_5X391 zj35jCG%la7{g)V_>~}z?+VXISJqos(naRZ{B{0N<+KS}9eft_i4IuFSs3l((IqCo# z0zHnAhiV{y0E7s4ODk-G(W6Jl*~NrJ0Q@W#o&yN!i+3{1+7NC4-#Q3#=TOHBJM_8^ zsmmYR)Y6dvU1GOsX~}U?Os!pm&X_5uslzeHE%Or1GVRS2=V@U^M)kFQdQ01$fr zPW_jE5bs@5cWRfn-9W?6CK62v1_8TLZ6L-Iq{*L0U35x=&R$ore~d;yGD!I{=Sx(R z?`8}z2+Q49<`G}qy^H8}i$#2ejBl5*tB9#!8zuB#4dCKBfQjg2aERhGmD8uL@7=y8YN0c%#_S>^HowzOr&<*8Oeklz}VeAq_ zvL^l&-@mnm11O5QcJ10W$A>(K3xO}0#Q$7AdGh3e3l}bs`QjfJ4kZ8Op7Z|#jqw*} TtukJ}00000NkvXXu0mjfPt@3v diff --git a/data/providers/skydrive.png b/data/providers/skydrive.png index 5e8f45a27f61cc08fedf8b7ddf5abf90d7a44d02..ebb6f016e82171108f823ef6c40e9df99244d5fe 100644 GIT binary patch literal 1261 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-s3dtTpz6=aiY77hwEes65fIO>_%)p?h48n{ROYO^m3Ql;s zIEHu}Pfn0vbrv>AV)r?tvnJ<_%nTt5lLDjS!p|Q*eH32l=n&vh!N}3k(IvRpF(!#o z#>2}~_=9m9O*S{O&~^ z;}-kz^gOOfm{ms}?fp1x2O=Ze=iE(U!5I(R#(Tdw$aW zzgX2uT@`rsCK)vTVq3`i!*Q`;I-!2>rq zKRZnqN#uQcm#4>eufR5y{cMT6VYLT3Ub8Qs#%d?5rY3wPz?5@}iHusaW$>OU99c80 zc<20BcK(IQTfe!H$;RCczwX_9cVcOq$>TQ*EPq^Ce*UP&^k<>x`!^kBoTV+?IJ0`e f>!v^leFlb0!fbIXR23D05zXM~>gTe~DWM4fR8ZoZ literal 3469 zcmV;84RZ2{P)|D^_ww@lRz|vCuzLs)$;-`! zo*{AqUjza0dRV*yaMRE;fKCVhpQKsoe1Yhg01=zBIT!& zC1$=TK@rP|Ibo3vKKm@PqnO#LJhq6%Ij6Hz*<$V$@wQAMN5qJ)hzm2hoGcOF60t^# zFqJFfH{#e-4l@G)6iI9sa9D{VHW4w29}?su;^hF~NC{tY+*d5%WDCTXa!E_i;d2ub z1#}&jF5T4HnnCyEWTkKf0>c0%E1Ah>(_PY1)0w;+02c53Su*0<(nUqKG_|(0G&D0Z z{i;y^b@OjZ+}lNZ8Th$p5Uu}MTtq^NHl z*T1?CO*}7&0ztZsv2j*bmJyf3G7=Z`5B*PvzoDiKdLpOAxi2$L0#SX*@cY_n(^h55xYX z#km%V()bZjV~l{*bt*u9?FT3d5g^g~#a;iSZ@&02Abxq_DwB(I|L-^bXThc7C4-yr zInE_0gw7K3GZ**7&k~>k0Z0NWkO#^@9q0fwx1%qjZ=)yBuQ3=5 z4Wo^*!gyjLF-e%Um=erBOdIALW)L%unZshS@>qSW9o8Sq#0s#5*edK%>{;v(b^`kb zN5rY%%y90wC>#%$kE_5P!JWYk;U;klcqzOl-UjcFXXA75rT9jCH~u<)0>40zCTJ7v z2qAyk54cquI@7b&LHdZ`+zlTss6bJ7%PQ)z$cROu4wBhpu-r)01)S~6}jY?%U? zgEALn#wiFzo#H}aQ8rT=DHkadR18&{>P1bW7E`~Y4p3)hWn`DhhRJ5j*2tcg9i<^O zEt(fCg;q*CP8+7ZTcWhYX$fb^_9d-LhL+6BEtPYWVlfK zTBusSTASKKb%HuWJzl+By+?gkLq)?+BTu761jmyXF)a;mc z^>(B7bo*HQ1NNg1st!zt28YLv>W*y3CdWx9U8f|cqfXDAO`Q48?auQqHZJR2&bcD4 z9Ip>EY~kKEPV6Wm+eXFV)D)_R=tM0@&p?(!V*Qu1PXHG9o^TY0bZ?)4%0 z1p8F`JoeS|<@=<@RE7GY07EYX@lwd>4oW|Yi!o+Su@M`;WuSK8LKk71XR(_ zRKHM1xJ5XYX`fk>`6eqY>qNG6HZQwBM=xi4&Sb88?zd}EYguc1@>KIS<&CX#T35dw zS|7K*XM_5Nf(;WJJvJWRMA($P>8E^?{IdL4o5MGE7bq2MEEwP7v8AO@qL5!WvekBL z-8R%V?zVyL=G&{be=K4bT`e{#t|)$A!YaA?jp;X)-+bB;zhj`(vULAW%ue3U;av{9 z4wp%n<(7@__S@Z2PA@Mif3+uO&y|X06?J#o zSi8M;ejj_^(0<4Lt#wLu#dYrva1Y$6_o(k^&}yhSh&h;f@JVA>W8b%oZ=0JGnu?n~ z9O4}sJsfnnx7n(>`H13?(iXTy*fM=I`sj`CT)*pTHEgYKqqP+u1IL8No_-(u{qS+0 z<2@%BCt82d{Gqm;(q7a7b>wu+b|!X?c13m#p7cK1({0<`{-e>4hfb-UsyQuty7Ua; zOu?B?XLHZaol8GAb3Wnxcu!2v{R_`T4=x`(GvqLI{-*2AOSimkUAw*F_TX^n z@STz9kDQ$NC=!KfXWC z8h`dn#xL(D3Z9UkR7|Q&Hcy#Notk!^zVUSB(}`#4&lYA1f0h2V_PNgUAAWQEt$#LR zcH#y9#i!p(Udq2b^lI6wp1FXzN3T;~FU%Lck$-deE#qz9yYP3D3t8{6?<+s(e(3(_ z^YOu_)K8!O1p}D#{Jgc%9RL6TAY({UO#lFTB>(_`g8%^e{{R4h=>PzAFaQARU;qF* zm;eA5Z<1fdMgRZ+32;bRa{vG?BLDy{BLR4&KXw2B0?tW9K~!ko?U-3e6=4*|Zxodf zm9(#7Xi!8FLD2HlrKClXpoMS&LyYi63-Y1W!U`(zsSwd#gdn0&>!qLtDsTgXb}S+y zh$vdfR;T}o|HMsZ`|h2&Gtu|(d%5?1bIpcO2Rn!rrZ zW)rj(Z@>;PED8cs!F7e;O@1(~(jqV)RDlzq0n~!!U?gZvB6yQ;pdd(r**r-;Sp4~C zaGOEc1^5Mgb&==>lY$Uf0QwYnbP(JEN5B@a8svjg-l=Cc>&pEWmQcy3Mbc@mlfXF8?(t$$pqBBW-2_g9-T;F)sc;e~ z_IQ!Yl$EM_Hw{52ve!;vvd7eU&e{-X|6`;Xx$_&ifqx0qu`hSKzyXlKLB$A>YwXYd z2(+@qJ1zRiypM+*yh#^F*53k!;GWBZ7cBc#5fKm$ffZ&h?emcTvpD`mMLj^n{N%tI?-c;WLnD1|LIKaFPA$aM2*ZA>XXdcUZ2M3eR vfazi@Q(}dAKnrLAEuaOoK$!dj`B`}^S)|f600000NkvXXu0mjfTIPl5 diff --git a/data/providers/wikipedia.png b/data/providers/wikipedia.png index 4a84436fa43d5a911d8600e97b28e8c4b9d17d0a..cd501b2aaaf3f86aa0f25596ca940835c86d021b 100644 GIT binary patch delta 510 zcmVfP?@5`Tzg`fam}Kbua(` z>RI+y?e7jT@qQ9J+u00Lr5M??VshmXv^00009a7bBm000XU000XU0RWnu7ytkP zg-Jv~R7l6IRa{m5g3A|2owgJ51pJl z*GZGAmk-ZIy47R%bN~RhjJ!7@TcqH0cXEy?tzHuCh7lG19>)z?kPcv5mi`X}55SxG z;~58hU&N09zSQUoKz6JN`FTbT+zG1q%E*CEkmtmSUPfznB$3oeQ<_Ym9k5t z#)M#$HL@Xt!G9ycPKjTunXqe~r+I}N)+&9VcHc}e%DHBj&NvVp6oF%{N(XuXW@^Gc zJ)KGq1bc-Q!9Wmda>6@;qe}4RIEH{CXINmpeq3DVf}mfB*DWyFs{3Cdh^&m5Q7jYG z__F#UMV0V7!C6el z#_Y+dTDd}y#cOB%ooHeGaD||gyU+TMbNTW%f-K&!*i(NiL8?T(UT554WA#mZ0^k*H z0QgI<|0?Z|UN>CqeZ`Gsi+$0nzDIF$1N; A-2eap literal 3203 zcmV-}41Dv6P)|D^_ww@lRz|vCuzLs)$;-`! zo*{AqUjza0dRV*yaMRE;fKCVhpQKsoe1Yhg01=zBIT!& zC1$=TK@rP|Ibo3vKKm@PqnO#LJhq6%Ij6Hz*<$V$@wQAMN5qJ)hzm2hoGcOF60t^# zFqJFfH{#e-4l@G)6iI9sa9D{VHW4w29}?su;^hF~NC{tY+*d5%WDCTXa!E_i;d2ub z1#}&jF5T4HnnCyEWTkKf0>c0%E1Ah>(_PY1)0w;+02c53Su*0<(nUqKG_|(0G&D0Z z{i;y^b@OjZ+}lNZ8Th$p5Uu}MTtq^NHl z*T1?CO*}7&0ztZsv2j*bmJyf3G7=Z`5B*PvzoDiKdLpOAxi2$L0#SX*@cY_n(^h55xYX z#km%V()bZjV~l{*bt*u9?FT3d5g^g~#a;iSZ@&02Abxq_DwB(I|L-^bXThc7C4-yr zInE_0gw7K3GZ**7&k~>k0Z0NWkO#^@9q0fwx1%qjZ=)yBuQ3=5 z4Wo^*!gyjLF-e%Um=erBOdIALW)L%unZshS@>qSW9o8Sq#0s#5*edK%>{;v(b^`kb zN5rY%%y90wC>#%$kE_5P!JWYk;U;klcqzOl-UjcFXXA75rT9jCH~u<)0>40zCTJ7v z2qAyk54cquI@7b&LHdZ`+zlTss6bJ7%PQ)z$cROu4wBhpu-r)01)S~6}jY?%U? zgEALn#wiFzo#H}aQ8rT=DHkadR18&{>P1bW7E`~Y4p3)hWn`DhhRJ5j*2tcg9i<^O zEt(fCg;q*CP8+7ZTcWhYX$fb^_9d-LhL+6BEtPYWVlfK zTBusSTASKKb%HuWJzl+By+?gkLq)?+BTu761jmyXF)a;mc z^>(B7bo*HQ1NNg1st!zt28YLv>W*y3CdWx9U8f|cqfXDAO`Q48?auQqHZJR2&bcD4 z9Ip>EY~kKEPV6Wm+eXFV)D)_R=tM0@&p?(!V*Qu1PXHG9o^TY0bZ?)4%0 z1p8F`JoeS|<@=<@RE7GY07EYX@lwd>4oW|Yi!o+Su@M`;WuSK8LKk71XR(_ zRKHM1xJ5XYX`fk>`6eqY>qNG6HZQwBM=xi4&Sb88?zd}EYguc1@>KIS<&CX#T35dw zS|7K*XM_5Nf(;WJJvJWRMA($P>8E^?{IdL4o5MGE7bq2MEEwP7v8AO@qL5!WvekBL z-8R%V?zVyL=G&{be=K4bT`e{#t|)$A!YaA?jp;X)-+bB;zhj`(vULAW%ue3U;av{9 z4wp%n<(7@__S@Z2PA@Mif3+uO&y|X06?J#o zSi8M;ejj_^(0<4Lt#wLu#dYrva1Y$6_o(k^&}yhSh&h;f@JVA>W8b%oZ=0JGnu?n~ z9O4}sJsfnnx7n(>`H13?(iXTy*fM=I`sj`CT)*pTHEgYKqqP+u1IL8No_-(u{qS+0 z<2@%BCt82d{Gqm;(q7a7b>wu+b|!X?c13m#p7cK1({0<`{-e>4hfb-UsyQuty7Ua; zOu?B?XLHZaol8GAb3Wnxcu!2v{R_`T4=x`(GvqLI{-*2AOSimkUAw*F_TX^n z@STz9kDQ$NC=!KfXWC z8h`dn#xL(D3Z9UkR7|Q&Hcy#Notk!^zVUSB(}`#4&lYA1f0h2V_PNgUAAWQEt$#LR zcH#y9#i!p(Udq2b^lI6wp1FXzN3T;~FU%Lck$-deE#qz9yYP3D3t8{6?<+s(e(3(_ z^YOu_)K8!O1p}D#{Fkv~6#xJLAY({UO#lFTB>(_`g8%^e{{R4h=>PzAFaQARU;qF* zm;eA5Z<1fdMgRZ+32;bRa{vGf6951U69E94oEQKA0mMl}K~z}7?N@EFgfI+50uqpb z1SB8<2}q~|Bp?9^NI(J-kkGs3UEVAuDIfRl`sZb)GdGu}*=)K2vg~Evd-q(6|GXiG z%h;ZOO#b^eapkGZWnZG*Y)9r3+dqI6fOF1V^E~^$?{E3Xaa@-byDZBOfUfI&Q4}7c z;MFwEx@i~&UzX*@m*=@}+xFLARn^9a*lC*9h2I>DT*$d=0UuJ=^^Pw5$KZB!zLF!U z6&uEF0Dvy80@bmBZp$yRQdwxIT01j~RjD1ubh00DNTL~9g#GCIp$eDobodKz*Pk&?^`0OY|Weql$uyq5uJl9cK#me~I%?*lA3^g7f%4<=#6 znhUo8u;et|^Z2$#_*(!%$!X)6S+d6NTd!n7tyP_{bVho&0K^`td>Ju2KK4>7?{P7Z pSE?5P$v;feewro!I8FU|{s0N@lHtW*&NKi3002ovPDHLkV1kBu3kLuI From 7bfe32c7df6af9d9c281d54a2070902ee5b488b8 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 16 Apr 2015 23:22:53 +0200 Subject: [PATCH 016/104] Avoid warning message when the level exceeds the threshold --- ext/libclementine-common/core/logging.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/libclementine-common/core/logging.cpp b/ext/libclementine-common/core/logging.cpp index b0a3564d8..3b1fdb72b 100644 --- a/ext/libclementine-common/core/logging.cpp +++ b/ext/libclementine-common/core/logging.cpp @@ -104,6 +104,7 @@ void Init() { sClassLevels = new QMap(); sNullDevice = new NullDevice; + sNullDevice->open(QIODevice::ReadWrite); // Catch other messages from Qt if (!sOriginalMessageHandler) { From 0938e81711f4439614467eeeca2debc3874f0abc Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 17 Apr 2015 10:38:38 +0200 Subject: [PATCH 017/104] Avoid "QFSFileEngine::open: No file name specified" messages if we know that the filename is empty --- src/covers/albumcoverloader.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/covers/albumcoverloader.cpp b/src/covers/albumcoverloader.cpp index 8ebf51cce..a1a4582ef 100644 --- a/src/covers/albumcoverloader.cpp +++ b/src/covers/albumcoverloader.cpp @@ -196,6 +196,9 @@ AlbumCoverLoader::TryLoadResult AlbumCoverLoader::TryLoadImage( QMetaObject::invokeMethod(spotify, "LoadImage", Qt::QueuedConnection, Q_ARG(QString, id)); return TryLoadResult(true, false, QImage()); + } else if (filename.isEmpty()) { + // Avoid "QFSFileEngine::open: No file name specified" messages if we know that the filename is empty + return TryLoadResult(false, false, task.options.default_output_image_); } QImage image(filename); From bd2afec1072e8b676bfc3699637a925495478953 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 3 Jun 2015 12:27:27 +0200 Subject: [PATCH 018/104] Fix warning message in behavioursettingspage ui page --- src/ui/behavioursettingspage.ui | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ui/behavioursettingspage.ui b/src/ui/behavioursettingspage.ui index 1c894fb2e..005a7c96f 100644 --- a/src/ui/behavioursettingspage.ui +++ b/src/ui/behavioursettingspage.ui @@ -7,7 +7,7 @@ 0 0 516 - 753 + 792 @@ -180,9 +180,9 @@ - Pressing "Previous" in player will... + Pressing "Previous" in player will... - + From 5d343cbe7f45d176aef3b803e8f4faac4753b466 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 3 Jun 2015 23:13:06 +0200 Subject: [PATCH 019/104] remove useless qt_version defines --- src/CMakeLists.txt | 8 +------- src/core/utilities.cpp | 4 ---- src/internet/lastfm/lastfmservice.cpp | 7 ------- src/ui/behavioursettingspage.cpp | 2 -- src/ui/iconloader.cpp | 2 -- 5 files changed, 1 insertion(+), 22 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5a3151bd5..54faff4f5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,13 +17,7 @@ if(WIN32) endif(WIN32) # Activate fast QString concatenation -if (QT_VERSION_MINOR GREATER 5) - if (QT_VERSION_MINOR GREATER 7) - add_definitions(-DQT_USE_QSTRINGBUILDER) - else(QT_VERSION_MINOR GREATER 7) - add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS) - endif(QT_VERSION_MINOR GREATER 7) -endif(QT_VERSION_MINOR GREATER 5) +add_definitions(-DQT_USE_QSTRINGBUILDER) add_definitions(-DQT_NO_URL_CAST_FROM_STRING) add_definitions(-DBOOST_BIND_NO_PLACEHOLDERS) diff --git a/src/core/utilities.cpp b/src/core/utilities.cpp index f1d3cbefa..1ee8a6f30 100644 --- a/src/core/utilities.cpp +++ b/src/core/utilities.cpp @@ -693,16 +693,12 @@ bool IsLaptop() { } QString SystemLanguageName() { -#if QT_VERSION >= 0x040800 QString system_language = QLocale::system().uiLanguages().empty() ? QLocale::system().name() : QLocale::system().uiLanguages().first(); // uiLanguages returns strings with "-" as separators for language/region; // however QTranslator needs "_" separators system_language.replace("-", "_"); -#else - QString system_language = QLocale::system().name(); -#endif return system_language; } diff --git a/src/internet/lastfm/lastfmservice.cpp b/src/internet/lastfm/lastfmservice.cpp index 11d20c905..ba7430b47 100644 --- a/src/internet/lastfm/lastfmservice.cpp +++ b/src/internet/lastfm/lastfmservice.cpp @@ -28,14 +28,7 @@ // some functions in their includes files, which aren't compatible with // QStringBuilder, we undef it here #include -#if QT_VERSION >= 0x040600 -#if QT_VERSION >= 0x040800 #undef QT_USE_QSTRINGBUILDER -#else -#undef QT_USE_FAST_CONCATENATION -#undef QT_USE_FAST_OPERATOR_PLUS -#endif // QT_VERSION >= 0x040800 -#endif // QT_VERSION >= 0x040600 #include "lastfmservice.h" diff --git a/src/ui/behavioursettingspage.cpp b/src/ui/behavioursettingspage.cpp index 4def22470..b8df4f8ff 100644 --- a/src/ui/behavioursettingspage.cpp +++ b/src/ui/behavioursettingspage.cpp @@ -70,12 +70,10 @@ BehaviourSettingsPage::BehaviourSettingsPage(SettingsDialog* dialog) .replace("_TW", "_Hant_TW"); QString language_name = QLocale::languageToString(QLocale(lookup_code).language()); -#if QT_VERSION >= 0x040800 QString native_name = QLocale(lookup_code).nativeLanguageName(); if (!native_name.isEmpty()) { language_name = native_name; } -#endif QString name = QString("%1 (%2)").arg(language_name, code); language_map_[name] = code; diff --git a/src/ui/iconloader.cpp b/src/ui/iconloader.cpp index 7f0422a88..c5cce40a6 100644 --- a/src/ui/iconloader.cpp +++ b/src/ui/iconloader.cpp @@ -33,11 +33,9 @@ QIcon IconLoader::Load(const QString& name) { if (name.isEmpty()) return ret; -#if QT_VERSION >= 0x040600 // Try to load it from the theme initially ret = QIcon::fromTheme(name); if (!ret.isNull()) return ret; -#endif // Otherwise use our fallback theme const QString path(":/icons/%1x%2/%3.png"); From f4ca305fd796132711daca502af293d20b5ead00 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 4 Jun 2015 10:37:34 +0200 Subject: [PATCH 020/104] remove useless qhash_qurl --- src/core/qhash_qurl.h | 29 ------------------------ src/internet/podcasts/gpoddersync.cpp | 1 - src/internet/podcasts/podcastupdater.cpp | 1 - src/moodbar/moodbaritemdelegate.cpp | 1 - src/moodbar/moodbarloader.cpp | 1 - src/playlist/playlist.cpp | 1 - 6 files changed, 34 deletions(-) delete mode 100644 src/core/qhash_qurl.h diff --git a/src/core/qhash_qurl.h b/src/core/qhash_qurl.h deleted file mode 100644 index d7d2924c3..000000000 --- a/src/core/qhash_qurl.h +++ /dev/null @@ -1,29 +0,0 @@ -/* This file is part of Clementine. - Copyright 2012, David Sansome - Copyright 2014, Krzysztof Sobiecki - Copyright 2014, John Maguire - - Clementine is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Clementine 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 Clementine. If not, see . -*/ - -#ifndef CORE_QHASH_QURL_H_ -#define CORE_QHASH_QURL_H_ - -#include - -#if QT_VERSION < 0x040700 -inline uint qHash(const QUrl& url) { return qHash(url.toEncoded()); } -#endif - -#endif // CORE_QHASH_QURL_H_ diff --git a/src/internet/podcasts/gpoddersync.cpp b/src/internet/podcasts/gpoddersync.cpp index bf8e15067..6e54d41cb 100644 --- a/src/internet/podcasts/gpoddersync.cpp +++ b/src/internet/podcasts/gpoddersync.cpp @@ -31,7 +31,6 @@ #include "core/closure.h" #include "core/logging.h" #include "core/network.h" -#include "core/qhash_qurl.h" #include "core/timeconstants.h" #include "core/utilities.h" diff --git a/src/internet/podcasts/podcastupdater.cpp b/src/internet/podcasts/podcastupdater.cpp index 6876faed5..60da225b2 100644 --- a/src/internet/podcasts/podcastupdater.cpp +++ b/src/internet/podcasts/podcastupdater.cpp @@ -25,7 +25,6 @@ #include "core/application.h" #include "core/closure.h" #include "core/logging.h" -#include "core/qhash_qurl.h" #include "core/timeconstants.h" #include "podcastbackend.h" #include "podcasturlloader.h" diff --git a/src/moodbar/moodbaritemdelegate.cpp b/src/moodbar/moodbaritemdelegate.cpp index c3a20ff87..b158ec856 100644 --- a/src/moodbar/moodbaritemdelegate.cpp +++ b/src/moodbar/moodbaritemdelegate.cpp @@ -21,7 +21,6 @@ #include "moodbarrenderer.h" #include "core/application.h" #include "core/closure.h" -#include "core/qhash_qurl.h" #include "playlist/playlist.h" #include "playlist/playlistview.h" diff --git a/src/moodbar/moodbarloader.cpp b/src/moodbar/moodbarloader.cpp index 578e8b4d6..5c886f958 100644 --- a/src/moodbar/moodbarloader.cpp +++ b/src/moodbar/moodbarloader.cpp @@ -31,7 +31,6 @@ #include "core/application.h" #include "core/closure.h" #include "core/logging.h" -#include "core/qhash_qurl.h" #include "core/utilities.h" MoodbarLoader::MoodbarLoader(Application* app, QObject* parent) diff --git a/src/playlist/playlist.cpp b/src/playlist/playlist.cpp index dcb0897d3..34ff0726e 100644 --- a/src/playlist/playlist.cpp +++ b/src/playlist/playlist.cpp @@ -48,7 +48,6 @@ #include "core/closure.h" #include "core/logging.h" #include "core/modelfuturewatcher.h" -#include "core/qhash_qurl.h" #include "core/tagreaderclient.h" #include "core/timeconstants.h" #include "internet/jamendo/jamendoplaylistitem.h" From 4943bca87789bdae771f11bf2a90df1821e8954d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 11 Jun 2015 11:35:30 +0200 Subject: [PATCH 021/104] Fix release compilation error because of qt_no_debug_output flag --- CMakeLists.txt | 1 + ext/libclementine-common/core/logging.h | 36 ++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cfceb30c..103729eaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,6 +140,7 @@ find_package(Threads) if(${CMAKE_BUILD_TYPE} MATCHES "Release") add_definitions(-DNDEBUG) add_definitions(-DQT_NO_DEBUG_OUTPUT) + add_definitions(-DQT_NO_WARNING_OUTPUT) endif(${CMAKE_BUILD_TYPE} MATCHES "Release") # Set up definitions and paths diff --git a/ext/libclementine-common/core/logging.h b/ext/libclementine-common/core/logging.h index 8cba187ea..32a34c2d1 100644 --- a/ext/libclementine-common/core/logging.h +++ b/ext/libclementine-common/core/logging.h @@ -27,10 +27,44 @@ #define qLog(level) \ while (false) QNoDebug() #else -#define qLog(level) \ +#define qLog(level) \ + qLog##level() + +#define qCreateLogger(level) \ logging::CreateLogger(logging::Level_##level, \ logging::ParsePrettyFunction(__PRETTY_FUNCTION__), \ __LINE__) + +#define qLogFatal() \ + qCreateLogger(Fatal) + +#define qLogError() \ + qCreateLogger(Error) + +#ifdef QT_NO_WARNING_OUTPUT +#define qLogWarning() \ + while (false) QNoDebug() +#else +#define qLogWarning() \ + qCreateLogger(Warning) +#endif + + +#ifdef QT_NO_DEBUG_OUTPUT +#define qLogInfo() \ + while (false) QNoDebug() + +#define qLogDebug() \ + while (false) QNoDebug() +#else +#define qLogInfo() \ + qCreateLogger(Info) + +#define qLogDebug() \ + qCreateLogger(Debug) +#endif + + #endif namespace logging { From 369ff1be237eac9346f731de40b0911c18d3df6a Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 11 Jun 2015 12:10:07 +0200 Subject: [PATCH 022/104] Update cmakelists min version to 2.8.11 --- 3rdparty/fancytabwidget/CMakeLists.txt | 2 +- 3rdparty/libmygpo-qt5/CMakeLists.txt | 2 +- 3rdparty/qsqlite/CMakeLists.txt | 2 +- 3rdparty/qtiocompressor/CMakeLists.txt | 2 +- 3rdparty/qtsingleapplication/CMakeLists.txt | 2 +- 3rdparty/qtwin/CMakeLists.txt | 2 +- 3rdparty/qxt/CMakeLists.txt | 2 +- CMakeLists.txt | 2 +- gst/moodbar/CMakeLists.txt | 2 +- tests/CMakeLists.txt | 2 +- tools/ultimate_lyrics_parser/CMakeLists.txt | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/3rdparty/fancytabwidget/CMakeLists.txt b/3rdparty/fancytabwidget/CMakeLists.txt index 122f38a57..06319355a 100644 --- a/3rdparty/fancytabwidget/CMakeLists.txt +++ b/3rdparty/fancytabwidget/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.11) set(SOURCES fancytabwidget.cpp diff --git a/3rdparty/libmygpo-qt5/CMakeLists.txt b/3rdparty/libmygpo-qt5/CMakeLists.txt index dd47ad1ac..d53edbc8d 100644 --- a/3rdparty/libmygpo-qt5/CMakeLists.txt +++ b/3rdparty/libmygpo-qt5/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required( VERSION 2.6 FATAL_ERROR ) +cmake_minimum_required( VERSION 2.8.11 FATAL_ERROR ) set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII" ) diff --git a/3rdparty/qsqlite/CMakeLists.txt b/3rdparty/qsqlite/CMakeLists.txt index cd958d93c..e6f28d673 100644 --- a/3rdparty/qsqlite/CMakeLists.txt +++ b/3rdparty/qsqlite/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.11) add_definitions(-DQT_STATICPLUGIN) diff --git a/3rdparty/qtiocompressor/CMakeLists.txt b/3rdparty/qtiocompressor/CMakeLists.txt index 03578c554..090a057a6 100644 --- a/3rdparty/qtiocompressor/CMakeLists.txt +++ b/3rdparty/qtiocompressor/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.11) set(IOCOMPRESSOR-SOURCES qtiocompressor.cpp diff --git a/3rdparty/qtsingleapplication/CMakeLists.txt b/3rdparty/qtsingleapplication/CMakeLists.txt index 975881adb..75d098d69 100644 --- a/3rdparty/qtsingleapplication/CMakeLists.txt +++ b/3rdparty/qtsingleapplication/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.11) set(SINGLEAPP-SOURCES qtlocalpeer.cpp diff --git a/3rdparty/qtwin/CMakeLists.txt b/3rdparty/qtwin/CMakeLists.txt index c2df87bfc..6859c43a4 100644 --- a/3rdparty/qtwin/CMakeLists.txt +++ b/3rdparty/qtwin/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.11) set(QTWIN-SOURCES qtwin.cpp diff --git a/3rdparty/qxt/CMakeLists.txt b/3rdparty/qxt/CMakeLists.txt index af8765568..6514a6472 100644 --- a/3rdparty/qxt/CMakeLists.txt +++ b/3rdparty/qxt/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.11) set(QXT-SOURCES qxtglobal.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 103729eaf..836902c1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.11) cmake_policy(SET CMP0011 OLD) include(CheckCXXCompilerFlag) diff --git a/gst/moodbar/CMakeLists.txt b/gst/moodbar/CMakeLists.txt index 2606c1baa..6ffc793e0 100644 --- a/gst/moodbar/CMakeLists.txt +++ b/gst/moodbar/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.11) set(CMAKE_C_FLAGS "-Wall") set(CMAKE_CXX_FLAGS "-Woverloaded-virtual -Wall --std=c++0x") diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 617704241..f589cc91d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -fpermissive -Wno-c++11-narrowing -U__STRICT_ANSI__") diff --git a/tools/ultimate_lyrics_parser/CMakeLists.txt b/tools/ultimate_lyrics_parser/CMakeLists.txt index e410d2eb4..347917ef0 100644 --- a/tools/ultimate_lyrics_parser/CMakeLists.txt +++ b/tools/ultimate_lyrics_parser/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 2.8.11) set(CMAKE_C_FLAGS "-Wall ${CMAKE_C_FLAGS}") set(CMAKE_CXX_FLAGS "-Woverloaded-virtual -Wall -Wno-sign-compare ${CMAKE_CXX_FLAGS}") From d755d5b602199280bf304e654a99f1616df4dcd0 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 11 Jun 2015 18:06:09 +0200 Subject: [PATCH 023/104] Use functions instead of macros for logs --- ext/libclementine-common/core/logging.h | 53 ++++++++++--------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/ext/libclementine-common/core/logging.h b/ext/libclementine-common/core/logging.h index 32a34c2d1..a572526b7 100644 --- a/ext/libclementine-common/core/logging.h +++ b/ext/libclementine-common/core/logging.h @@ -27,45 +27,16 @@ #define qLog(level) \ while (false) QNoDebug() #else + #define qLog(level) \ - qLog##level() + logging::CreateLogger##level() #define qCreateLogger(level) \ logging::CreateLogger(logging::Level_##level, \ logging::ParsePrettyFunction(__PRETTY_FUNCTION__), \ __LINE__) -#define qLogFatal() \ - qCreateLogger(Fatal) - -#define qLogError() \ - qCreateLogger(Error) - -#ifdef QT_NO_WARNING_OUTPUT -#define qLogWarning() \ - while (false) QNoDebug() -#else -#define qLogWarning() \ - qCreateLogger(Warning) -#endif - - -#ifdef QT_NO_DEBUG_OUTPUT -#define qLogInfo() \ - while (false) QNoDebug() - -#define qLogDebug() \ - while (false) QNoDebug() -#else -#define qLogInfo() \ - qCreateLogger(Info) - -#define qLogDebug() \ - qCreateLogger(Debug) -#endif - - -#endif +#endif // QT_NO_DEBUG_STREAM namespace logging { class NullDevice : public QIODevice { @@ -90,6 +61,24 @@ void DumpStackTrace(); QString ParsePrettyFunction(const char* pretty_function); QDebug CreateLogger(Level level, const QString& class_name, int line); +QDebug CreateLoggerFatal() { return qCreateLogger(Fatal); } +QDebug CreateLoggerError() { return qCreateLogger(Error); } + +#ifdef QT_NO_WARNING_OUTPUT +QNoDebug CreateLoggerWarning() { return QNoDebug(); } +#else +QDebug CreateLoggerWarning() { return qCreateLogger(Warning); } +#endif // QT_NO_WARNING_OUTPUT + +#ifdef QT_NO_DEBUG_OUTPUT +QNoDebug CreateLoggerInfo() { return QNoDebug(); } +QNoDebug CreateLoggerDebug() { return QNoDebug(); } +#else +QDebug CreateLoggerInfo() { return qCreateLogger(Info); } +QDebug CreateLoggerDebug() { return qCreateLogger(Debug); } +#endif // QT_NO_DEBUG_OUTPUT + + void GLog(const char* domain, int level, const char* message, void* user_data); extern const char* kDefaultLogLevels; From 98a450ad7783fe9d0ddd60084a27353a082834f1 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sat, 13 Jun 2015 20:51:18 +0200 Subject: [PATCH 024/104] Fix compilation error (logging macros) --- ext/libclementine-common/core/logging.cpp | 17 +++++++++++++++++ ext/libclementine-common/core/logging.h | 16 ++++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/ext/libclementine-common/core/logging.cpp b/ext/libclementine-common/core/logging.cpp index 3b1fdb72b..1e3c6d27e 100644 --- a/ext/libclementine-common/core/logging.cpp +++ b/ext/libclementine-common/core/logging.cpp @@ -267,4 +267,21 @@ void DumpStackTrace() { #endif } +QDebug CreateLoggerFatal() { return qCreateLogger(Fatal); } +QDebug CreateLoggerError() { return qCreateLogger(Error); } + +#ifdef QT_NO_WARNING_OUTPUT +QNoDebug CreateLoggerWarning() { return QNoDebug(); } +#else +QDebug CreateLoggerWarning() { return qCreateLogger(Warning); } +#endif // QT_NO_WARNING_OUTPUT + +#ifdef QT_NO_DEBUG_OUTPUT +QNoDebug CreateLoggerInfo() { return QNoDebug(); } +QNoDebug CreateLoggerDebug() { return QNoDebug(); } +#else +QDebug CreateLoggerInfo() { return qCreateLogger(Info); } +QDebug CreateLoggerDebug() { return qCreateLogger(Debug); } +#endif // QT_NO_DEBUG_OUTPUT + } // namespace logging diff --git a/ext/libclementine-common/core/logging.h b/ext/libclementine-common/core/logging.h index a572526b7..b04bf49d3 100644 --- a/ext/libclementine-common/core/logging.h +++ b/ext/libclementine-common/core/logging.h @@ -61,21 +61,21 @@ void DumpStackTrace(); QString ParsePrettyFunction(const char* pretty_function); QDebug CreateLogger(Level level, const QString& class_name, int line); -QDebug CreateLoggerFatal() { return qCreateLogger(Fatal); } -QDebug CreateLoggerError() { return qCreateLogger(Error); } +QDebug CreateLoggerFatal(); +QDebug CreateLoggerError(); #ifdef QT_NO_WARNING_OUTPUT -QNoDebug CreateLoggerWarning() { return QNoDebug(); } +QNoDebug CreateLoggerWarning(); #else -QDebug CreateLoggerWarning() { return qCreateLogger(Warning); } +QDebug CreateLoggerWarning(); #endif // QT_NO_WARNING_OUTPUT #ifdef QT_NO_DEBUG_OUTPUT -QNoDebug CreateLoggerInfo() { return QNoDebug(); } -QNoDebug CreateLoggerDebug() { return QNoDebug(); } +QNoDebug CreateLoggerInfo(); +QNoDebug CreateLoggerDebug(); #else -QDebug CreateLoggerInfo() { return qCreateLogger(Info); } -QDebug CreateLoggerDebug() { return qCreateLogger(Debug); } +QDebug CreateLoggerInfo(); +QDebug CreateLoggerDebug(); #endif // QT_NO_DEBUG_OUTPUT From 43c98fd74e3a4907400dd5950f7594f84bcbca73 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sat, 13 Jun 2015 23:01:52 +0200 Subject: [PATCH 025/104] Adapt spotify part to qt5 --- ext/clementine-spotifyblob/spotifyclient.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/clementine-spotifyblob/spotifyclient.cpp b/ext/clementine-spotifyblob/spotifyclient.cpp index 48af32316..30c3f8b13 100644 --- a/ext/clementine-spotifyblob/spotifyclient.cpp +++ b/ext/clementine-spotifyblob/spotifyclient.cpp @@ -697,7 +697,7 @@ void SpotifyClient::ConvertTrack(sp_track* track, pb::spotify::Track* pb) { const QByteArray art_id(reinterpret_cast(sp_album_cover( sp_track_album(track), SP_IMAGE_SIZE_LARGE)), kSpotifyImageIDSize); - const QString art_id_b64 = QString::fromAscii(art_id.toBase64()); + const QString art_id_b64 = QString::fromLatin1(art_id.toBase64()); pb->set_album_art_id(DataCommaSizeFromQString(art_id_b64)); // Artists @@ -732,7 +732,7 @@ void SpotifyClient::ConvertAlbum(sp_album* album, pb::spotify::Track* pb) { const QByteArray art_id( reinterpret_cast(sp_album_cover(album, SP_IMAGE_SIZE_LARGE)), kSpotifyImageIDSize); - const QString art_id_b64 = QString::fromAscii(art_id.toBase64()); + const QString art_id_b64 = QString::fromLatin1(art_id.toBase64()); pb->set_album_art_id(DataCommaSizeFromQString(art_id_b64)); // URI - Blugh @@ -979,7 +979,7 @@ void SpotifyClient::SendPlaybackError(const QString& error) { } void SpotifyClient::LoadImage(const QString& id_b64) { - QByteArray id = QByteArray::fromBase64(id_b64.toAscii()); + QByteArray id = QByteArray::fromBase64(id_b64.toLatin1()); if (id.length() != kSpotifyImageIDSize) { qLog(Warning) << "Invalid image ID (did not decode to" << kSpotifyImageIDSize << "bytes):" << id_b64; From e816131bf3b52f8f0aea157cd81fa91a20c3646d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 16 Jun 2015 15:36:14 +0200 Subject: [PATCH 026/104] Fix compilation error when we don't have qt4 include directories for lastm/echonest --- src/core/song.cpp | 4 ++-- src/internet/lastfm/lastfmservice.cpp | 4 ++-- src/internet/lastfm/lastfmsettingspage.cpp | 2 +- src/songinfo/echonestbiographies.cpp | 2 +- src/songinfo/echonestimages.cpp | 2 +- src/songinfo/echonestsimilarartists.cpp | 2 +- src/songinfo/echonesttags.cpp | 2 +- src/songinfo/songkickconcerts.cpp | 2 +- tests/albumcoverfetcher_test.cpp | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/core/song.cpp b/src/core/song.cpp index c990fb3ae..d7465ba00 100644 --- a/src/core/song.cpp +++ b/src/core/song.cpp @@ -45,9 +45,9 @@ #ifdef HAVE_LIBLASTFM #include "internet/lastfm/fixlastfm.h" #ifdef HAVE_LIBLASTFM1 -#include +#include #else -#include +#include #endif #endif diff --git a/src/internet/lastfm/lastfmservice.cpp b/src/internet/lastfm/lastfmservice.cpp index ba7430b47..dbdd8ac6c 100644 --- a/src/internet/lastfm/lastfmservice.cpp +++ b/src/internet/lastfm/lastfmservice.cpp @@ -36,9 +36,9 @@ #include #ifdef HAVE_LIBLASTFM1 -#include +#include #else -#include +#include #endif #include "lastfmcompat.h" diff --git a/src/internet/lastfm/lastfmsettingspage.cpp b/src/internet/lastfm/lastfmsettingspage.cpp index 22313aece..ac883aa5b 100644 --- a/src/internet/lastfm/lastfmsettingspage.cpp +++ b/src/internet/lastfm/lastfmsettingspage.cpp @@ -22,7 +22,7 @@ #include "lastfmsettingspage.h" #include "ui_lastfmsettingspage.h" -#include +#include #include #include diff --git a/src/songinfo/echonestbiographies.cpp b/src/songinfo/echonestbiographies.cpp index 1f060529a..ff0db2c88 100644 --- a/src/songinfo/echonestbiographies.cpp +++ b/src/songinfo/echonestbiographies.cpp @@ -19,7 +19,7 @@ #include -#include +#include #include "songinfotextview.h" #include "core/logging.h" diff --git a/src/songinfo/echonestimages.cpp b/src/songinfo/echonestimages.cpp index 08256e3e5..630074ba0 100644 --- a/src/songinfo/echonestimages.cpp +++ b/src/songinfo/echonestimages.cpp @@ -19,7 +19,7 @@ #include -#include +#include #include "core/logging.h" diff --git a/src/songinfo/echonestsimilarartists.cpp b/src/songinfo/echonestsimilarartists.cpp index b481d4c32..210e6cc33 100644 --- a/src/songinfo/echonestsimilarartists.cpp +++ b/src/songinfo/echonestsimilarartists.cpp @@ -20,7 +20,7 @@ #include "core/logging.h" #include "ui/iconloader.h" -#include +#include Q_DECLARE_METATYPE(QVector); diff --git a/src/songinfo/echonesttags.cpp b/src/songinfo/echonesttags.cpp index 7911cecf4..4a8f2c111 100644 --- a/src/songinfo/echonesttags.cpp +++ b/src/songinfo/echonesttags.cpp @@ -19,7 +19,7 @@ #include -#include +#include #include "tagwidget.h" #include "core/logging.h" diff --git a/src/songinfo/songkickconcerts.cpp b/src/songinfo/songkickconcerts.cpp index 0f21633cf..ce1337226 100644 --- a/src/songinfo/songkickconcerts.cpp +++ b/src/songinfo/songkickconcerts.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include "core/closure.h" #include "core/logging.h" diff --git a/tests/albumcoverfetcher_test.cpp b/tests/albumcoverfetcher_test.cpp index a1a052c05..c96011fe8 100644 --- a/tests/albumcoverfetcher_test.cpp +++ b/tests/albumcoverfetcher_test.cpp @@ -18,7 +18,7 @@ #include "core/albumcoverfetcher.h" #include "core/networkaccessmanager.h" -#include +#include #include #include From 149e870ab4c4cce7ea0c7ed7c2fd96811fdc1e0a Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 16 Jun 2015 19:58:36 +0200 Subject: [PATCH 027/104] Fix log messages (lines and classname) --- ext/libclementine-common/core/logging.cpp | 16 +++++++-------- ext/libclementine-common/core/logging.h | 24 +++++++++++------------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/ext/libclementine-common/core/logging.cpp b/ext/libclementine-common/core/logging.cpp index 1e3c6d27e..86dd727fd 100644 --- a/ext/libclementine-common/core/logging.cpp +++ b/ext/libclementine-common/core/logging.cpp @@ -267,21 +267,21 @@ void DumpStackTrace() { #endif } -QDebug CreateLoggerFatal() { return qCreateLogger(Fatal); } -QDebug CreateLoggerError() { return qCreateLogger(Error); } +QDebug CreateLoggerFatal(int line, const char *class_name) { return qCreateLogger(line, class_name, Fatal); } +QDebug CreateLoggerError(int line, const char *class_name) { return qCreateLogger(line, class_name, Error); } #ifdef QT_NO_WARNING_OUTPUT -QNoDebug CreateLoggerWarning() { return QNoDebug(); } +QNoDebug CreateLoggerWarning(int, const char*) { return QNoDebug(); } #else -QDebug CreateLoggerWarning() { return qCreateLogger(Warning); } +QDebug CreateLoggerWarning(int line, const char *class_name) { return qCreateLogger(line, class_name, Warning); } #endif // QT_NO_WARNING_OUTPUT #ifdef QT_NO_DEBUG_OUTPUT -QNoDebug CreateLoggerInfo() { return QNoDebug(); } -QNoDebug CreateLoggerDebug() { return QNoDebug(); } +QNoDebug CreateLoggerInfo(int, const char*) { return QNoDebug(); } +QNoDebug CreateLoggerDebug(int, const char*) { return QNoDebug(); } #else -QDebug CreateLoggerInfo() { return qCreateLogger(Info); } -QDebug CreateLoggerDebug() { return qCreateLogger(Debug); } +QDebug CreateLoggerInfo(int line, const char *class_name) { return qCreateLogger(line, class_name, Info); } +QDebug CreateLoggerDebug(int line, const char *class_name) { return qCreateLogger(line, class_name, Debug); } #endif // QT_NO_DEBUG_OUTPUT } // namespace logging diff --git a/ext/libclementine-common/core/logging.h b/ext/libclementine-common/core/logging.h index b04bf49d3..5320f9c55 100644 --- a/ext/libclementine-common/core/logging.h +++ b/ext/libclementine-common/core/logging.h @@ -29,12 +29,12 @@ #else #define qLog(level) \ - logging::CreateLogger##level() + logging::CreateLogger##level(__LINE__, __PRETTY_FUNCTION__) -#define qCreateLogger(level) \ +#define qCreateLogger(line, class_name, level) \ logging::CreateLogger(logging::Level_##level, \ - logging::ParsePrettyFunction(__PRETTY_FUNCTION__), \ - __LINE__) + logging::ParsePrettyFunction(class_name), \ + line) #endif // QT_NO_DEBUG_STREAM @@ -61,21 +61,21 @@ void DumpStackTrace(); QString ParsePrettyFunction(const char* pretty_function); QDebug CreateLogger(Level level, const QString& class_name, int line); -QDebug CreateLoggerFatal(); -QDebug CreateLoggerError(); +QDebug CreateLoggerFatal(int line, const char* class_name); +QDebug CreateLoggerError(int line, const char* class_name); #ifdef QT_NO_WARNING_OUTPUT -QNoDebug CreateLoggerWarning(); +QNoDebug CreateLoggerWarning(int, const char*); #else -QDebug CreateLoggerWarning(); +QDebug CreateLoggerWarning(int line, const char* class_name); #endif // QT_NO_WARNING_OUTPUT #ifdef QT_NO_DEBUG_OUTPUT -QNoDebug CreateLoggerInfo(); -QNoDebug CreateLoggerDebug(); +QNoDebug CreateLoggerInfo(int, const char*); +QNoDebug CreateLoggerDebug(int, const char*); #else -QDebug CreateLoggerInfo(); -QDebug CreateLoggerDebug(); +QDebug CreateLoggerInfo(int line, const char* class_name); +QDebug CreateLoggerDebug(int line, const char* class_name); #endif // QT_NO_DEBUG_OUTPUT From e821314e342e83fbef09f2b5292dc30756b24c51 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 16 Jun 2015 20:07:11 +0200 Subject: [PATCH 028/104] Fix deprecated pixmap grab method --- src/smartplaylists/searchtermwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/smartplaylists/searchtermwidget.cpp b/src/smartplaylists/searchtermwidget.cpp index 9cf989475..8a1add545 100644 --- a/src/smartplaylists/searchtermwidget.cpp +++ b/src/smartplaylists/searchtermwidget.cpp @@ -363,7 +363,7 @@ void SearchTermWidget::Overlay::Grab() { hide(); // Take a "screenshot" of the window - QPixmap pixmap = QPixmap::grabWidget(parent_); + QPixmap pixmap = parent_->grab(); QImage image = pixmap.toImage(); // Blur it From 53af2bd75cce111b316530bca9a83ca7342f1a50 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 8 Jul 2015 19:00:14 +0200 Subject: [PATCH 029/104] Fix echonest qt5 compilation issues with different GNU/Linux distributions --- CMakeLists.txt | 2 +- src/main.cpp | 2 +- src/songinfo/echonestbiographies.cpp | 2 +- src/songinfo/echonestimages.cpp | 2 +- src/songinfo/echonestsimilarartists.cpp | 2 +- src/songinfo/echonesttags.cpp | 2 +- src/songinfo/songkickconcerts.cpp | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 836902c1e..1031495b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -371,7 +371,7 @@ else (USE_SYSTEM_QXT) endif (NOT APPLE) endif (USE_SYSTEM_QXT) -find_path(ECHONEST5_INCLUDE_DIRS echonest5/echonest_export.h) +find_path(ECHONEST5_INCLUDE_DIRS Artist.h PATH_SUFFIXES echonest5 echonest) find_library(ECHONEST5_LIBRARIES echonest5) # Use system gmock if it's available diff --git a/src/main.cpp b/src/main.cpp index 8a8879e18..7a1eb813e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -76,7 +76,7 @@ #include #include -#include +#include #ifdef Q_OS_DARWIN #include diff --git a/src/songinfo/echonestbiographies.cpp b/src/songinfo/echonestbiographies.cpp index ff0db2c88..b1fc20bf0 100644 --- a/src/songinfo/echonestbiographies.cpp +++ b/src/songinfo/echonestbiographies.cpp @@ -19,7 +19,7 @@ #include -#include +#include #include "songinfotextview.h" #include "core/logging.h" diff --git a/src/songinfo/echonestimages.cpp b/src/songinfo/echonestimages.cpp index 630074ba0..3b34575d6 100644 --- a/src/songinfo/echonestimages.cpp +++ b/src/songinfo/echonestimages.cpp @@ -19,7 +19,7 @@ #include -#include +#include #include "core/logging.h" diff --git a/src/songinfo/echonestsimilarartists.cpp b/src/songinfo/echonestsimilarartists.cpp index 210e6cc33..b6f391ee1 100644 --- a/src/songinfo/echonestsimilarartists.cpp +++ b/src/songinfo/echonestsimilarartists.cpp @@ -20,7 +20,7 @@ #include "core/logging.h" #include "ui/iconloader.h" -#include +#include Q_DECLARE_METATYPE(QVector); diff --git a/src/songinfo/echonesttags.cpp b/src/songinfo/echonesttags.cpp index 4a8f2c111..55e27a326 100644 --- a/src/songinfo/echonesttags.cpp +++ b/src/songinfo/echonesttags.cpp @@ -19,7 +19,7 @@ #include -#include +#include #include "tagwidget.h" #include "core/logging.h" diff --git a/src/songinfo/songkickconcerts.cpp b/src/songinfo/songkickconcerts.cpp index ce1337226..eb88d3edb 100644 --- a/src/songinfo/songkickconcerts.cpp +++ b/src/songinfo/songkickconcerts.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include "core/closure.h" #include "core/logging.h" From 947f7a132efb8522ea1a38ac798111406bbe171d Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 14 Jul 2015 10:32:08 +0200 Subject: [PATCH 030/104] Fix media global shortcuts which don't work --- 3rdparty/qxt/qxtglobalshortcut_x11.cpp | 28 ++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/3rdparty/qxt/qxtglobalshortcut_x11.cpp b/3rdparty/qxt/qxtglobalshortcut_x11.cpp index 7ecbdf24a..9ddb1e088 100644 --- a/3rdparty/qxt/qxtglobalshortcut_x11.cpp +++ b/3rdparty/qxt/qxtglobalshortcut_x11.cpp @@ -38,6 +38,7 @@ #endif #include #include +#include "keymapper_x11.h" namespace { @@ -214,15 +215,30 @@ quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifier quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) { - QxtX11Data x11; - if (!x11.isValid()) - return 0; + // (davidsansome) Try the table from QKeyMapper first - this seems to be + // the only way to get Keysyms for the media keys. + unsigned int keysym = 0; + int i = 0; + while (KeyTbl[i]) { + if (KeyTbl[i+1] == static_cast(key)) { + keysym = KeyTbl[i]; + break; + } + i += 2; + } - KeySym keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data()); + // If that didn't work then fall back on XStringToKeysym + if (!keysym) { + keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data()); if (keysym == NoSymbol) - keysym = static_cast(key); + keysym = static_cast(key); + } - return XKeysymToKeycode(x11.display(), keysym); + QxtX11Data x11; + if (!x11.isValid()) + return 0; + + return XKeysymToKeycode(x11.display(), keysym); } bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) From 7a866ac46b85396896ab9276069397b60926ce10 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Sun, 26 Jul 2015 09:54:19 +0200 Subject: [PATCH 031/104] Fix compilation with Qt5.5 --- 3rdparty/qtsingleapplication/qtlocalpeer.cpp | 1 + 3rdparty/vreen/vreen/src/api/attachment.cpp | 1 + 3rdparty/vreen/vreen/src/api/newsitem.cpp | 1 + ext/libclementine-common/core/messagehandler.cpp | 1 + 4 files changed, 4 insertions(+) diff --git a/3rdparty/qtsingleapplication/qtlocalpeer.cpp b/3rdparty/qtsingleapplication/qtlocalpeer.cpp index 1c89e3c00..837752b63 100644 --- a/3rdparty/qtsingleapplication/qtlocalpeer.cpp +++ b/3rdparty/qtsingleapplication/qtlocalpeer.cpp @@ -41,6 +41,7 @@ #include "qtlocalpeer.h" #include #include +#include #include #if defined(Q_OS_WIN) diff --git a/3rdparty/vreen/vreen/src/api/attachment.cpp b/3rdparty/vreen/vreen/src/api/attachment.cpp index 06c2e793d..cc69e9b98 100644 --- a/3rdparty/vreen/vreen/src/api/attachment.cpp +++ b/3rdparty/vreen/vreen/src/api/attachment.cpp @@ -25,6 +25,7 @@ #include "attachment.h" #include #include +#include namespace Vreen { diff --git a/3rdparty/vreen/vreen/src/api/newsitem.cpp b/3rdparty/vreen/vreen/src/api/newsitem.cpp index cca110233..561fe71af 100644 --- a/3rdparty/vreen/vreen/src/api/newsitem.cpp +++ b/3rdparty/vreen/vreen/src/api/newsitem.cpp @@ -28,6 +28,7 @@ #include #include #include +#include namespace Vreen { diff --git a/ext/libclementine-common/core/messagehandler.cpp b/ext/libclementine-common/core/messagehandler.cpp index 1ea64929b..065964d5f 100644 --- a/ext/libclementine-common/core/messagehandler.cpp +++ b/ext/libclementine-common/core/messagehandler.cpp @@ -23,6 +23,7 @@ #include #include +#include _MessageHandlerBase::_MessageHandlerBase(QIODevice* device, QObject* parent) : QObject(parent), From f5cd85c6de1deaa4af43fd69d91d1943eded5080 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 5 Oct 2015 12:16:52 +0200 Subject: [PATCH 032/104] Fix the command line options when another instance is running --- src/core/commandlineoptions.cpp | 4 ++-- src/core/commandlineoptions.h | 2 +- src/main.cpp | 8 ++++---- src/ui/mainwindow.cpp | 10 ++-------- src/ui/mainwindow.h | 2 +- 5 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/core/commandlineoptions.cpp b/src/core/commandlineoptions.cpp index 58d4a89cc..b1d891a52 100644 --- a/src/core/commandlineoptions.cpp +++ b/src/core/commandlineoptions.cpp @@ -301,11 +301,11 @@ QByteArray CommandlineOptions::Serialize() const { s << *this; buf.close(); - return buf.data(); + return buf.data().toBase64(); } void CommandlineOptions::Load(const QByteArray& serialized) { - QByteArray copy(serialized); + QByteArray copy = QByteArray::fromBase64(serialized); QBuffer buf(©); buf.open(QIODevice::ReadOnly); diff --git a/src/core/commandlineoptions.h b/src/core/commandlineoptions.h index 7b807dfc3..2ce20b4d2 100644 --- a/src/core/commandlineoptions.h +++ b/src/core/commandlineoptions.h @@ -33,7 +33,7 @@ class CommandlineOptions { friend QDataStream& operator>>(QDataStream& s, CommandlineOptions& a); public: - explicit CommandlineOptions(int argc = 0, char* *argv = nullptr); + explicit CommandlineOptions(int argc = 0, char** argv = nullptr); static const char* kHelpText; static const char* kVersionText; diff --git a/src/main.cpp b/src/main.cpp index b9a0ae010..b8753ea56 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -111,7 +111,6 @@ namespace { void LoadTranslation(const QString& prefix, const QString& path, const QString& language) { - QTranslator* t = new PoTranslator; if (t->load(prefix + "_" + language, path)) QCoreApplication::installTranslator(t); @@ -349,7 +348,8 @@ int main(int argc, char* argv[]) { a.setQuitOnLastWindowClosed(false); // Do this check again because another instance might have started by now - if (a.isRunning() && a.sendMessage(options.Serialize(), 5000)) { + if (a.isRunning() && + a.sendMessage(QString::fromLatin1(options.Serialize()), 5000)) { return 0; } @@ -390,8 +390,8 @@ int main(int argc, char* argv[]) { // Add root CA cert for SoundCloud, whose certificate is missing on OS X. QSslSocket::addDefaultCaCertificates( QSslCertificate::fromPath(":/soundcloud-ca.pem", QSsl::Pem)); - QSslSocket::addDefaultCaCertificates( - QSslCertificate::fromPath(":/Equifax_Secure_Certificate_Authority.pem", QSsl::Pem)); + QSslSocket::addDefaultCaCertificates(QSslCertificate::fromPath( + ":/Equifax_Secure_Certificate_Authority.pem", QSsl::Pem)); // Has the user forced a different language? QString override_language = options.language(); diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 9c1b21d98..d45e5140a 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -2045,15 +2045,9 @@ void MainWindow::PlaylistEditFinished(const QModelIndex& index) { if (index == playlist_menu_index_) SelectionSetValue(); } -void MainWindow::CommandlineOptionsReceived( - const QString& serialized_options) { - if (serialized_options == "wake up!") { - // Old versions of Clementine sent this - just ignore it - return; - } - +void MainWindow::CommandlineOptionsReceived(const QString& string_options) { CommandlineOptions options; - options.Load(serialized_options.toLatin1()); + options.Load(string_options.toLatin1()); if (options.is_empty()) { show(); diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h index af1e303f8..4be836257 100644 --- a/src/ui/mainwindow.h +++ b/src/ui/mainwindow.h @@ -240,7 +240,7 @@ signals: void AddCDTracks(); void AddPodcast(); - void CommandlineOptionsReceived(const QString &serialized_options); + void CommandlineOptionsReceived(const QString& string_options); void CheckForUpdates(); From abc6370b00ba0ead39a9c46582a3a1a28183af76 Mon Sep 17 00:00:00 2001 From: John Maguire Date: Wed, 17 Feb 2016 17:13:31 +0000 Subject: [PATCH 033/104] Don't force native windows on OS X with qt5 --- src/main.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index b8753ea56..83d363c5c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -359,8 +359,6 @@ int main(int argc, char* argv[]) { QCoreApplication::setAttribute(Qt::AA_DontShowIconsInMenus, false); #else QCoreApplication::setAttribute(Qt::AA_DontShowIconsInMenus, true); - // Fixes focus issue with NSSearchField, see QTBUG-11401 - QCoreApplication::setAttribute(Qt::AA_NativeWindows, true); #endif SetGstreamerEnvironment(); From 8cf6fc839c9dfb5707db4aa3b85092b465640ab0 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 29 Feb 2016 18:16:09 +0100 Subject: [PATCH 034/104] Use QWidget::grab instead of deprecated QPixmap::grabWidget --- src/widgets/widgetfadehelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/widgetfadehelper.cpp b/src/widgets/widgetfadehelper.cpp index adb1fcb67..407b7521f 100644 --- a/src/widgets/widgetfadehelper.cpp +++ b/src/widgets/widgetfadehelper.cpp @@ -76,7 +76,7 @@ void WidgetFadeHelper::StartBlur() { void WidgetFadeHelper::CaptureParent() { // Take a "screenshot" of the window - original_pixmap_ = QPixmap::grabWidget(parent_); + original_pixmap_ = parent_->grab(); QImage original_image = original_pixmap_.toImage(); // Blur it From 7c9d177755b22eff407351eee20e4bb25bf7a2e7 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 28 Mar 2016 11:40:37 +0200 Subject: [PATCH 035/104] Use Qt LTS --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 89a59fc5c..3567bf47e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,8 +32,7 @@ if (UNIX AND NOT APPLE) set(LINUX 1) endif (UNIX AND NOT APPLE) -# See https://bugreports.qt.io/browse/QTBUG-43859 -set(QT_MIN_VERSION 5.4.2) +set(QT_MIN_VERSION 5.6.0) find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core OpenGL Sql Network Xml Widgets Concurrent Test) find_package(X11) From cbd2a0843256ddad7258b05b909710c51793f086 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 28 Mar 2016 11:50:52 +0200 Subject: [PATCH 036/104] Register metatype QAbstractSocket::SocketState --- src/core/metatypes.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/metatypes.cpp b/src/core/metatypes.cpp index ee81fa231..fc21b1e7b 100644 --- a/src/core/metatypes.cpp +++ b/src/core/metatypes.cpp @@ -106,6 +106,7 @@ void RegisterMetaTypes() { qRegisterMetaType("SubdirectoryList"); qRegisterMetaType("Subdirectory"); qRegisterMetaType>("QList"); + qRegisterMetaType(); #ifdef HAVE_VK qRegisterMetaType("MusicOwner"); From 0605dd83a598bc83bec6d3470cdf50377fb3b4b7 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 30 Mar 2016 19:29:30 +0200 Subject: [PATCH 037/104] Fix compilation (wrong echonest include) --- src/songinfo/echonestimages.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/songinfo/echonestimages.h b/src/songinfo/echonestimages.h index 6e67e8726..94a8c1cb1 100644 --- a/src/songinfo/echonestimages.h +++ b/src/songinfo/echonestimages.h @@ -22,7 +22,7 @@ #include -#include +#include #include "songinfo/songinfoprovider.h" From 182e5c30348ee988e4006d75a42b938460d05734 Mon Sep 17 00:00:00 2001 From: "David G. F" Date: Tue, 19 Apr 2016 21:50:21 +0100 Subject: [PATCH 038/104] Fixing a couple of issues with subsonic in the qt5 port (#5346) --- src/internet/subsonic/subsonicservice.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internet/subsonic/subsonicservice.cpp b/src/internet/subsonic/subsonicservice.cpp index 99448ebe9..e97a500db 100644 --- a/src/internet/subsonic/subsonicservice.cpp +++ b/src/internet/subsonic/subsonicservice.cpp @@ -571,7 +571,7 @@ void SubsonicLibraryScanner::OnGetAlbumFinished(QNetworkReply* reply) { void SubsonicLibraryScanner::GetAlbumList(int offset) { QUrl url = service_->BuildRequestUrl("getAlbumList2"); - QUrlQuery url_query; + QUrlQuery url_query(url.query()); url_query.addQueryItem("type", "alphabeticalByName"); url_query.addQueryItem("size", QString::number(kAlbumChunkSize)); url_query.addQueryItem("offset", QString::number(offset)); @@ -583,7 +583,7 @@ void SubsonicLibraryScanner::GetAlbumList(int offset) { void SubsonicLibraryScanner::GetAlbum(const QString& id) { QUrl url = service_->BuildRequestUrl("getAlbum"); - QUrlQuery url_query; + QUrlQuery url_query(url.query()); url_query.addQueryItem("id", id); if (service_->IsAmpache()) { url_query.addQueryItem("ampache", "1"); From f1825629dbf827405ea56ecf9d2528f5a76aeeb1 Mon Sep 17 00:00:00 2001 From: "David G. F" Date: Tue, 19 Apr 2016 23:22:23 +0100 Subject: [PATCH 039/104] Qt5 * Fixing a couple of issues with subsonic in the qt5 port * Forgot to add this fixes as well, otherwise won't play music! --- src/internet/subsonic/subsonicdynamicplaylist.cpp | 4 ++-- src/internet/subsonic/subsonicurlhandler.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/internet/subsonic/subsonicdynamicplaylist.cpp b/src/internet/subsonic/subsonicdynamicplaylist.cpp index f1a8cd445..d53368a1b 100644 --- a/src/internet/subsonic/subsonicdynamicplaylist.cpp +++ b/src/internet/subsonic/subsonicdynamicplaylist.cpp @@ -99,7 +99,7 @@ PlaylistItemList SubsonicDynamicPlaylist::GenerateMore(int count) { if (count > kMaxCount) count = kMaxCount; - QUrlQuery url_query; + QUrlQuery url_query(url.query()); url_query.addQueryItem("type", GetTypeString()); url_query.addQueryItem("size", QString::number(count)); url_query.addQueryItem("offset", QString::number(offset_)); @@ -160,7 +160,7 @@ void SubsonicDynamicPlaylist::GetAlbum(SubsonicService* service, QNetworkAccessManager& network, const bool usesslv3) { QUrl url = service->BuildRequestUrl("getAlbum"); - QUrlQuery url_query; + QUrlQuery url_query(url.query()); url_query.addQueryItem("id", id); if (service->IsAmpache()) { url_query.addQueryItem("ampache", "1"); diff --git a/src/internet/subsonic/subsonicurlhandler.cpp b/src/internet/subsonic/subsonicurlhandler.cpp index 9ff90f33c..91177cf90 100644 --- a/src/internet/subsonic/subsonicurlhandler.cpp +++ b/src/internet/subsonic/subsonicurlhandler.cpp @@ -31,7 +31,7 @@ UrlHandler::LoadResult SubsonicUrlHandler::StartLoading(const QUrl& url) { return LoadResult(url); QUrl newurl = service_->BuildRequestUrl("stream"); - QUrlQuery url_query; + QUrlQuery url_query(newurl.query()); url_query.addQueryItem("id", url.host()); newurl.setQuery(url_query); return LoadResult(url, LoadResult::TrackAvailable, newurl); From f2fce34ad8bd1f682d000c1ec74dad7187fc8fef Mon Sep 17 00:00:00 2001 From: Bigard Florian Date: Mon, 9 May 2016 11:55:16 +0200 Subject: [PATCH 040/104] Fix spotify blob config path (#5370) --- ext/clementine-spotifyblob/main.cpp | 4 ++-- src/main.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/clementine-spotifyblob/main.cpp b/ext/clementine-spotifyblob/main.cpp index cce0d106c..76915b3a2 100644 --- a/ext/clementine-spotifyblob/main.cpp +++ b/ext/clementine-spotifyblob/main.cpp @@ -28,8 +28,8 @@ int main(int argc, char** argv) { QCoreApplication a(argc, argv); - QCoreApplication::setApplicationName("Clementine"); - QCoreApplication::setOrganizationName("Clementine"); + QCoreApplication::setApplicationName("Clementine-qt5"); + QCoreApplication::setOrganizationName("Clementine-qt5"); QCoreApplication::setOrganizationDomain("clementine-player.org"); logging::Init(); diff --git a/src/main.cpp b/src/main.cpp index 9fb666a31..2ecc79872 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -257,7 +257,7 @@ int main(int argc, char* argv[]) { QCoreApplication::setApplicationName("Clementine-qt5"); QCoreApplication::setApplicationVersion(CLEMENTINE_VERSION_DISPLAY); QCoreApplication::setOrganizationName("Clementine-qt5"); - QCoreApplication::setOrganizationDomain("clementine-player-qt5.org"); + QCoreApplication::setOrganizationDomain("clementine-player.org"); // This makes us show up nicely in gnome-volume-control #if !GLIB_CHECK_VERSION(2, 36, 0) From 28274eacec522e8b72c5267dec036c6657d29fa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Przyby=C5=82?= Date: Sun, 29 May 2016 14:56:18 +0200 Subject: [PATCH 041/104] kf5: Fix DESTINATION path for protocol files protocol files are stored in `/usr/share/kservices5` PATH in Plasma 5 --- dist/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/CMakeLists.txt b/dist/CMakeLists.txt index 67af06bf2..f5adf65d4 100644 --- a/dist/CMakeLists.txt +++ b/dist/CMakeLists.txt @@ -62,7 +62,7 @@ if (NOT APPLE) clementine-itpc.protocol clementine-feed.protocol clementine-zune.protocol - DESTINATION share/kde4/services + DESTINATION share/kservices5 ) install(FILES clementine.appdata.xml From 84dcfeba054e11b74448417d31092df2d58e833c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Przyby=C5=82?= Date: Sun, 29 May 2016 15:04:25 +0200 Subject: [PATCH 042/104] clementine.spec.in: Fix path for protocol files --- dist/clementine.spec.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dist/clementine.spec.in b/dist/clementine.spec.in index a26aadce4..6e9f5434e 100644 --- a/dist/clementine.spec.in +++ b/dist/clementine.spec.in @@ -83,10 +83,10 @@ make clean %{_datadir}/appdata/clementine.appdata.xml %{_datadir}/applications/clementine.desktop %{_datadir}/clementine/projectm-presets -%{_datadir}/kde4/services/clementine-itms.protocol -%{_datadir}/kde4/services/clementine-itpc.protocol -%{_datadir}/kde4/services/clementine-feed.protocol -%{_datadir}/kde4/services/clementine-zune.protocol +%{_datadir}/kservices5/clementine-itms.protocol +%{_datadir}/kservices5/clementine-itpc.protocol +%{_datadir}/kservices5/clementine-feed.protocol +%{_datadir}/kservices5/clementine-zune.protocol %{_datadir}/icons/hicolor/64x64/apps/clementine.png %{_datadir}/icons/hicolor/128x128/apps/clementine.png %{_datadir}/icons/hicolor/scalable/apps/clementine.svg From f08cf3ed8ea305fb5f2ef5dc00e604b8d83e636f Mon Sep 17 00:00:00 2001 From: Pavel Vatagin Date: Mon, 9 Jan 2017 18:17:38 +0400 Subject: [PATCH 043/104] fix build (Qt5) qtwin (#5585) --- 3rdparty/qtwin/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/3rdparty/qtwin/CMakeLists.txt b/3rdparty/qtwin/CMakeLists.txt index 6859c43a4..9122be354 100644 --- a/3rdparty/qtwin/CMakeLists.txt +++ b/3rdparty/qtwin/CMakeLists.txt @@ -7,3 +7,7 @@ set(QTWIN-SOURCES ADD_LIBRARY(qtwin STATIC ${QTWIN-SOURCES} ) + +target_link_libraries(qtwin + Qt5::Widgets +) From 168ec9d7ab7803efbbeee3397610f2190a98f9c8 Mon Sep 17 00:00:00 2001 From: Pavel Vatagin Date: Mon, 9 Jan 2017 18:17:57 +0400 Subject: [PATCH 044/104] fix linking qsqlite (#5582) --- 3rdparty/qsqlite/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/3rdparty/qsqlite/CMakeLists.txt b/3rdparty/qsqlite/CMakeLists.txt index e6f28d673..19e6bf7bf 100644 --- a/3rdparty/qsqlite/CMakeLists.txt +++ b/3rdparty/qsqlite/CMakeLists.txt @@ -46,4 +46,5 @@ set_property(TARGET qsqlite PROPERTY QT_STATICPLUGIN 1) target_link_libraries(qsqlite Qt5::Core Qt5::Sql + ${SQLITE_LIBRARIES} ) From cb47beb4df5c37b7bd2330c4ceb5ce088368e958 Mon Sep 17 00:00:00 2001 From: Pavel Vatagin Date: Mon, 9 Jan 2017 18:19:18 +0400 Subject: [PATCH 045/104] fix Windows build qsqlite (#5583) --- 3rdparty/qsqlite/clementinesqlcachedresult.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/3rdparty/qsqlite/clementinesqlcachedresult.h b/3rdparty/qsqlite/clementinesqlcachedresult.h index 7447f2605..c170270ae 100644 --- a/3rdparty/qsqlite/clementinesqlcachedresult.h +++ b/3rdparty/qsqlite/clementinesqlcachedresult.h @@ -53,7 +53,7 @@ // We mean it. // -#include "QtSql/qsqlresult.h" +#include QT_BEGIN_NAMESPACE @@ -62,7 +62,7 @@ template class QVector; class ClementineSqlCachedResultPrivate; -class Q_SQL_EXPORT ClementineSqlCachedResult: public QSqlResult +class ClementineSqlCachedResult: public QSqlResult { public: virtual ~ClementineSqlCachedResult(); From 446b382c741f7b6b882c70e94a0e9e03e594f135 Mon Sep 17 00:00:00 2001 From: Pavel Vatagin Date: Mon, 9 Jan 2017 18:19:54 +0400 Subject: [PATCH 046/104] fix configure Windows build (Qt5) (#5586) --- 3rdparty/qxt/CMakeLists.txt | 6 +++++- CMakeLists.txt | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/3rdparty/qxt/CMakeLists.txt b/3rdparty/qxt/CMakeLists.txt index 6514a6472..75fa686b2 100644 --- a/3rdparty/qxt/CMakeLists.txt +++ b/3rdparty/qxt/CMakeLists.txt @@ -28,4 +28,8 @@ ADD_LIBRARY(qxt STATIC ${QXT-SOURCES-MOC} ) -QT5_USE_MODULES(qxt Core Widgets X11Extras) +if(WIN32) + QT5_USE_MODULES(qxt Core Widgets) +else(WIN32) + QT5_USE_MODULES(qxt Core Widgets X11Extras) +endif(WIN32) diff --git a/CMakeLists.txt b/CMakeLists.txt index 50e3bee57..7309e5b85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ pkg_check_modules(TAGLIB REQUIRED taglib>=1.6) if (WIN32) find_package(ZLIB REQUIRED) - find_library(QTSPARKLE_LIBRARIES qtsparkle) + find_library(QTSPARKLE_LIBRARIES qtsparkle-qt5) endif (WIN32) find_library(LASTFM5_LIBRARIES lastfm5) @@ -299,7 +299,11 @@ if (HAVE_VK) endif(HAVE_VK) # We can include the Qt definitions now -set(QT_LIBRARIES Qt5::Core Qt5::OpenGL Qt5::Sql Qt5::Network Qt5::Xml Qt5::Widgets Qt5::Concurrent Qt5::X11Extras Qt5::DBus) +if(WIN32) + set(QT_LIBRARIES Qt5::Core Qt5::OpenGL Qt5::Sql Qt5::Network Qt5::Xml Qt5::Widgets Qt5::Concurrent) +else(WIN32) + set(QT_LIBRARIES Qt5::Core Qt5::OpenGL Qt5::Sql Qt5::Network Qt5::Xml Qt5::Widgets Qt5::Concurrent Qt5::X11Extras Qt5::DBus) +endif(WIN32) # Remove GLU and GL from the link line - they're not really required # and don't exist on my mingw toolchain From b52c99755db8aecbcaf627ecc97697bdf9c76362 Mon Sep 17 00:00:00 2001 From: Pavel Vatagin Date: Tue, 10 Jan 2017 00:11:27 +0400 Subject: [PATCH 047/104] Fix windows7thumbbar.cpp and osdpretty.cpp (#5588) * fix problem with toWinHICON() in Qt5 * fix Windows (Qt5) build (conversion to HWND) --- src/ui/windows7thumbbar.cpp | 9 ++++++--- src/widgets/osdpretty.cpp | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/ui/windows7thumbbar.cpp b/src/ui/windows7thumbbar.cpp index 4eb754e40..b8fbdecb6 100644 --- a/src/ui/windows7thumbbar.cpp +++ b/src/ui/windows7thumbbar.cpp @@ -53,10 +53,13 @@ void Windows7ThumbBar::SetActions(const QList& actions) { } #ifdef Q_OS_WIN32 + +extern HICON qt_pixmapToWinHICON(const QPixmap &p); + static void SetupButton(const QAction* action, THUMBBUTTON* button) { if (action) { button->hIcon = - action->icon().pixmap(Windows7ThumbBar::kIconSize).toWinHICON(); + qt_pixmapToWinHICON(action->icon().pixmap(Windows7ThumbBar::kIconSize)); button->dwFlags = action->isEnabled() ? THBF_ENABLED : THBF_DISABLED; // This is unsafe - doesn't obey 260-char restriction action->text().toWCharArray(button->szTip); @@ -130,7 +133,7 @@ void Windows7ThumbBar::HandleWinEvent(MSG* msg) { } qLog(Debug) << "Adding buttons"; - hr = taskbar_list->ThumbBarAddButtons(widget_->winId(), actions_.count(), + hr = taskbar_list->ThumbBarAddButtons((HWND)widget_->winId(), actions_.count(), buttons); if (hr != S_OK) qLog(Debug) << "Failed to add buttons" << hex << DWORD(hr); for (int i = 0; i < actions_.count(); i++) { @@ -164,7 +167,7 @@ void Windows7ThumbBar::ActionChanged() { if (buttons->hIcon > 0) DestroyIcon(buttons->hIcon); } - taskbar_list->ThumbBarUpdateButtons(widget_->winId(), actions_.count(), + taskbar_list->ThumbBarUpdateButtons((HWND)widget_->winId(), actions_.count(), buttons); #endif // Q_OS_WIN32 } diff --git a/src/widgets/osdpretty.cpp b/src/widgets/osdpretty.cpp index 0440b6a3f..6c2241cac 100644 --- a/src/widgets/osdpretty.cpp +++ b/src/widgets/osdpretty.cpp @@ -76,9 +76,9 @@ OSDPretty::OSDPretty(Mode mode, QWidget* parent) #ifdef Q_OS_WIN32 // Don't show the window in the taskbar. Qt::ToolTip does this too, but it // adds an extra ugly shadow. - int ex_style = GetWindowLong(winId(), GWL_EXSTYLE); + int ex_style = GetWindowLong((HWND)winId(), GWL_EXSTYLE); ex_style |= WS_EX_NOACTIVATE; - SetWindowLong(winId(), GWL_EXSTYLE, ex_style); + SetWindowLong((HWND)winId(), GWL_EXSTYLE, ex_style); #endif // Mode settings From 09c4b05ec59c127b5a9bd35ec587dd80fe6500e7 Mon Sep 17 00:00:00 2001 From: Pavel Vatagin Date: Tue, 10 Jan 2017 03:25:13 +0400 Subject: [PATCH 048/104] fix Windows build libmygpo-qt5 (#5581) --- 3rdparty/libmygpo-qt5/src/mygpo_export.h | 4 +++- CMakeLists.txt | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/3rdparty/libmygpo-qt5/src/mygpo_export.h b/3rdparty/libmygpo-qt5/src/mygpo_export.h index d2a8c3a58..28980e2c6 100644 --- a/3rdparty/libmygpo-qt5/src/mygpo_export.h +++ b/3rdparty/libmygpo-qt5/src/mygpo_export.h @@ -25,7 +25,7 @@ #include -#ifndef MYGPO_EXPORT +#ifndef MYGPO_STATIC # if defined(MYGPO_MAKEDLL) /* We are building this library */ # define MYGPO_EXPORT Q_DECL_EXPORT @@ -33,6 +33,8 @@ /* We are using this library */ # define MYGPO_EXPORT Q_DECL_IMPORT # endif +#else +# define MYGPO_EXPORT #endif #endif // MYGPO_EXPORT_H diff --git a/CMakeLists.txt b/CMakeLists.txt index 7309e5b85..59617dfa4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -406,6 +406,7 @@ if(LIBMYGPO_QT5_FOUND) set(MYGPOQT5_LIBRARIES ${LIBMYGPO_QT5_LIBRARIES}) set(MYGPOQT5_INCLUDE_DIRS ${LIBMYGPO_QT5_INCLUDE_DIRS}) else() + add_definitions(-DMYGPO_STATIC) add_subdirectory(3rdparty/libmygpo-qt5) set(MYGPOQT5_LIBRARIES mygpo-qt5) set(MYGPOQT5_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/libmygpo-qt5/src) From 08a80a5750147c6f1e1818b2ef40eed1b7a4d729 Mon Sep 17 00:00:00 2001 From: droserasprout Date: Wed, 18 Oct 2017 03:32:25 +0400 Subject: [PATCH 049/104] Fix oversized currenttrack icon in playlistview (#5885) --- src/playlist/playlistview.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/playlist/playlistview.cpp b/src/playlist/playlistview.cpp index 3eb685c8b..32ac0608d 100644 --- a/src/playlist/playlistview.cpp +++ b/src/playlist/playlistview.cpp @@ -141,11 +141,11 @@ PlaylistView::PlaylistView(QWidget* parent) QIcon currenttrack_play = IconLoader::Load("currenttrack_play", IconLoader::Other); currenttrack_play_ = - currenttrack_play.pixmap(currenttrack_play.availableSizes().last()); + currenttrack_play.pixmap(currenttrack_play.actualSize(QSize(32, 32))); QIcon currenttrack_pause = IconLoader::Load("currenttrack_pause", IconLoader::Other); currenttrack_pause_ = - currenttrack_pause.pixmap(currenttrack_pause.availableSizes().last()); + currenttrack_pause.pixmap(currenttrack_pause.actualSize(QSize(32, 32))); connect(header_, SIGNAL(sectionResized(int, int, int)), SLOT(SaveGeometry())); connect(header_, SIGNAL(sectionMoved(int, int, int)), SLOT(SaveGeometry())); From 0a59257dc334b8df60a4d7d90b04f1766747efcf Mon Sep 17 00:00:00 2001 From: droserasprout Date: Wed, 18 Oct 2017 04:53:45 +0400 Subject: [PATCH 050/104] Prevent thumbnailing nocover icon for MPRIS (#5886) --- src/covers/currentartloader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/covers/currentartloader.cpp b/src/covers/currentartloader.cpp index 2cbc7f197..ab43fad46 100644 --- a/src/covers/currentartloader.cpp +++ b/src/covers/currentartloader.cpp @@ -61,7 +61,7 @@ void CurrentArtLoader::TempArtLoaded(quint64 id, const QImage& image) { QString thumbnail_uri; QImage thumbnail; - if (!image.isNull()) { + if (image != options_.default_output_image_) { temp_art_.reset(new QTemporaryFile(temp_file_pattern_)); temp_art_->setAutoRemove(true); temp_art_->open(); From b8381321c20389d0075af9958e0651270107478e Mon Sep 17 00:00:00 2001 From: Andreas Sturmlechner Date: Tue, 21 Nov 2017 10:59:48 +0100 Subject: [PATCH 051/104] Properly find Qt5LinguistTools (#5913) --- CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4022c383b..5bdb2a00e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,9 +45,8 @@ if(NOT APPLE) find_package(Qt5 COMPONENTS WebKitWidgets) endif(NOT APPLE) -# Find Qt's lconvert binary. Try qt's binary dir first, fall back to looking in PATH -find_program(QT_LCONVERT_EXECUTABLE NAMES lconvert lconvert-qt5 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH) -find_program(QT_LCONVERT_EXECUTABLE NAMES lconvert lconvert-qt5) +find_package(Qt5LinguistTools CONFIG REQUIRED) +set(QT_LCONVERT_EXECUTABLE Qt5::lconvert) if(APPLE) if(NOT QT_MAC_USE_COCOA) From 902c22ef1b07cfc80b5b808dce6211729bc9d47a Mon Sep 17 00:00:00 2001 From: Benoit Brummer Date: Fri, 15 Dec 2017 03:10:02 +0100 Subject: [PATCH 052/104] fixed issue #5868: IPs were not recognized as private when Qt translates ipv4 to ipv6 (#5896) --- src/networkremote/networkremote.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/networkremote/networkremote.cpp b/src/networkremote/networkremote.cpp index 0ec86e454..91b324833 100644 --- a/src/networkremote/networkremote.cpp +++ b/src/networkremote/networkremote.cpp @@ -197,6 +197,10 @@ bool NetworkRemote::IpIsPrivate(const QHostAddress& address) { address.isInSubnet(QHostAddress::parseSubnet("192.168.0.0/16")) || address.isInSubnet(QHostAddress::parseSubnet("172.16.0.0/12")) || address.isInSubnet(QHostAddress::parseSubnet("10.0.0.0/8")) || + // Private v4 range translated to v6 + address.isInSubnet(QHostAddress::parseSubnet("::ffff:192.168.0.0/112")) || + address.isInSubnet(QHostAddress::parseSubnet("::ffff:172.16.0.0/108")) || + address.isInSubnet(QHostAddress::parseSubnet("::ffff:10.0.0.0/104")) || // Private v6 range address.isInSubnet(QHostAddress::parseSubnet("fc00::/7")); } From abf390729a42890cc62e6700f50cb63a2ac8211d Mon Sep 17 00:00:00 2001 From: Andreas Sturmlechner Date: Sun, 7 Jan 2018 15:11:25 +0100 Subject: [PATCH 053/104] Drop obsolete Qt5WebKit dep from CMakeLists.txt (#5954) Fixes https://github.com/clementine-player/Clementine/issues/5945 --- CMakeLists.txt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5bdb2a00e..820b13851 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,11 +40,6 @@ if(X11_FOUND) find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS X11Extras) endif() - -if(NOT APPLE) - find_package(Qt5 COMPONENTS WebKitWidgets) -endif(NOT APPLE) - find_package(Qt5LinguistTools CONFIG REQUIRED) set(QT_LCONVERT_EXECUTABLE Qt5::lconvert) @@ -148,11 +143,6 @@ add_definitions(${QT_DEFINITIONS}) link_directories(${TAGLIB_LIBRARY_DIRS}) link_directories(${GSTREAMER_LIBRARY_DIRS}) -# Don't try to use webkit if their include directories couldn't be found. -if (NOT QT_QTWEBKIT_INCLUDE_DIR) - set (QT_USE_QTWEBKIT 0) -endif (NOT QT_QTWEBKIT_INCLUDE_DIR) - include_directories(${Boost_INCLUDE_DIRS}) include_directories(${TAGLIB_INCLUDE_DIRS}) include_directories(${GSTREAMER_INCLUDE_DIRS}) From a1a892b35eb2498b16c4d658e553602720606f75 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 19 Feb 2018 08:41:41 +0100 Subject: [PATCH 054/104] Fix "Invalid key" error in lastfm auth --- src/internet/lastfm/lastfmservice.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/internet/lastfm/lastfmservice.cpp b/src/internet/lastfm/lastfmservice.cpp index 25c5efae0..d8cf94b04 100644 --- a/src/internet/lastfm/lastfmservice.cpp +++ b/src/internet/lastfm/lastfmservice.cpp @@ -145,13 +145,14 @@ QByteArray SignApiRequest(QList> params) { void LastFMService::Authenticate() { QUrl url("https://www.last.fm/api/auth/"); - QUrlQuery url_query; - url_query.addQueryItem("api_key", kApiKey); LocalRedirectServer* server = new LocalRedirectServer(this); server->Listen(); + QUrlQuery url_query; + url_query.addQueryItem("api_key", kApiKey); url_query.addQueryItem("cb", server->url().toString()); + url.setQuery(url_query); NewClosure(server, SIGNAL(Finished()), [this, server]() { server->deleteLater(); From d5e5f8246fd7904acc01474968d3b1c286e212d8 Mon Sep 17 00:00:00 2001 From: Andreas Sturmlechner Date: Mon, 19 Feb 2018 17:03:54 +0100 Subject: [PATCH 055/104] Remove "-qt5" suffix from ApplicationName and OrganizationName Renaming the application does not really make sense, but keeping it in qLog info to identify it in debug output. --- ext/clementine-spotifyblob/main.cpp | 4 ++-- src/main.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/clementine-spotifyblob/main.cpp b/ext/clementine-spotifyblob/main.cpp index 76915b3a2..cce0d106c 100644 --- a/ext/clementine-spotifyblob/main.cpp +++ b/ext/clementine-spotifyblob/main.cpp @@ -28,8 +28,8 @@ int main(int argc, char** argv) { QCoreApplication a(argc, argv); - QCoreApplication::setApplicationName("Clementine-qt5"); - QCoreApplication::setOrganizationName("Clementine-qt5"); + QCoreApplication::setApplicationName("Clementine"); + QCoreApplication::setOrganizationName("Clementine"); QCoreApplication::setOrganizationDomain("clementine-player.org"); logging::Init(); diff --git a/src/main.cpp b/src/main.cpp index dbe13a1b6..48acf367c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -252,9 +252,9 @@ int main(int argc, char* argv[]) { } #endif - QCoreApplication::setApplicationName("Clementine-qt5"); + QCoreApplication::setApplicationName("Clementine"); QCoreApplication::setApplicationVersion(CLEMENTINE_VERSION_DISPLAY); - QCoreApplication::setOrganizationName("Clementine-qt5"); + QCoreApplication::setOrganizationName("Clementine"); QCoreApplication::setOrganizationDomain("clementine-player.org"); // This makes us show up nicely in gnome-volume-control From 5966ff51ccbdddcf5fb0d186435ea8a8663c55e1 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Wed, 28 Feb 2018 23:34:19 +0100 Subject: [PATCH 056/104] Fix bug in fetching album covers from Amazon (#6007) * Fix bug where the http request is not sending anything else than the signature. * Fix bug in fetching album covers from Amazon --- src/covers/amazoncoverprovider.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/covers/amazoncoverprovider.cpp b/src/covers/amazoncoverprovider.cpp index 7d991bb0d..fd7ac403b 100644 --- a/src/covers/amazoncoverprovider.cpp +++ b/src/covers/amazoncoverprovider.cpp @@ -23,8 +23,8 @@ #include #include #include -#include #include +#include #include "core/closure.h" #include "core/logging.h" @@ -63,19 +63,19 @@ bool AmazonCoverProvider::StartSearch(const QString& artist, "yyyy-MM-ddThh:mm:ss.zzzZ")) << Arg("Version", "2009-11-01"); - EncodedArgList encoded_args; + QUrlQuery url_query; + QUrl url(kUrl); QStringList query_items; // Encode the arguments for (const Arg& arg : args) { EncodedArg encoded_arg(QUrl::toPercentEncoding(arg.first), QUrl::toPercentEncoding(arg.second)); - encoded_args << encoded_arg; query_items << QString(encoded_arg.first + "=" + encoded_arg.second); + url_query.addQueryItem(encoded_arg.first, encoded_arg.second); } // Sign the request - QUrl url(kUrl); const QByteArray data_to_sign = QString("GET\n%1\n%2\n%3") @@ -85,8 +85,9 @@ bool AmazonCoverProvider::StartSearch(const QString& artist, QByteArray::fromBase64(kSecretAccessKeyB64), data_to_sign)); // Add the signature to the request - QUrlQuery url_query; - url_query.addQueryItem("Signature", QUrl::toPercentEncoding(signature.toBase64())); + + url_query.addQueryItem("Signature", + QUrl::toPercentEncoding(signature.toBase64())); url.setQuery(url_query); QNetworkReply* reply = network_->get(QNetworkRequest(url)); From 335bc89c9788eae1ea9ce6c29e0d607f9ae8d344 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Sat, 10 Mar 2018 00:09:55 +0100 Subject: [PATCH 057/104] Workaround for broken CD playback in Qt5 (#6021) * Workaround for cdda URL in qUrl() * Workaround for cdda URL in qUrl() * Fix code formatting * Fix code style --- src/devices/cddasongloader.cpp | 2 +- src/engines/gstenginepipeline.cpp | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/devices/cddasongloader.cpp b/src/devices/cddasongloader.cpp index 9a584b10b..9923e1636 100644 --- a/src/devices/cddasongloader.cpp +++ b/src/devices/cddasongloader.cpp @@ -35,7 +35,7 @@ CddaSongLoader::~CddaSongLoader() { QUrl CddaSongLoader::GetUrlFromTrack(int track_number) const { if (url_.isEmpty()) { - return QUrl(QString("cdda://%1").arg(track_number)); + return QUrl(QString("cdda://%1a").arg(track_number)); } else { return QUrl(QString("cdda://%1/%2").arg(url_.path()).arg(track_number)); } diff --git a/src/engines/gstenginepipeline.cpp b/src/engines/gstenginepipeline.cpp index bff43aeac..43f988fe5 100644 --- a/src/engines/gstenginepipeline.cpp +++ b/src/engines/gstenginepipeline.cpp @@ -181,9 +181,16 @@ bool GstEnginePipeline::ReplaceDecodeBin(const QUrl& url) { spotify_server, "StartPlayback", Qt::QueuedConnection, Q_ARG(QString, url.toString()), Q_ARG(quint16, port)); } else { + QByteArray uri; + if (url.scheme() == "cdda") { + QString str = url.toString(); + str.remove(str.lastIndexOf(QChar('a')), 1); + uri = str.toUtf8(); + } else { + uri = url.toEncoded(); + } new_bin = engine_->CreateElement("uridecodebin"); - g_object_set(G_OBJECT(new_bin), "uri", url.toEncoded().constData(), - nullptr); + g_object_set(G_OBJECT(new_bin), "uri", uri.constData(), nullptr); CHECKED_GCONNECT(G_OBJECT(new_bin), "drained", &SourceDrainedCallback, this); CHECKED_GCONNECT(G_OBJECT(new_bin), "pad-added", &NewPadCallback, this); From 2d7894915dfc9043da9282d216775ef75041c773 Mon Sep 17 00:00:00 2001 From: Valeriy Malov Date: Tue, 13 Mar 2018 21:19:14 +0300 Subject: [PATCH 058/104] Accept closeEvent() for mainwindow when closing to tray There's no difference between close() and hide() if WA_DeleteOnClose is not set, so if we're going to hide the window we might as well accept the event. Ignoring the event may interrupt shutdowns since it signals that the application doesn't want to close the window, at least this happens on Plasma 5.11 when Clementine is not minimized to tray. --- src/ui/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 641395151..587c0c628 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -1408,7 +1408,7 @@ void MainWindow::closeEvent(QCloseEvent* event) { bool keep_running = s.value("keeprunning", tray_icon_->IsVisible()).toBool(); if (keep_running && event->spontaneous()) { - event->ignore(); + event->accept(); SetHiddenInTray(true); } else { QApplication::quit(); From 55a39a96091249f7635ee84a5786c68c7dfed611 Mon Sep 17 00:00:00 2001 From: Andreas Sturmlechner Date: Sat, 17 Mar 2018 07:16:49 +0100 Subject: [PATCH 059/104] Fix build with Qt 5.11 (#6029) --- src/playlist/playlistcontainer.cpp | 1 + src/ui/globalshortcutssettingspage.cpp | 1 + src/widgets/errordialog.cpp | 2 ++ 3 files changed, 4 insertions(+) diff --git a/src/playlist/playlistcontainer.cpp b/src/playlist/playlistcontainer.cpp index 58f1ad2d6..2ba1a3ff1 100644 --- a/src/playlist/playlistcontainer.cpp +++ b/src/playlist/playlistcontainer.cpp @@ -23,6 +23,7 @@ #include "playlistparsers/playlistparser.h" #include "ui/iconloader.h" +#include #include #include #include diff --git a/src/ui/globalshortcutssettingspage.cpp b/src/ui/globalshortcutssettingspage.cpp index ec5d29b28..c60a9561d 100644 --- a/src/ui/globalshortcutssettingspage.cpp +++ b/src/ui/globalshortcutssettingspage.cpp @@ -24,6 +24,7 @@ #include "ui/iconloader.h" #include "ui/settingsdialog.h" +#include #include #include #include diff --git a/src/widgets/errordialog.cpp b/src/widgets/errordialog.cpp index 1086305f3..3fd590840 100644 --- a/src/widgets/errordialog.cpp +++ b/src/widgets/errordialog.cpp @@ -18,6 +18,8 @@ #include "errordialog.h" #include "ui_errordialog.h" +#include + ErrorDialog::ErrorDialog(QWidget* parent) : QDialog(parent), ui_(new Ui_ErrorDialog) { ui_->setupUi(this); From 804168edc74d7230a84e8937e2ea9a3b1ad2e9c2 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Mon, 19 Mar 2018 15:18:56 +0100 Subject: [PATCH 060/104] Bring back album cover fetching from discogs. (#6028) * Bring back cover fetching from discogs. --- src/CMakeLists.txt | 2 + src/core/application.cpp | 4 +- src/covers/albumcoverfetcher.cpp | 5 +- src/covers/albumcoverfetcher.h | 6 +- src/covers/albumcoverfetchersearch.cpp | 5 + src/covers/amazoncoverprovider.cpp | 2 +- src/covers/coverprovider.cpp | 5 +- src/covers/coverprovider.h | 5 +- src/covers/discogscoverprovider.cpp | 323 ++++++++++++++++++++++++ src/covers/discogscoverprovider.h | 94 +++++++ src/covers/lastfmcoverprovider.cpp | 2 +- src/covers/musicbrainzcoverprovider.cpp | 2 +- src/ui/albumcoverchoicecontroller.cpp | 2 +- src/ui/albumcovermanager.cpp | 6 +- 14 files changed, 451 insertions(+), 12 deletions(-) create mode 100644 src/covers/discogscoverprovider.cpp create mode 100644 src/covers/discogscoverprovider.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6e24c9726..5db70ec64 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -107,6 +107,7 @@ set(SOURCES covers/albumcoverfetchersearch.cpp covers/albumcoverloader.cpp covers/amazoncoverprovider.cpp + covers/discogscoverprovider.cpp covers/coverexportrunnable.cpp covers/coverprovider.cpp covers/coverproviders.cpp @@ -430,6 +431,7 @@ set(HEADERS covers/albumcoverfetchersearch.h covers/albumcoverloader.h covers/amazoncoverprovider.h + covers/discogscoverprovider.h covers/coverexportrunnable.h covers/coverprovider.h covers/coverproviders.h diff --git a/src/core/application.cpp b/src/core/application.cpp index 031ae2106..7a0a94a0f 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -33,6 +33,7 @@ #include "covers/amazoncoverprovider.h" #include "covers/coverproviders.h" #include "covers/currentartloader.h" +#include "covers/discogscoverprovider.h" #include "covers/musicbrainzcoverprovider.h" #include "devices/devicemanager.h" #include "globalsearch/globalsearch.h" @@ -43,8 +44,8 @@ #include "internet/podcasts/podcastdeleter.h" #include "internet/podcasts/podcastdownloader.h" #include "internet/podcasts/podcastupdater.h" -#include "library/librarybackend.h" #include "library/library.h" +#include "library/librarybackend.h" #include "moodbar/moodbarcontroller.h" #include "moodbar/moodbarloader.h" #include "networkremote/networkremote.h" @@ -100,6 +101,7 @@ class ApplicationImpl { // Initialize the repository of cover providers. cover_providers->AddProvider(new AmazonCoverProvider); cover_providers->AddProvider(new MusicbrainzCoverProvider); + cover_providers->AddProvider(new DiscogsCoverProvider); #ifdef HAVE_LIBLASTFM cover_providers->AddProvider(new LastFmCoverProvider(app)); #endif diff --git a/src/covers/albumcoverfetcher.cpp b/src/covers/albumcoverfetcher.cpp index f32305eb3..3c409bb64 100644 --- a/src/covers/albumcoverfetcher.cpp +++ b/src/covers/albumcoverfetcher.cpp @@ -40,12 +40,14 @@ AlbumCoverFetcher::AlbumCoverFetcher(CoverProviders* cover_providers, } quint64 AlbumCoverFetcher::FetchAlbumCover(const QString& artist, - const QString& album) { + const QString& album, + bool fetchall) { CoverSearchRequest request; request.artist = artist; request.album = album; request.search = false; request.id = next_id_++; + request.fetchall = fetchall; AddRequest(request); return request.id; @@ -58,6 +60,7 @@ quint64 AlbumCoverFetcher::SearchForCovers(const QString& artist, request.album = album; request.search = true; request.id = next_id_++; + request.fetchall = false; AddRequest(request); return request.id; diff --git a/src/covers/albumcoverfetcher.h b/src/covers/albumcoverfetcher.h index 75e51161c..588c7ea2e 100644 --- a/src/covers/albumcoverfetcher.h +++ b/src/covers/albumcoverfetcher.h @@ -51,6 +51,9 @@ struct CoverSearchRequest { // is this only a search request or should we also fetch the first // cover that's found? bool search; + + // is the request part of fetchall (fetching all missing covers) + bool fetchall; }; // This structure represents a single result of some album's cover search @@ -88,7 +91,8 @@ class AlbumCoverFetcher : public QObject { static const int kMaxConcurrentRequests; quint64 SearchForCovers(const QString& artist, const QString& album); - quint64 FetchAlbumCover(const QString& artist, const QString& album); + quint64 FetchAlbumCover(const QString& artist, const QString& album, + bool fetchall); void Clear(); diff --git a/src/covers/albumcoverfetchersearch.cpp b/src/covers/albumcoverfetchersearch.cpp index 1bfdab7f8..3688fd132 100644 --- a/src/covers/albumcoverfetchersearch.cpp +++ b/src/covers/albumcoverfetchersearch.cpp @@ -63,6 +63,11 @@ void AlbumCoverFetcherSearch::TerminateSearch() { void AlbumCoverFetcherSearch::Start(CoverProviders* cover_providers) { for (CoverProvider* provider : cover_providers->List()) { + // Skip provider if it does not have fetchall set, and we are doing fetchall + // - "Fetch Missing Covers". + if (!provider->fetchall() && request_.fetchall) { + continue; + } connect(provider, SIGNAL(SearchFinished(int, QList)), SLOT(ProviderSearchFinished(int, QList))); const int id = cover_providers->NextId(); diff --git a/src/covers/amazoncoverprovider.cpp b/src/covers/amazoncoverprovider.cpp index fd7ac403b..e2613d26d 100644 --- a/src/covers/amazoncoverprovider.cpp +++ b/src/covers/amazoncoverprovider.cpp @@ -40,7 +40,7 @@ const char* AmazonCoverProvider::kUrl = "http://ecs.amazonaws.com/onca/xml"; const char* AmazonCoverProvider::kAssociateTag = "clemmusiplay-20"; AmazonCoverProvider::AmazonCoverProvider(QObject* parent) - : CoverProvider("Amazon", parent), + : CoverProvider("Amazon", true, parent), network_(new NetworkAccessManager(this)) {} bool AmazonCoverProvider::StartSearch(const QString& artist, diff --git a/src/covers/coverprovider.cpp b/src/covers/coverprovider.cpp index 17dd8a262..247109dfe 100644 --- a/src/covers/coverprovider.cpp +++ b/src/covers/coverprovider.cpp @@ -19,5 +19,6 @@ #include "coverprovider.h" -CoverProvider::CoverProvider(const QString& name, QObject* parent) - : QObject(parent), name_(name) {} +CoverProvider::CoverProvider(const QString& name, const bool& fetchall, + QObject* parent) + : QObject(parent), name_(name), fetchall_(fetchall) {} diff --git a/src/covers/coverprovider.h b/src/covers/coverprovider.h index c87ad5dae..040eaa201 100644 --- a/src/covers/coverprovider.h +++ b/src/covers/coverprovider.h @@ -35,10 +35,12 @@ class CoverProvider : public QObject { Q_OBJECT public: - explicit CoverProvider(const QString& name, QObject* parent); + explicit CoverProvider(const QString& name, const bool& fetchall, + QObject* parent); // A name (very short description) of this provider, like "last.fm". QString name() const { return name_; } + bool fetchall() const { return fetchall_; } // Starts searching for covers matching the given query text. Returns true // if the query has been started, or false if an error occurred. The provider @@ -53,6 +55,7 @@ class CoverProvider : public QObject { private: QString name_; + bool fetchall_; }; #endif // COVERS_COVERPROVIDER_H_ diff --git a/src/covers/discogscoverprovider.cpp b/src/covers/discogscoverprovider.cpp new file mode 100644 index 000000000..95e00fe28 --- /dev/null +++ b/src/covers/discogscoverprovider.cpp @@ -0,0 +1,323 @@ +/* This file is part of Clementine. + Copyright 2012, Martin Björklund + Copyright 2018, Jonas Kvinge + + Clementine is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Clementine 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 Clementine. If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "discogscoverprovider.h" + +#include "core/closure.h" +#include "core/logging.h" +#include "core/network.h" +#include "core/utilities.h" + +const char* DiscogsCoverProvider::kUrlSearch = + "https://api.discogs.com/database/search"; +const char* DiscogsCoverProvider::kUrlReleases = + "https://api.discogs.com/releases"; + +const char* DiscogsCoverProvider::kAccessKeyB64 = + "YVR4Yk5JTnlmUkhFY0pTaldid2c="; +const char* DiscogsCoverProvider::kSecretKeyB64 = + "QkJNb2tMVXVUVFhSRWRUVmZDc0ZGamZmSWRjdHZRVno="; + +DiscogsCoverProvider::DiscogsCoverProvider(QObject* parent) + : CoverProvider("Discogs", false, parent), + network_(new NetworkAccessManager(this)) {} + +bool DiscogsCoverProvider::StartSearch(const QString& artist, + const QString& album, int s_id) { + DiscogsCoverSearchContext* s_ctx = new DiscogsCoverSearchContext; + + s_ctx->id = s_id; + s_ctx->artist = artist; + s_ctx->album = album; + s_ctx->r_count = 0; + requests_search_.insert(s_id, s_ctx); + SendSearchRequest(s_ctx); + + return true; +} + +void DiscogsCoverProvider::CancelSearch(int id) { + delete requests_search_.take(id); +} + +bool DiscogsCoverProvider::StartRelease(DiscogsCoverSearchContext* s_ctx, + int r_id, QString resource_url) { + DiscogsCoverReleaseContext* r_ctx = new DiscogsCoverReleaseContext; + + s_ctx->r_count++; + + r_ctx->id = r_id; + r_ctx->resource_url = resource_url; + + r_ctx->s_id = s_ctx->id; + + requests_release_.insert(r_id, r_ctx); + SendReleaseRequest(s_ctx, r_ctx); + + return true; +} + +void DiscogsCoverProvider::SendSearchRequest(DiscogsCoverSearchContext* s_ctx) { + typedef QPair Arg; + typedef QList ArgList; + + typedef QPair EncodedArg; + typedef QList EncodedArgList; + + ArgList args = + ArgList() << Arg("key", QByteArray::fromBase64(kAccessKeyB64)) + << Arg("secret", QByteArray::fromBase64(kSecretKeyB64)); + + args.append(Arg("type", "release")); + if (!s_ctx->artist.isEmpty()) { + args.append(Arg("artist", s_ctx->artist.toLower())); + } + if (!s_ctx->album.isEmpty()) { + args.append(Arg("release_title", s_ctx->album.toLower())); + } + + QUrlQuery url_query; + QUrl url(kUrlSearch); + QStringList query_items; + + // Encode the arguments + for (const Arg& arg : args) { + EncodedArg encoded_arg(QUrl::toPercentEncoding(arg.first), + QUrl::toPercentEncoding(arg.second)); + query_items << QString(encoded_arg.first + "=" + encoded_arg.second); + url_query.addQueryItem(encoded_arg.first, encoded_arg.second); + } + + // Sign the request + const QByteArray data_to_sign = + QString("GET\n%1\n%2\n%3") + .arg(url.host(), url.path(), query_items.join("&")) + .toUtf8(); + const QByteArray signature(Utilities::HmacSha256( + QByteArray::fromBase64(kSecretKeyB64), data_to_sign)); + + // Add the signature to the request + url_query.addQueryItem("Signature", + QUrl::toPercentEncoding(signature.toBase64())); + + url.setQuery(url_query); + QNetworkReply* reply = network_->get(QNetworkRequest(url)); + + NewClosure(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, + SLOT(SearchRequestError(QNetworkReply::NetworkError, + QNetworkReply*, int)), + reply, s_ctx->id); + NewClosure(reply, SIGNAL(finished()), this, + SLOT(HandleSearchReply(QNetworkReply*, int)), reply, s_ctx->id); +} + +void DiscogsCoverProvider::SendReleaseRequest( + DiscogsCoverSearchContext* s_ctx, DiscogsCoverReleaseContext* r_ctx) { + typedef QPair Arg; + typedef QList ArgList; + + typedef QPair EncodedArg; + typedef QList EncodedArgList; + + QUrlQuery url_query; + QStringList query_items; + + ArgList args = + ArgList() << Arg("key", QByteArray::fromBase64(kAccessKeyB64)) + << Arg("secret", QByteArray::fromBase64(kSecretKeyB64)); + // Encode the arguments + for (const Arg& arg : args) { + EncodedArg encoded_arg(QUrl::toPercentEncoding(arg.first), + QUrl::toPercentEncoding(arg.second)); + query_items << QString(encoded_arg.first + "=" + encoded_arg.second); + url_query.addQueryItem(encoded_arg.first, encoded_arg.second); + } + + QUrl url(r_ctx->resource_url); + + // Sign the request + const QByteArray data_to_sign = + QString("GET\n%1\n%2\n%3") + .arg(url.host(), url.path(), query_items.join("&")) + .toUtf8(); + const QByteArray signature(Utilities::HmacSha256( + QByteArray::fromBase64(kSecretKeyB64), data_to_sign)); + + // Add the signature to the request + url_query.addQueryItem("Signature", + QUrl::toPercentEncoding(signature.toBase64())); + + url.setQuery(url_query); + QNetworkReply* reply = network_->get(QNetworkRequest(url)); + + NewClosure(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, + SLOT(ReleaseRequestError(QNetworkReply::NetworkError, + QNetworkReply*, int, int)), + reply, s_ctx->id, r_ctx->id); + NewClosure(reply, SIGNAL(finished()), this, + SLOT(HandleReleaseReply(QNetworkReply*, int, int)), reply, + s_ctx->id, r_ctx->id); +} + +void DiscogsCoverProvider::HandleSearchReply(QNetworkReply* reply, int s_id) { + reply->deleteLater(); + + if (!requests_search_.contains(s_id)) return; + DiscogsCoverSearchContext* s_ctx = requests_search_.value(s_id); + + QJsonDocument json_doc = QJsonDocument::fromJson(reply->readAll()); + if ((json_doc.isNull()) || (!json_doc.isObject())) { + qLog(Error) << "Discogs: Failed to create JSON doc."; + EndSearch(s_ctx); + return; + } + + QJsonObject json_obj = json_doc.object(); + if (json_obj.isEmpty()) { + qLog(Error) << "Discogs: Failed to create JSON object."; + EndSearch(s_ctx); + return; + } + + QVariantMap reply_map = json_obj.toVariantMap(); + if (!reply_map.contains("results")) { + EndSearch(s_ctx); + return; + } + + QVariantList results = reply_map["results"].toList(); + int i = 0; + for (const QVariant& result : results) { + QVariantMap result_map = result.toMap(); + if ((result_map.contains("id")) && (result_map.contains("resource_url"))) { + int r_id = result_map["id"].toInt(); + QString title = result_map["title"].toString(); + QString resource_url = result_map["resource_url"].toString(); + if (resource_url.isEmpty()) continue; + StartRelease(s_ctx, r_id, resource_url); + i++; + } + } + if (i <= 0) EndSearch(s_ctx); +} + +void DiscogsCoverProvider::HandleReleaseReply(QNetworkReply* reply, int s_id, + int r_id) { + reply->deleteLater(); + + if (!requests_release_.contains(r_id)) return; + DiscogsCoverReleaseContext* r_ctx = requests_release_.value(r_id); + + if (!requests_search_.contains(s_id)) { + EndSearch(r_ctx); + return; + } + DiscogsCoverSearchContext* s_ctx = requests_search_.value(s_id); + + QJsonDocument json_doc = QJsonDocument::fromJson(reply->readAll()); + if ((json_doc.isNull()) || (!json_doc.isObject())) { + qLog(Error) << "Discogs: Failed to create JSON doc."; + EndSearch(s_ctx, r_ctx); + return; + } + QJsonObject json_obj = json_doc.object(); + if (json_obj.isEmpty()) { + qLog(Error) << "Discogs: JSON object is empty."; + EndSearch(s_ctx, r_ctx); + return; + } + + QVariantMap reply_map = json_obj.toVariantMap(); + if (!reply_map.contains("images")) { + EndSearch(s_ctx, r_ctx); + return; + } + + QVariantList results = reply_map["images"].toList(); + + for (const QVariant& result : results) { + QVariantMap result_map = result.toMap(); + CoverSearchResult cover_result; + cover_result.description = s_ctx->title; + + if (result_map.contains("type")) { + QString type = result_map["type"].toString(); + if (type != "primary") continue; + } + if (result_map.contains("resource_url")) { + cover_result.image_url = QUrl(result_map["resource_url"].toString()); + } + if (cover_result.image_url.isEmpty()) continue; + s_ctx->results.append(cover_result); + } + + EndSearch(s_ctx, r_ctx); +} + +void DiscogsCoverProvider::SearchRequestError(QNetworkReply::NetworkError error, + QNetworkReply* reply, int s_id) { + if (!requests_search_.contains(s_id)) return; + DiscogsCoverSearchContext* s_ctx = requests_search_.value(s_id); + + EndSearch(s_ctx); +} + +void DiscogsCoverProvider::ReleaseRequestError( + QNetworkReply::NetworkError error, QNetworkReply* reply, int s_id, + int r_id) { + if (!requests_release_.contains(r_id)) return; + DiscogsCoverReleaseContext* r_ctx = requests_release_.value(r_id); + + if (!requests_search_.contains(s_id)) { + EndSearch(r_ctx); + return; + } + DiscogsCoverSearchContext* s_ctx = requests_search_.value(s_id); + EndSearch(s_ctx, r_ctx); +} + +void DiscogsCoverProvider::EndSearch(DiscogsCoverSearchContext* s_ctx, + DiscogsCoverReleaseContext* r_ctx) { + delete requests_release_.take(r_ctx->id); + + s_ctx->r_count--; + + if (s_ctx->r_count <= 0) EndSearch(s_ctx); +} + +void DiscogsCoverProvider::EndSearch(DiscogsCoverSearchContext* s_ctx) { + requests_search_.remove(s_ctx->id); + emit SearchFinished(s_ctx->id, s_ctx->results); + delete s_ctx; +} + +void DiscogsCoverProvider::EndSearch(DiscogsCoverReleaseContext* r_ctx) { + delete requests_release_.take(r_ctx->id); +} diff --git a/src/covers/discogscoverprovider.h b/src/covers/discogscoverprovider.h new file mode 100644 index 000000000..3b16c0597 --- /dev/null +++ b/src/covers/discogscoverprovider.h @@ -0,0 +1,94 @@ +/* This file is part of Clementine. + Copyright 2012, Martin Björklund + Copyright 2018, Jonas Kvinge + + Clementine is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Clementine 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 Clementine. If not, see . +*/ + +#ifndef COVERS_DISCOGSCOVERPROVIDER_H +#define COVERS_DISCOGSCOVERPROVIDER_H + +#include +#include + +#include "coverprovider.h" + +class QNetworkAccessManager; + +// This struct represents a single search request. It identifies and describes +// the request. +struct DiscogsCoverSearchContext { + // the unique request identifier + int id; + + // the search query + QString artist; + QString album; + QString title; + int r_count; + + CoverSearchResults results; +}; +Q_DECLARE_METATYPE(DiscogsCoverSearchContext) + +// This struct represents a single release request. It identifies and describes +// the request. +struct DiscogsCoverReleaseContext { + int id; // the unique request identifier + int s_id; // the search request identifier + + QString resource_url; +}; +Q_DECLARE_METATYPE(DiscogsCoverReleaseContext) + +class DiscogsCoverProvider : public CoverProvider { + Q_OBJECT + + public: + explicit DiscogsCoverProvider(QObject* parent = nullptr); + + bool StartSearch(const QString& artist, const QString& album, int s_id); + void CancelSearch(int id); + + private slots: + void SearchRequestError(QNetworkReply::NetworkError error, + QNetworkReply* reply, int s_id); + void ReleaseRequestError(QNetworkReply::NetworkError error, + QNetworkReply* reply, int s_id, int r_id); + void HandleSearchReply(QNetworkReply* reply, int s_id); + void HandleReleaseReply(QNetworkReply* reply, int s_id, int r_id); + + private: + static const char* kUrlSearch; + static const char* kUrlReleases; + static const char* kAccessKeyB64; + static const char* kSecretKeyB64; + + QNetworkAccessManager* network_; + QHash requests_search_; + QHash requests_release_; + + bool StartRelease(DiscogsCoverSearchContext* s_ctx, int r_id, + QString resource_url); + + void SendSearchRequest(DiscogsCoverSearchContext* s_ctx); + void SendReleaseRequest(DiscogsCoverSearchContext* s_ctx, + DiscogsCoverReleaseContext* r_ctx); + void EndSearch(DiscogsCoverSearchContext* s_ctx, + DiscogsCoverReleaseContext* r_ctx); + void EndSearch(DiscogsCoverSearchContext* s_ctx); + void EndSearch(DiscogsCoverReleaseContext* r_ctx); +}; + +#endif // COVERS_DISCOGSCOVERPROVIDER_H diff --git a/src/covers/lastfmcoverprovider.cpp b/src/covers/lastfmcoverprovider.cpp index a83cc71e3..cd7d0d8ea 100644 --- a/src/covers/lastfmcoverprovider.cpp +++ b/src/covers/lastfmcoverprovider.cpp @@ -29,7 +29,7 @@ #include "internet/lastfm/lastfmcompat.h" LastFmCoverProvider::LastFmCoverProvider(QObject* parent) - : CoverProvider("last.fm", parent) {} + : CoverProvider("last.fm", true, parent) {} bool LastFmCoverProvider::StartSearch(const QString& artist, const QString& album, int id) { diff --git a/src/covers/musicbrainzcoverprovider.cpp b/src/covers/musicbrainzcoverprovider.cpp index fffaab179..73d945e38 100644 --- a/src/covers/musicbrainzcoverprovider.cpp +++ b/src/covers/musicbrainzcoverprovider.cpp @@ -37,7 +37,7 @@ static const char* kAlbumCoverUrl = } // namespace MusicbrainzCoverProvider::MusicbrainzCoverProvider(QObject* parent) - : CoverProvider("MusicBrainz", parent), + : CoverProvider("MusicBrainz", true, parent), network_(new NetworkAccessManager(this)) {} bool MusicbrainzCoverProvider::StartSearch(const QString& artist, diff --git a/src/ui/albumcoverchoicecontroller.cpp b/src/ui/albumcoverchoicecontroller.cpp index d2cea9f39..b15aa6a6f 100644 --- a/src/ui/albumcoverchoicecontroller.cpp +++ b/src/ui/albumcoverchoicecontroller.cpp @@ -250,7 +250,7 @@ void AlbumCoverChoiceController::ShowCover(const Song& song) { void AlbumCoverChoiceController::SearchCoverAutomatically(const Song& song) { qint64 id = cover_fetcher_->FetchAlbumCover(song.effective_albumartist(), - song.effective_album()); + song.effective_album(), false); cover_fetching_tasks_[id] = song; } diff --git a/src/ui/albumcovermanager.cpp b/src/ui/albumcovermanager.cpp index b79a9bcdc..bdfbff300 100644 --- a/src/ui/albumcovermanager.cpp +++ b/src/ui/albumcovermanager.cpp @@ -430,7 +430,8 @@ void AlbumCoverManager::FetchAlbumCovers() { if (ItemHasCover(*item)) continue; quint64 id = cover_fetcher_->FetchAlbumCover( - EffectiveAlbumArtistName(*item), item->data(Role_AlbumName).toString()); + EffectiveAlbumArtistName(*item), item->data(Role_AlbumName).toString(), + true); cover_fetching_tasks_[id] = item; jobs_++; } @@ -566,7 +567,8 @@ void AlbumCoverManager::ShowCover() { void AlbumCoverManager::FetchSingleCover() { for (QListWidgetItem* item : context_menu_items_) { quint64 id = cover_fetcher_->FetchAlbumCover( - EffectiveAlbumArtistName(*item), item->data(Role_AlbumName).toString()); + EffectiveAlbumArtistName(*item), item->data(Role_AlbumName).toString(), + false); cover_fetching_tasks_[id] = item; jobs_++; } From a4e362b9f76de7ef58e494479b159aa3a447c42c Mon Sep 17 00:00:00 2001 From: Andreas Sturmlechner Date: Mon, 16 Apr 2018 01:05:32 +0200 Subject: [PATCH 061/104] Fix cmake with Qt 5.11_beta3 (dropping qt5_use_modules) One usage of the macro remains in the bundled libmygpo-qt5. This should be updated once the pending upstream fix was merged. qtsingleapplication is already fixed upstream. --- 3rdparty/qtiocompressor/CMakeLists.txt | 2 +- 3rdparty/qtsingleapplication/CMakeLists.txt | 2 +- 3rdparty/qxt/CMakeLists.txt | 4 ++-- ext/libclementine-common/CMakeLists.txt | 2 +- gst/moodbar/CMakeLists.txt | 2 +- tests/CMakeLists.txt | 3 +-- 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/3rdparty/qtiocompressor/CMakeLists.txt b/3rdparty/qtiocompressor/CMakeLists.txt index 090a057a6..bbead7d9e 100644 --- a/3rdparty/qtiocompressor/CMakeLists.txt +++ b/3rdparty/qtiocompressor/CMakeLists.txt @@ -15,4 +15,4 @@ ADD_LIBRARY(qtiocompressor STATIC ${IOCOMPRESSOR-SOURCES-MOC} ) -QT5_USE_MODULES(qtiocompressor Core) +target_link_libraries(qtiocompressor Qt5::Core) diff --git a/3rdparty/qtsingleapplication/CMakeLists.txt b/3rdparty/qtsingleapplication/CMakeLists.txt index 75d098d69..e7639b3f6 100644 --- a/3rdparty/qtsingleapplication/CMakeLists.txt +++ b/3rdparty/qtsingleapplication/CMakeLists.txt @@ -25,4 +25,4 @@ ADD_LIBRARY(qtsingleapplication STATIC ${SINGLEAPP-SOURCES-MOC} ) -QT5_USE_MODULES(qtsingleapplication Core Widgets Network) +target_link_libraries(qtsingleapplication Qt5::Core Qt5::Widgets Qt5::Network) diff --git a/3rdparty/qxt/CMakeLists.txt b/3rdparty/qxt/CMakeLists.txt index 75fa686b2..9f56983c3 100644 --- a/3rdparty/qxt/CMakeLists.txt +++ b/3rdparty/qxt/CMakeLists.txt @@ -29,7 +29,7 @@ ADD_LIBRARY(qxt STATIC ) if(WIN32) - QT5_USE_MODULES(qxt Core Widgets) + target_link_libraries(qxt Qt5::Core Qt5::Widgets) else(WIN32) - QT5_USE_MODULES(qxt Core Widgets X11Extras) + target_link_libraries(qxt Qt5::Core Qt5::Widgets Qt5::X11Extras) endif(WIN32) diff --git a/ext/libclementine-common/CMakeLists.txt b/ext/libclementine-common/CMakeLists.txt index 2cf31339b..200f73c96 100644 --- a/ext/libclementine-common/CMakeLists.txt +++ b/ext/libclementine-common/CMakeLists.txt @@ -40,4 +40,4 @@ target_link_libraries(libclementine-common ${CMAKE_THREAD_LIBS_INIT} ) -QT5_USE_MODULES(libclementine-common Core Network) +target_link_libraries(libclementine-common Qt5::Core Qt5::Network) diff --git a/gst/moodbar/CMakeLists.txt b/gst/moodbar/CMakeLists.txt index 6ffc793e0..7713046e1 100644 --- a/gst/moodbar/CMakeLists.txt +++ b/gst/moodbar/CMakeLists.txt @@ -28,4 +28,4 @@ target_link_libraries(gstmoodbar ${FFTW3_FFTW_LIBRARY} ) -QT5_USE_MODULES(gstmoodbar Core) +target_link_libraries(gstmoodbar Qt5::Core) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 24863a4a8..4474e7be5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -99,8 +99,7 @@ macro(add_test_file test_source gui_required) EXCLUDE_FROM_ALL ${test_source} ) - target_link_libraries(${TEST_NAME} ${GMOCK_LIBRARIES} clementine_lib test_utils) - qt5_use_modules (${TEST_NAME} Test) + target_link_libraries(${TEST_NAME} ${GMOCK_LIBRARIES} clementine_lib test_utils Qt5::Test) set(GUI_REQUIRED ${gui_required}) if (GUI_REQUIRED) target_link_libraries(${TEST_NAME} test_gui_main) From 6a312e7459c3f7a6c7fbccd96c2abdd4e78a621f Mon Sep 17 00:00:00 2001 From: Antonio Russo Date: Tue, 22 May 2018 06:18:54 -0400 Subject: [PATCH 062/104] Limit both QSettings reads and writes (#6057) Any access, read or write, via QSettings requires locking `Clementine.conf`. On some devices, this can be slow. Moreover, it also increases power use and wear on devices such as SSDs. To improve the situation, defer QSettings updates until program close for window resize, current playlist tab, and playlist geometry, i.e. `PlaylistView::SaveGeometry`. Also, limit `PlaylistView::LoadGeometry` to once per program run. Signed-off-by: Antonio Russo --- src/playlist/playlistcontainer.cpp | 6 ++++-- src/playlist/playlistview.cpp | 16 ++++++++-------- src/playlist/playlistview.h | 3 +++ src/ui/mainwindow.cpp | 7 ------- src/ui/mainwindow.h | 1 - 5 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/playlist/playlistcontainer.cpp b/src/playlist/playlistcontainer.cpp index 2ba1a3ff1..78003fbba 100644 --- a/src/playlist/playlistcontainer.cpp +++ b/src/playlist/playlistcontainer.cpp @@ -94,7 +94,6 @@ PlaylistContainer::PlaylistContainer(QWidget* parent) ui_->tab_bar->setMaximumHeight(0); // Connections - connect(ui_->tab_bar, SIGNAL(currentChanged(int)), SLOT(Save())); connect(ui_->tab_bar, SIGNAL(Save(int)), SLOT(SavePlaylist(int))); // set up timer for delayed filter updates @@ -109,7 +108,10 @@ PlaylistContainer::PlaylistContainer(QWidget* parent) ui_->filter->installEventFilter(this); } -PlaylistContainer::~PlaylistContainer() { delete ui_; } +PlaylistContainer::~PlaylistContainer() { + Save(); + delete ui_; +} PlaylistView* PlaylistContainer::view() const { return ui_->playlist; } diff --git a/src/playlist/playlistview.cpp b/src/playlist/playlistview.cpp index 0e1f50a32..5473188c2 100644 --- a/src/playlist/playlistview.cpp +++ b/src/playlist/playlistview.cpp @@ -113,6 +113,7 @@ PlaylistView::PlaylistView(QWidget* parent) upgrading_from_qheaderview_(false), read_only_settings_(true), upgrading_from_version_(-1), + header_loaded_(false), background_initialized_(false), background_image_type_(Default), blur_radius_(kDefaultBlurRadius), @@ -148,12 +149,6 @@ PlaylistView::PlaylistView(QWidget* parent) currenttrack_pause_ = currenttrack_pause.pixmap(currenttrack_pause.actualSize(QSize(32, 32))); - connect(header_, SIGNAL(sectionResized(int, int, int)), SLOT(SaveGeometry())); - connect(header_, SIGNAL(sectionMoved(int, int, int)), SLOT(SaveGeometry())); - connect(header_, SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), - SLOT(SaveGeometry())); - connect(header_, SIGNAL(SectionVisibilityChanged(int, bool)), - SLOT(SaveGeometry())); connect(header_, SIGNAL(SectionRatingLockStatusChanged(bool)), SLOT(SetRatingLockStatus(bool))); connect(header_, SIGNAL(sectionResized(int, int, int)), @@ -190,6 +185,11 @@ PlaylistView::PlaylistView(QWidget* parent) fade_animation_->setDirection(QTimeLine::Backward); // 1.0 -> 0.0 } +PlaylistView::~PlaylistView() { + SaveGeometry(); + delete style_; +} + void PlaylistView::SetApplication(Application* app) { Q_ASSERT(app); app_ = app; @@ -281,7 +281,7 @@ void PlaylistView::SetPlaylist(Playlist* playlist) { } playlist_ = playlist; - LoadGeometry(); + if (!header_loaded_) LoadGeometry(); LoadRatingLockStatus(); ReloadSettings(); DynamicModeChanged(playlist->is_dynamic()); @@ -326,6 +326,7 @@ void PlaylistView::setModel(QAbstractItemModel* m) { void PlaylistView::LoadGeometry() { QSettings settings; + header_loaded_ = true; settings.beginGroup(Playlist::kSettingsGroup); QByteArray state(settings.value("state").toByteArray()); @@ -1177,7 +1178,6 @@ void PlaylistView::SaveSettings() { void PlaylistView::StretchChanged(bool stretch) { setHorizontalScrollBarPolicy(stretch ? Qt::ScrollBarAlwaysOff : Qt::ScrollBarAsNeeded); - SaveGeometry(); } void PlaylistView::DynamicModeChanged(bool dynamic) { diff --git a/src/playlist/playlistview.h b/src/playlist/playlistview.h index 512d4d607..4e97f6347 100644 --- a/src/playlist/playlistview.h +++ b/src/playlist/playlistview.h @@ -57,6 +57,8 @@ class PlaylistProxyStyle : public QProxyStyle { class PlaylistView : public QTreeView { Q_OBJECT public: + ~PlaylistView(); + enum BackgroundImageType { Default, None, Custom, AlbumCover }; PlaylistView(QWidget* parent = nullptr); @@ -194,6 +196,7 @@ signals: bool upgrading_from_qheaderview_; bool read_only_settings_; int upgrading_from_version_; + bool header_loaded_; bool background_initialized_; BackgroundImageType background_image_type_; diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index aa44ead14..ab90ec7ef 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -865,11 +865,6 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd, connect(global_shortcuts_, SIGNAL(RemoveCurrentSong()), app_->playlist_manager(), SLOT(RemoveCurrentSong())); - // Fancy tabs - connect(ui_->tabs, SIGNAL(ModeChanged(FancyTabWidget::Mode)), - SLOT(SaveGeometry())); - connect(ui_->tabs, SIGNAL(CurrentChanged(int)), SLOT(SaveGeometry())); - // Lyrics ConnectInfoView(song_info_view_); ConnectInfoView(artist_info_view_); @@ -1261,8 +1256,6 @@ void MainWindow::ScrobbleButtonVisibilityChanged(bool value) { } } -void MainWindow::resizeEvent(QResizeEvent*) { SaveGeometry(); } - void MainWindow::SaveGeometry() { was_maximized_ = isMaximized(); settings_.setValue("maximized", was_maximized_); diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h index bfcc95b58..9277d54f1 100644 --- a/src/ui/mainwindow.h +++ b/src/ui/mainwindow.h @@ -131,7 +131,6 @@ class MainWindow : public QMainWindow, public PlatformInterface { protected: void keyPressEvent(QKeyEvent* event); - void resizeEvent(QResizeEvent* event); void closeEvent(QCloseEvent* event); #ifdef Q_OS_WIN32 From 783cdf938a48ad81dfbbef84949f932d0a6509e4 Mon Sep 17 00:00:00 2001 From: Antonio Russo Date: Wed, 23 May 2018 07:53:12 -0400 Subject: [PATCH 063/104] Do not reset column_widths_ on model change (#6058) `column_widths_` is managed elsewhere. Resetting it on model change makes tab-switching slow, and---if a vertical scroll bar becomes visible or hidden---can be triggered in unexpected situations, leading to visible column information loss. Signed-off-by: Antonio Russo --- src/widgets/stretchheaderview.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/widgets/stretchheaderview.cpp b/src/widgets/stretchheaderview.cpp index 77d988873..e2f8838ee 100644 --- a/src/widgets/stretchheaderview.cpp +++ b/src/widgets/stretchheaderview.cpp @@ -39,11 +39,6 @@ StretchHeaderView::StretchHeaderView(Qt::Orientation orientation, void StretchHeaderView::setModel(QAbstractItemModel* model) { QHeaderView::setModel(model); - - if (stretch_enabled_) { - column_widths_.resize(count()); - std::fill(column_widths_.begin(), column_widths_.end(), 1.0 / count()); - } } void StretchHeaderView::NormaliseWidths(const QList& sections) { From 4619a4c1ab3b17b13d4b2327ad477912917eaf36 Mon Sep 17 00:00:00 2001 From: ftiede Date: Wed, 23 May 2018 15:23:21 +0200 Subject: [PATCH 064/104] Work around Qt's QUrl parser. (#6059) Qt's QUrl parser does no longer accept pure numeric hostnames without trying to make a dotted IPv4 address of them. Thus current method of storing subsonic's numeric ids in the host part of a QUrl ("subsonic://") does no longer work. Instead a query is constructed omitting the host-part entirely and using "subsonic://?id=" to store and retrieve subsonic titles. --- src/internet/subsonic/subsonicservice.cpp | 5 ++++- src/internet/subsonic/subsonicurlhandler.cpp | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/internet/subsonic/subsonicservice.cpp b/src/internet/subsonic/subsonicservice.cpp index cce04a32a..24ad4588e 100644 --- a/src/internet/subsonic/subsonicservice.cpp +++ b/src/internet/subsonic/subsonicservice.cpp @@ -541,7 +541,10 @@ void SubsonicLibraryScanner::OnGetAlbumFinished(QNetworkReply* reply) { qint64 length = reader.attributes().value("duration").toString().toInt(); length *= kNsecPerSec; song.set_length_nanosec(length); - QUrl url = QUrl(QString("subsonic://%1").arg(id)); + QUrl url = QUrl(QString("subsonic://")); + QUrlQuery song_query(url.query()); + song_query.addQueryItem("id", id); + url.setQuery(song_query); QUrl cover_url = service_->BuildRequestUrl("getCoverArt"); QUrlQuery cover_url_query(url.query()); cover_url_query.addQueryItem("id", id); diff --git a/src/internet/subsonic/subsonicurlhandler.cpp b/src/internet/subsonic/subsonicurlhandler.cpp index 91177cf90..f3a33faac 100644 --- a/src/internet/subsonic/subsonicurlhandler.cpp +++ b/src/internet/subsonic/subsonicurlhandler.cpp @@ -30,9 +30,10 @@ UrlHandler::LoadResult SubsonicUrlHandler::StartLoading(const QUrl& url) { if (service_->login_state() != SubsonicService::LoginState_Loggedin) return LoadResult(url); + QUrlQuery id(url.query()); QUrl newurl = service_->BuildRequestUrl("stream"); QUrlQuery url_query(newurl.query()); - url_query.addQueryItem("id", url.host()); + url_query.addQueryItem("id", id.queryItemValue("id")); newurl.setQuery(url_query); return LoadResult(url, LoadResult::TrackAvailable, newurl); } From 0de964954df469b30fe624bbc64b923525033b93 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Fri, 29 Jun 2018 02:48:53 +0200 Subject: [PATCH 065/104] Replace toAscii/fromAscii with toLatin1/fromLatin1 --- ext/libclementine-tagreader/gmereader.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ext/libclementine-tagreader/gmereader.cpp b/ext/libclementine-tagreader/gmereader.cpp index 1e1c6d443..25d1ccd83 100644 --- a/ext/libclementine-tagreader/gmereader.cpp +++ b/ext/libclementine-tagreader/gmereader.cpp @@ -32,7 +32,7 @@ void GME::SPC::Read(const QFileInfo& file_info, qLog(Debug) << "Reading tags from SPC file: " << file_info.fileName(); // Check for header -- more reliable than file name alone. - if (!file.read(33).startsWith(QString("SNES-SPC700").toAscii())) return; + if (!file.read(33).startsWith(QString("SNES-SPC700").toLatin1())) return; /* * First order of business -- get any tag values that exist within the core @@ -47,13 +47,13 @@ void GME::SPC::Read(const QFileInfo& file_info, bool has_id6 = (file.read(1)[0] == (char)xID6_STATUS::ON); file.seek(SONG_TITLE_OFFSET); - song_info->set_title(QString::fromAscii(file.read(32)).toStdString()); + song_info->set_title(QString::fromLatin1(file.read(32)).toStdString()); file.seek(GAME_TITLE_OFFSET); - song_info->set_album(QString::fromAscii(file.read(32)).toStdString()); + song_info->set_album(QString::fromLatin1(file.read(32)).toStdString()); file.seek(ARTIST_OFFSET); - song_info->set_artist(QString::fromAscii(file.read(32)).toStdString()); + song_info->set_artist(QString::fromLatin1(file.read(32)).toStdString()); file.seek(INTRO_LENGTH_OFFSET); QByteArray length_bytes = file.read(INTRO_LENGTH_SIZE); @@ -89,7 +89,7 @@ void GME::SPC::Read(const QFileInfo& file_info, * in data from this is ideal before trying to rely on APETAG values. XID6 * format follows EA's binary file format standard named "IFF" */ file.seek(XID6_OFFSET); - if (has_id6 && file.read(4) == QString("xid6").toAscii()) { + if (has_id6 && file.read(4) == QString("xid6").toLatin1()) { QByteArray xid6_head_data = file.read(4); if (xid6_head_data.size() >= 4) { qint64 xid6_size = xid6_head_data[0] | (xid6_head_data[1] << 8) | @@ -160,7 +160,7 @@ void GME::VGM::Read(const QFileInfo& file_info, qLog(Debug) << "Reading tags from VGM file: " << file_info.fileName(); - if (!file.read(4).startsWith(QString("Vgm ").toAscii())) return; + if (!file.read(4).startsWith(QString("Vgm ").toLatin1())) return; file.seek(GD3_TAG_PTR); QByteArray gd3_head = file.read(4); From 58108dd0d0f2a243a71b39154f0a3be0f766201d Mon Sep 17 00:00:00 2001 From: Amish Naidu Date: Thu, 4 Oct 2018 12:12:09 +0530 Subject: [PATCH 066/104] Set OpenGL_GL_PREFERENCE to LEGACY to silence warnings on cmake 3.11+ --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index d4fc2982c..5b5091484 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ if(APPLE) endif(NOT QT_MAC_USE_COCOA) endif(APPLE) +set(OpenGL_GL_PREFERENCE LEGACY) find_package(OpenGL REQUIRED) find_package(Boost REQUIRED) find_package(Gettext REQUIRED) From fb00835468295925a6945a286406a2eec6bdb67a Mon Sep 17 00:00:00 2001 From: Amish Naidu Date: Fri, 5 Oct 2018 00:30:05 +0530 Subject: [PATCH 067/104] Allow ignoring prefixes when sorting playlist This introduces new configuration options which allow you to ignore prefixes while sorting the playlist on album, artist and titles. Prefixes are configurable, default are "a" and "the". --- src/playlist/playlist.cpp | 60 +++++++++++++++++++++++++------- src/playlist/playlist.h | 5 ++- src/ui/behavioursettingspage.cpp | 9 +++++ src/ui/behavioursettingspage.ui | 23 ++++++++++++ 4 files changed, 83 insertions(+), 14 deletions(-) diff --git a/src/playlist/playlist.cpp b/src/playlist/playlist.cpp index 72198910f..e386ead46 100644 --- a/src/playlist/playlist.cpp +++ b/src/playlist/playlist.cpp @@ -89,6 +89,8 @@ const char* Playlist::kSettingsGroup = "Playlist"; const char* Playlist::kPathType = "path_type"; const char* Playlist::kWriteMetadata = "write_metadata"; +const char* Playlist::kSortIgnorePrefix = "sort_ignore_prefix"; +const char* Playlist::kSortIgnorePrefixList = "sort_ignore_prefix_list"; const int Playlist::kUndoStackSize = 20; const int Playlist::kUndoItemLimit = 500; @@ -96,6 +98,17 @@ const int Playlist::kUndoItemLimit = 500; const qint64 Playlist::kMinScrobblePointNsecs = 31ll * kNsecPerSec; const qint64 Playlist::kMaxScrobblePointNsecs = 240ll * kNsecPerSec; +namespace { +QString removePrefix(const QString& a, const QStringList& prefixes) { + for (const QString& prefix : prefixes) { + if (a.startsWith(prefix)) { + return a.mid(prefix.size()); + } + } + return a; +} +} // namespace + Playlist::Playlist(PlaylistBackend* backend, TaskManager* task_manager, LibraryBackend* library, int id, const QString& special_type, bool favorite, QObject* parent) @@ -1246,14 +1259,16 @@ QMimeData* Playlist::mimeData(const QModelIndexList& indexes) const { bool Playlist::CompareItems(int column, Qt::SortOrder order, shared_ptr _a, - shared_ptr _b) { + shared_ptr _b, + const QStringList& prefixes) { shared_ptr a = order == Qt::AscendingOrder ? _a : _b; shared_ptr b = order == Qt::AscendingOrder ? _b : _a; #define cmp(field) return a->Metadata().field() < b->Metadata().field() #define strcmp(field) \ - return QString::localeAwareCompare(a->Metadata().field().toLower(), \ - b->Metadata().field().toLower()) < 0; + return QString::localeAwareCompare( \ + removePrefix(a->Metadata().field().toLower(), prefixes), \ + removePrefix(b->Metadata().field().toLower(), prefixes)) < 0; switch (column) { case Column_Title: @@ -1431,25 +1446,44 @@ void Playlist::sort(int column, Qt::SortOrder order) { if (dynamic_playlist_ && current_item_index_.isValid()) begin += current_item_index_.row() + 1; + QSettings s; + s.beginGroup(Playlist::kSettingsGroup); + QStringList prefixes; + if ((column == Column_Album || column == Column_Artist || + column == Column_Title) && + s.value(Playlist::kSortIgnorePrefix, false).toBool()) { + prefixes = s.value(Playlist::kSortIgnorePrefixList, QString()) + .toString() + .split(','); + for (QString& prefix : prefixes) { + prefix = prefix.trimmed() + ' '; + } + } + s.endGroup(); + if (column == Column_Album) { // When sorting by album, also take into account discs and tracks. - qStableSort(begin, new_items.end(), std::bind(&Playlist::CompareItems, - Column_Track, order, _1, _2)); qStableSort(begin, new_items.end(), - std::bind(&Playlist::CompareItems, Column_Disc, order, _1, _2)); - qStableSort(begin, new_items.end(), std::bind(&Playlist::CompareItems, - Column_Album, order, _1, _2)); + std::bind(&Playlist::CompareItems, Column_Track, order, _1, _2, + prefixes)); + qStableSort(begin, new_items.end(), + std::bind(&Playlist::CompareItems, Column_Disc, order, _1, _2, + prefixes)); + qStableSort(begin, new_items.end(), + std::bind(&Playlist::CompareItems, Column_Album, order, _1, _2, + prefixes)); } else if (column == Column_Filename) { // When sorting by full paths we also expect a hierarchical order. This // returns a breath-first ordering of paths. - qStableSort( - begin, new_items.end(), - std::bind(&Playlist::CompareItems, Column_Filename, order, _1, _2)); + qStableSort(begin, new_items.end(), + std::bind(&Playlist::CompareItems, Column_Filename, order, _1, + _2, prefixes)); qStableSort(begin, new_items.end(), std::bind(&Playlist::ComparePathDepths, order, _1, _2)); } else { - qStableSort(begin, new_items.end(), - std::bind(&Playlist::CompareItems, column, order, _1, _2)); + qStableSort( + begin, new_items.end(), + std::bind(&Playlist::CompareItems, column, order, _1, _2, prefixes)); } undo_stack_->push( diff --git a/src/playlist/playlist.h b/src/playlist/playlist.h index ed2041040..0899238e6 100644 --- a/src/playlist/playlist.h +++ b/src/playlist/playlist.h @@ -37,6 +37,7 @@ class TaskManager; class QSortFilterProxyModel; class QUndoStack; +class QStringList; namespace PlaylistUndoCommands { class InsertItems; @@ -157,6 +158,8 @@ class Playlist : public QAbstractListModel { static const char* kPathType; static const char* kWriteMetadata; + static const char* kSortIgnorePrefix; + static const char* kSortIgnorePrefixList; static const int kUndoStackSize; static const int kUndoItemLimit; @@ -165,7 +168,7 @@ class Playlist : public QAbstractListModel { static const qint64 kMaxScrobblePointNsecs; static bool CompareItems(int column, Qt::SortOrder order, PlaylistItemPtr a, - PlaylistItemPtr b); + PlaylistItemPtr b, const QStringList& prefixes = {}); static QString column_name(Column column); static QString abbreviated_column_name(Column column); diff --git a/src/ui/behavioursettingspage.cpp b/src/ui/behavioursettingspage.cpp index 6b6581d80..a2df195ba 100644 --- a/src/ui/behavioursettingspage.cpp +++ b/src/ui/behavioursettingspage.cpp @@ -201,6 +201,12 @@ void BehaviourSettingsPage::Load() { } ui_->b_write_metadata->setChecked( s.value(Playlist::kWriteMetadata, true).toBool()); + + ui_->sort_ignore_prefix->setChecked( + s.value(Playlist::kSortIgnorePrefix, true).toBool()); + ui_->sort_ignore_prefix_list->setText( + s.value(Playlist::kSortIgnorePrefixList, QStringLiteral("a, the")) + .toString()); s.endGroup(); s.beginGroup(PlaylistTabBar::kSettingsGroup); @@ -281,6 +287,9 @@ void BehaviourSettingsPage::Save() { s.setValue("click_edit_inline", ui_->b_click_edit_inline_->isChecked()); s.setValue(Playlist::kPathType, static_cast(path)); s.setValue(Playlist::kWriteMetadata, ui_->b_write_metadata->isChecked()); + s.setValue(Playlist::kSortIgnorePrefix, ui_->sort_ignore_prefix->isChecked()); + s.setValue(Playlist::kSortIgnorePrefixList, + ui_->sort_ignore_prefix_list->text()); s.endGroup(); s.beginGroup(PlaylistTabBar::kSettingsGroup); diff --git a/src/ui/behavioursettingspage.ui b/src/ui/behavioursettingspage.ui index 2307a2d90..88b42e77a 100644 --- a/src/ui/behavioursettingspage.ui +++ b/src/ui/behavioursettingspage.ui @@ -405,6 +405,29 @@ + + + + When sorting artists, albums and titles + + + + + + Ignore prefix word(s) + + + + + + + Comma seperated list of prefix words to ignore when sorting + + + + + + From 623a5368129ea64f23d344e0d6c23bf118cc454a Mon Sep 17 00:00:00 2001 From: eclipseo <30413512+eclipseo@users.noreply.github.com> Date: Mon, 22 Oct 2018 17:44:59 +0200 Subject: [PATCH 068/104] Use qt5 version of system-wide libraries (#6181) --- CMakeLists.txt | 12 ++++++------ src/CMakeLists.txt | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b5091484..bf64dd4f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -329,9 +329,9 @@ include_directories("3rdparty/qsqlite") # to system installed qtsingleapplication instead. option(USE_SYSTEM_QTSINGLEAPPLICATION "Don't set this option unless your system QtSingleApplication library has been compiled with the Clementine patches in 3rdparty" OFF) if(USE_SYSTEM_QTSINGLEAPPLICATION) - find_path(QTSINGLEAPPLICATION_INCLUDE_DIRS qtsingleapplication.h PATH_SUFFIXES QtSolutions) - find_library(QTSINGLEAPPLICATION_LIBRARIES QtSolutions_SingleApplication-2.6) - find_library(QTSINGLECOREAPPLICATION_LIBRARIES QtSolutions_SingleCoreApplication-2.6) + find_path(QTSINGLEAPPLICATION_INCLUDE_DIRS qtsingleapplication.h PATH_SUFFIXES qt5/QtSolutions) + find_library(QTSINGLEAPPLICATION_LIBRARIES Qt5Solutions_SingleApplication-2.6) + find_library(QTSINGLECOREAPPLICATION_LIBRARIES Qt5Solutions_SingleCoreApplication-2.6) else(USE_SYSTEM_QTSINGLEAPPLICATION) add_subdirectory(3rdparty/qtsingleapplication) set(QTSINGLEAPPLICATION_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/qtsingleapplication) @@ -352,11 +352,11 @@ endif(NOT QTIOCOMPRESSOR_INCLUDE_DIRS OR NOT QTIOCOMPRESSOR_LIBRARIES) # used to link to system installed qxt instead. option(USE_SYSTEM_QXT "Don't set this option unless your system Qxt library has been compiled with the Clementine patches in 3rdparty" OFF) if (USE_SYSTEM_QXT) - find_path(QXTCORE_INCLUDE_DIRS qxtglobal.h PATH_SUFFIXES QxtCore) - find_path(QXTGUI_INCLUDE_DIRS qxtglobalshortcut.h PATH_SUFFIXES QxtGui) + find_path(QXTCORE_INCLUDE_DIRS qxtglobal.h PATH_SUFFIXES qt5/QxtCore) + find_path(QXTGUI_INCLUDE_DIRS qxtglobalshortcut.h PATH_SUFFIXES qt5/QxtWidgets) set(QXT_INCLUDE_DIRS ${QXTCORE_INCLUDE_DIRS} ${QXTGUI_INCLUDE_DIRS}) # We only need its header. We don't need to link to QxtCore. - find_library(QXT_LIBRARIES QxtGui) + find_library(QXT_LIBRARIES QxtWidgets-qt5) else (USE_SYSTEM_QXT) add_definitions(-DQXT_STATIC -DBUILD_QXT_GUI -DBUILD_QXT_CORE) set(QXT_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/qxt) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 81de7b348..2fdde62c4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1238,6 +1238,7 @@ target_link_libraries(clementine_lib ${GSTREAMER_TAG_LIBRARIES} ${GSTREAMER_PBUTILS_LIBRARIES} ${QTSINGLEAPPLICATION_LIBRARIES} + ${QTSINGLECOREAPPLICATION_LIBRARIES} ${QTIOCOMPRESSOR_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${SQLITE_LIBRARIES} From 8c198a99a5eb3d81599552fb9b2ac958debffb6e Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Sat, 17 Nov 2018 15:08:37 +0100 Subject: [PATCH 069/104] Qt 5 fixes --- 3rdparty/libmygpo-qt5/src/CMakeLists.txt | 5 +- 3rdparty/qocoa/qbutton_mac.mm | 8 +- 3rdparty/qocoa/qocoa_mac.h | 6 +- 3rdparty/qtiocompressor/qtiocompressor.h | 2 +- 3rdparty/qtsingleapplication/qtlocalpeer.cpp | 6 +- 3rdparty/qtsingleapplication/qtlocalpeer.h | 2 +- 3rdparty/qtsingleapplication/qtlockedfile.h | 6 +- .../qtsingleapplication/qtlockedfile_win.cpp | 10 +- .../qtsingleapplication.cpp | 41 ---- .../qtsingleapplication/qtsingleapplication.h | 7 +- 3rdparty/qtwin/CMakeLists.txt | 13 - 3rdparty/qtwin/qtwin.cpp | 229 ------------------ 3rdparty/qtwin/qtwin.h | 38 --- 3rdparty/qxt/qxtglobalshortcut.cpp | 12 +- 3rdparty/qxt/qxtglobalshortcut_p.h | 4 +- 3rdparty/tinysvcmdns/CMakeLists.txt | 2 +- CMakeLists.txt | 138 +++++++---- debian/compat | 2 +- debian/control | 56 ++--- debian/copyright | 6 - dist/clementine.spec.in | 58 ++++- ext/libclementine-common/core/workerpool.h | 4 +- src/CMakeLists.txt | 147 ++++++----- src/analyzers/analyzerbase.h | 2 +- src/config.h.in | 6 + src/core/globalshortcuts.cpp | 7 +- src/core/gnomeglobalshortcutbackend.cpp | 17 +- src/core/metatypes.cpp | 4 +- src/covers/albumcoverloader.cpp | 14 +- src/covers/albumcoverloader.h | 3 + src/devices/deviceview.cpp | 4 +- src/devices/macdevicelister.mm | 45 ++-- src/engines/gstenginepipeline.cpp | 14 +- src/internet/core/internetmodel.cpp | 6 +- src/internet/spotify/spotifyservice.cpp | 4 +- src/main.cpp | 27 ++- src/musicbrainz/chromaprinter.cpp | 4 + src/playlist/playlistdelegates.cpp | 10 +- src/playlist/playlistdelegates.h | 2 +- src/playlist/playlistview.cpp | 4 +- src/playlist/playlistview.h | 2 +- src/songinfo/artistinfoview.cpp | 6 +- src/ui/mainwindow.cpp | 2 +- src/ui/settingsdialog.cpp | 7 +- src/ui/windows7thumbbar.cpp | 10 +- src/widgets/groupediconview.cpp | 4 +- src/widgets/osd.cpp | 6 +- src/widgets/osd.h | 5 +- src/widgets/osdpretty.cpp | 11 +- tests/main.cpp | 2 +- 50 files changed, 429 insertions(+), 601 deletions(-) delete mode 100644 3rdparty/qtwin/CMakeLists.txt delete mode 100644 3rdparty/qtwin/qtwin.cpp delete mode 100644 3rdparty/qtwin/qtwin.h diff --git a/3rdparty/libmygpo-qt5/src/CMakeLists.txt b/3rdparty/libmygpo-qt5/src/CMakeLists.txt index 47f4ea2c5..c15771c3e 100644 --- a/3rdparty/libmygpo-qt5/src/CMakeLists.txt +++ b/3rdparty/libmygpo-qt5/src/CMakeLists.txt @@ -3,9 +3,8 @@ set( MYGPO_QT_VERSION_MAJOR "1" ) set( MYGPO_QT_VERSION_MINOR "0" ) set( MYGPO_QT_VERSION_PATCH "9" ) configure_file( Version.h.in ${CMAKE_CURRENT_BINARY_DIR}/Version.h ) -include_directories("${QJSON_INCLUDEDIR}/qjson") -include_directories( ${QJSON_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) +include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) set ( LIBMYGPO_QT_SRC Config.cpp @@ -86,4 +85,4 @@ QT_WRAP_CPP(LIBMYGPO_QT_MOC_SRC ${LIBMYGPO_QT_MOC_H} ) add_library( ${MYGPO_QT_TARGET_NAME} STATIC ${LIBMYGPO_QT_SRC} ${LIBMYGPO_QT_MOC_SRC} ) target_link_libraries( ${MYGPO_QT_TARGET_NAME} ${QJSON_LIBRARIES} ${QT_QTCORE_LIBRARY} ${QT_QTNETWORK_LIBRARY} ) -qt5_use_modules( ${MYGPO_QT_TARGET_NAME} Core Network ) +target_link_libraries( ${MYGPO_QT_TARGET_NAME} Qt5::Core Qt5::Network ) diff --git a/3rdparty/qocoa/qbutton_mac.mm b/3rdparty/qocoa/qbutton_mac.mm index 93f7c7c8b..b7e1bc0c5 100644 --- a/3rdparty/qocoa/qbutton_mac.mm +++ b/3rdparty/qocoa/qbutton_mac.mm @@ -37,7 +37,9 @@ public: switch(bezelStyle) { case QButton::Disclosure: case QButton::Circular: +#ifdef __MAC_10_7 case QButton::Inline: +#endif case QButton::RoundedDisclosure: case QButton::HelpButton: [nsButton setTitle:@""]; @@ -55,7 +57,7 @@ public: font = [NSFont fontWithName:@"Lucida Grande Bold" size:12]; break; -#ifdef MAC_OS_X_VERSION_10_7 +#ifdef __MAC_10_7 case QButton::Inline: font = [NSFont boldSystemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]; break; @@ -112,7 +114,7 @@ public: qButton->setFixedHeight(22); qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); break; -#ifdef MAC_OS_X_VERSION_10_7 +#ifdef __MAC_10_7 case QButton::Inline: qButton->setMinimumWidth(10); qButton->setFixedHeight(16); @@ -130,7 +132,7 @@ public: [nsButton setButtonType:NSMomentaryPushInButton]; } - [nsButton setBezelStyle:bezelStyle]; + [nsButton setBezelStyle:(__bridge NSBezelStyle)bezelStyle]; } void clicked() diff --git a/3rdparty/qocoa/qocoa_mac.h b/3rdparty/qocoa/qocoa_mac.h index ced431173..f93a56b9d 100644 --- a/3rdparty/qocoa/qocoa_mac.h +++ b/3rdparty/qocoa/qocoa_mac.h @@ -20,9 +20,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include #include #include #include +#include #include static inline NSString* fromQString(const QString &string) @@ -41,11 +43,11 @@ static inline QString toQString(NSString *string) static inline NSImage* fromQPixmap(const QPixmap &pixmap) { - CGImageRef cgImage = pixmap.toMacCGImageRef(); + CGImageRef cgImage = QtMac::toCGImageRef(pixmap); return [[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize]; } -static inline void setupLayout(void *cocoaView, QWidget *parent) +static inline void setupLayout(NSView *cocoaView, QWidget *parent) { parent->setAttribute(Qt::WA_NativeWindow); QVBoxLayout *layout = new QVBoxLayout(parent); diff --git a/3rdparty/qtiocompressor/qtiocompressor.h b/3rdparty/qtiocompressor/qtiocompressor.h index 61284a5dc..eea9b6dfa 100644 --- a/3rdparty/qtiocompressor/qtiocompressor.h +++ b/3rdparty/qtiocompressor/qtiocompressor.h @@ -49,7 +49,7 @@ #include -#if defined(Q_WS_WIN) +#if defined(Q_OS_WIN) # if !defined(QT_QTIOCOMPRESSOR_EXPORT) && !defined(QT_QTIOCOMPRESSOR_IMPORT) # define QT_QTIOCOMPRESSOR_EXPORT # elif defined(QT_QTIOCOMPRESSOR_IMPORT) diff --git a/3rdparty/qtsingleapplication/qtlocalpeer.cpp b/3rdparty/qtsingleapplication/qtlocalpeer.cpp index 837752b63..4b2fac915 100644 --- a/3rdparty/qtsingleapplication/qtlocalpeer.cpp +++ b/3rdparty/qtsingleapplication/qtlocalpeer.cpp @@ -54,14 +54,12 @@ static PProcessIdToSessionId pProcessIdToSessionId = 0; #include #endif -namespace QtLP_Private { #include "qtlockedfile.cpp" #if defined(Q_OS_WIN) #include "qtlockedfile_win.cpp" #else #include "qtlockedfile_unix.cpp" #endif -} const char* QtLocalPeer::ack = "ack"; @@ -113,7 +111,7 @@ bool QtLocalPeer::isClient() if (lockFile.isLocked()) return false; - if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) + if (!lockFile.lock(QtLockedFile::WriteLock, false)) return true; bool res = server->listen(socketName); @@ -149,7 +147,7 @@ bool QtLocalPeer::sendMessage(const QString &message, int timeout) Sleep(DWORD(ms)); #else struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; - nanosleep(&ts, NULL); + nanosleep(&ts, nullptr); #endif } if (!connOk) diff --git a/3rdparty/qtsingleapplication/qtlocalpeer.h b/3rdparty/qtsingleapplication/qtlocalpeer.h index 7b3fa8159..bd25f137a 100644 --- a/3rdparty/qtsingleapplication/qtlocalpeer.h +++ b/3rdparty/qtsingleapplication/qtlocalpeer.h @@ -67,7 +67,7 @@ protected: QString id; QString socketName; QLocalServer* server; - QtLP_Private::QtLockedFile lockFile; + QtLockedFile lockFile; private: static const char* ack; diff --git a/3rdparty/qtsingleapplication/qtlockedfile.h b/3rdparty/qtsingleapplication/qtlockedfile.h index 2af3e3ea2..37e013ec1 100644 --- a/3rdparty/qtsingleapplication/qtlockedfile.h +++ b/3rdparty/qtsingleapplication/qtlockedfile.h @@ -45,7 +45,7 @@ #include #endif -#if defined(Q_WS_WIN) || defined(Q_OS_WIN) +#if defined(Q_OS_WIN) # if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) # define QT_QTLOCKEDFILE_EXPORT # elif defined(QT_QTLOCKEDFILE_IMPORT) @@ -61,8 +61,6 @@ # define QT_QTLOCKEDFILE_EXPORT #endif -namespace QtLP_Private { - class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile { public: @@ -92,5 +90,5 @@ private: #endif LockMode m_lock_mode; }; -} + #endif diff --git a/3rdparty/qtsingleapplication/qtlockedfile_win.cpp b/3rdparty/qtsingleapplication/qtlockedfile_win.cpp index ed2995f3f..737a23f86 100644 --- a/3rdparty/qtsingleapplication/qtlockedfile_win.cpp +++ b/3rdparty/qtsingleapplication/qtlockedfile_win.cpp @@ -59,10 +59,10 @@ Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) Qt::HANDLE mutex; if (doCreate) { #if (QT_VERSION < 0x050000) - QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); }, - { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } ); + QT_WA( { mutex = CreateMutexW(nullptr, FALSE, (WCHAR*)mname.utf16()); }, + { mutex = CreateMutexA(nullptr, FALSE, mname.toLocal8Bit().constData()); } ); #else - mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); + mutex = CreateMutexW(nullptr, FALSE, (WCHAR*)mname.utf16()); #endif if (!mutex) { qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); @@ -71,10 +71,10 @@ Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) } else { #if (QT_VERSION < 0x050000) - QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); }, + QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (WCHAR*)mname.utf16()); }, { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } ); #else - mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); + mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (WCHAR*)mname.utf16()); #endif if (!mutex) { if (GetLastError() != ERROR_FILE_NOT_FOUND) diff --git a/3rdparty/qtsingleapplication/qtsingleapplication.cpp b/3rdparty/qtsingleapplication/qtsingleapplication.cpp index 48c2e45f2..a28074a93 100644 --- a/3rdparty/qtsingleapplication/qtsingleapplication.cpp +++ b/3rdparty/qtsingleapplication/qtsingleapplication.cpp @@ -169,47 +169,6 @@ QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char * } -#if defined(Q_WS_X11) -/*! - Special constructor for X11, ref. the documentation of - QApplication's corresponding constructor. The application identifier - will be QCoreApplication::applicationFilePath(). \a dpy, \a visual, - and \a cmap are passed on to the QApplication constructor. -*/ -QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, visual, cmap) -{ - sysInit(); -} - -/*! - Special constructor for X11, ref. the documentation of - QApplication's corresponding constructor. The application identifier - will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a - argv, \a visual, and \a cmap are passed on to the QApplication - constructor. -*/ -QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, argc, argv, visual, cmap) -{ - sysInit(); -} - -/*! - Special constructor for X11, ref. the documentation of - QApplication's corresponding constructor. The application identifier - will be \a appId. \a dpy, \a argc, \a - argv, \a visual, and \a cmap are passed on to the QApplication - constructor. -*/ -QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) - : QApplication(dpy, argc, argv, visual, cmap) -{ - sysInit(appId); -} -#endif - - /*! Returns true if another instance of this application is running; otherwise false. diff --git a/3rdparty/qtsingleapplication/qtsingleapplication.h b/3rdparty/qtsingleapplication/qtsingleapplication.h index 42e977281..5d2ae46f3 100644 --- a/3rdparty/qtsingleapplication/qtsingleapplication.h +++ b/3rdparty/qtsingleapplication/qtsingleapplication.h @@ -44,7 +44,7 @@ class QtLocalPeer; -#if defined(Q_WS_WIN) || defined(Q_OS_WIN32) +#if defined(Q_OS_WIN) || defined(Q_OS_WIN32) # if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) # define QT_QTSINGLEAPPLICATION_EXPORT # elif defined(QT_QTSINGLEAPPLICATION_IMPORT) @@ -67,11 +67,6 @@ class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication public: QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); QtSingleApplication(const QString &id, int &argc, char **argv); -#if defined(Q_WS_X11) - QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); - QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); - QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); -#endif bool isRunning(); QString id() const; diff --git a/3rdparty/qtwin/CMakeLists.txt b/3rdparty/qtwin/CMakeLists.txt deleted file mode 100644 index 9122be354..000000000 --- a/3rdparty/qtwin/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -cmake_minimum_required(VERSION 2.8.11) - -set(QTWIN-SOURCES - qtwin.cpp -) - -ADD_LIBRARY(qtwin STATIC - ${QTWIN-SOURCES} -) - -target_link_libraries(qtwin - Qt5::Widgets -) diff --git a/3rdparty/qtwin/qtwin.cpp b/3rdparty/qtwin/qtwin.cpp deleted file mode 100644 index 69a24a9d5..000000000 --- a/3rdparty/qtwin/qtwin.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Use, modification and distribution is allowed without limitation, -** warranty, liability or support of any kind. -** -****************************************************************************/ - -#include "qtwin.h" -#include -#include -#include -#include -#include - -#ifdef Q_WS_WIN - -#include - -// Blur behind data structures -#define DWM_BB_ENABLE 0x00000001 // fEnable has been specified -#define DWM_BB_BLURREGION 0x00000002 // hRgnBlur has been specified -#define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004 // fTransitionOnMaximized has been specified -#define WM_DWMCOMPOSITIONCHANGED 0x031E // Composition changed window message - -typedef struct _DWM_BLURBEHIND -{ - DWORD dwFlags; - BOOL fEnable; - HRGN hRgnBlur; - BOOL fTransitionOnMaximized; -} DWM_BLURBEHIND, *PDWM_BLURBEHIND; - -typedef struct _MARGINS -{ - int cxLeftWidth; - int cxRightWidth; - int cyTopHeight; - int cyBottomHeight; -} MARGINS, *PMARGINS; - -typedef HRESULT (WINAPI *PtrDwmIsCompositionEnabled)(BOOL* pfEnabled); -typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS* pMarInset); -typedef HRESULT (WINAPI *PtrDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind); -typedef HRESULT (WINAPI *PtrDwmGetColorizationColor)(DWORD *pcrColorization, BOOL *pfOpaqueBlend); - -static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0; -static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0; -static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0; -static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0; - - -/* - * Internal helper class that notifies windows if the - * DWM compositing state changes and updates the widget - * flags correspondingly. - */ -class WindowNotifier : public QWidget -{ -public: - WindowNotifier() { winId(); } - void addWidget(QWidget *widget) { widgets.append(widget); } - void removeWidget(QWidget *widget) { widgets.removeAll(widget); } - bool winEvent(MSG *message, long *result); - -private: - QWidgetList widgets; -}; - -static bool resolveLibs() -{ - if (!pDwmIsCompositionEnabled) { - QLibrary dwmLib(QString::fromAscii("dwmapi")); - pDwmIsCompositionEnabled =(PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled"); - pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea"); - pDwmEnableBlurBehindWindow = (PtrDwmEnableBlurBehindWindow)dwmLib.resolve("DwmEnableBlurBehindWindow"); - pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor"); - } - return pDwmIsCompositionEnabled != 0; -} - -#endif - -/*! - * Chekcs and returns true if Windows DWM composition - * is currently enabled on the system. - * - * To get live notification on the availability of - * this feature, you will currently have to - * reimplement winEvent() on your widget and listen - * for the WM_DWMCOMPOSITIONCHANGED event to occur. - * - */ -bool QtWin::isCompositionEnabled() -{ -#ifdef Q_WS_WIN - if (resolveLibs()) { - HRESULT hr = S_OK; - BOOL isEnabled = false; - hr = pDwmIsCompositionEnabled(&isEnabled); - if (SUCCEEDED(hr)) - return isEnabled; - } -#endif - return false; -} - -/*! - * Enables Blur behind on a Widget. - * - * \a enable tells if the blur should be enabled or not - */ -bool QtWin::enableBlurBehindWindow(QWidget *widget, bool enable, - const QRegion ®ion) -{ - Q_ASSERT(widget); - bool result = false; -#ifdef Q_WS_WIN - if (resolveLibs()) { - DWM_BLURBEHIND bb = {0}; - HRESULT hr = S_OK; - bb.fEnable = enable; - bb.dwFlags = DWM_BB_ENABLE; - bb.hRgnBlur = NULL; - - if (!region.isEmpty()) { - bb.dwFlags |= DWM_BB_BLURREGION; - bb.hRgnBlur = region.handle(); - } - - widget->setAttribute(Qt::WA_TranslucentBackground, enable); - widget->setAttribute(Qt::WA_NoSystemBackground, enable); - hr = pDwmEnableBlurBehindWindow(widget->winId(), &bb); - if (SUCCEEDED(hr)) { - result = true; - windowNotifier()->addWidget(widget); - } - } -#endif - return result; -} - -/*! - * ExtendFrameIntoClientArea. - * - * This controls the rendering of the frame inside the window. - * Note that passing margins of -1 (the default value) will completely - * remove the frame from the window. - * - * \note you should not call enableBlurBehindWindow before calling - * this functions - * - * \a enable tells if the blur should be enabled or not - */ -bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom) -{ - - Q_ASSERT(widget); - Q_UNUSED(left); - Q_UNUSED(top); - Q_UNUSED(right); - Q_UNUSED(bottom); - - bool result = false; -#ifdef Q_WS_WIN - if (resolveLibs()) { - QLibrary dwmLib(QString::fromAscii("dwmapi")); - HRESULT hr = S_OK; - MARGINS m = {left, top, right, bottom}; - hr = pDwmExtendFrameIntoClientArea(widget->winId(), &m); - if (SUCCEEDED(hr)) { - result = true; - windowNotifier()->addWidget(widget); - } - widget->setAttribute(Qt::WA_TranslucentBackground, result); - } -#endif - return result; -} - -/*! - * Returns the current colorizationColor for the window. - * - * \a enable tells if the blur should be enabled or not - */ -QColor QtWin::colorizatinColor() -{ - QColor resultColor = QApplication::palette().window().color(); - -#ifdef Q_WS_WIN - if (resolveLibs()) { - DWORD color = 0; - BOOL opaque = FALSE; - QLibrary dwmLib(QString::fromAscii("dwmapi")); - HRESULT hr = S_OK; - hr = pDwmGetColorizationColor(&color, &opaque); - if (SUCCEEDED(hr)) - resultColor = QColor(color); - } -#endif - return resultColor; -} - -#ifdef Q_WS_WIN -WindowNotifier *QtWin::windowNotifier() -{ - static WindowNotifier *windowNotifierInstance = 0; - if (!windowNotifierInstance) - windowNotifierInstance = new WindowNotifier; - return windowNotifierInstance; -} - - -/* Notify all enabled windows that the DWM state changed */ -bool WindowNotifier::winEvent(MSG *message, long *result) -{ - if (message && message->message == WM_DWMCOMPOSITIONCHANGED) { - bool compositionEnabled = QtWin::isCompositionEnabled(); - foreach(QWidget * widget, widgets) { - if (widget) { - widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled); - } - widget->update(); - } - } - return QWidget::winEvent(message, result); -} -#endif diff --git a/3rdparty/qtwin/qtwin.h b/3rdparty/qtwin/qtwin.h deleted file mode 100644 index a40185853..000000000 --- a/3rdparty/qtwin/qtwin.h +++ /dev/null @@ -1,38 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Use, modification and distribution is allowed without limitation, -** warranty, liability or support of any kind. -** -****************************************************************************/ - -#ifndef QTWIN_H -#define QTWIN_H - -#include -#include -/** - * This is a helper class for using the Desktop Window Manager - * functionality on Windows 7 and Windows Vista. On other platforms - * these functions will simply not do anything. - */ - -class WindowNotifier; - -class QtWin -{ -public: - static bool enableBlurBehindWindow(QWidget *widget, bool enable = true, - const QRegion& region = QRegion()); - static bool extendFrameIntoClientArea(QWidget *widget, - int left = -1, int top = -1, - int right = -1, int bottom = -1); - static bool isCompositionEnabled(); - static QColor colorizatinColor(); - -private: - static WindowNotifier *windowNotifier(); -}; - -#endif // QTWIN_H diff --git a/3rdparty/qxt/qxtglobalshortcut.cpp b/3rdparty/qxt/qxtglobalshortcut.cpp index 6ea380ca7..db483060e 100644 --- a/3rdparty/qxt/qxtglobalshortcut.cpp +++ b/3rdparty/qxt/qxtglobalshortcut.cpp @@ -34,36 +34,36 @@ #include bool QxtGlobalShortcutPrivate::error = false; -#ifndef Q_WS_MAC +#ifndef Q_OS_MAC int QxtGlobalShortcutPrivate::ref = 0; #if QT_VERSION < QT_VERSION_CHECK(5,0,0) QAbstractEventDispatcher::EventFilter QxtGlobalShortcutPrivate::prevEventFilter = 0; #endif -#endif // Q_WS_MAC +#endif // Q_OS_MAC QHash, QxtGlobalShortcut*> QxtGlobalShortcutPrivate::shortcuts; QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate() : enabled(true), key(Qt::Key(0)), mods(Qt::NoModifier) { -#ifndef Q_WS_MAC +#ifndef Q_OS_MAC if (!ref++) #if QT_VERSION < QT_VERSION_CHECK(5,0,0) prevEventFilter = QAbstractEventDispatcher::instance()->setEventFilter(eventFilter); #else QAbstractEventDispatcher::instance()->installNativeEventFilter(this); #endif -#endif // Q_WS_MAC +#endif // Q_OS_MAC } QxtGlobalShortcutPrivate::~QxtGlobalShortcutPrivate() { -#ifndef Q_WS_MAC +#ifndef Q_OS_MAC if (!--ref) #if QT_VERSION < QT_VERSION_CHECK(5,0,0) QAbstractEventDispatcher::instance()->setEventFilter(prevEventFilter); #else QAbstractEventDispatcher::instance()->removeNativeEventFilter(this); #endif -#endif // Q_WS_MAC +#endif // Q_OS_MAC } bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut) diff --git a/3rdparty/qxt/qxtglobalshortcut_p.h b/3rdparty/qxt/qxtglobalshortcut_p.h index 1a788852e..14088c457 100644 --- a/3rdparty/qxt/qxtglobalshortcut_p.h +++ b/3rdparty/qxt/qxtglobalshortcut_p.h @@ -59,7 +59,7 @@ public: bool unsetShortcut(); static bool error; -#ifndef Q_WS_MAC +#ifndef Q_OS_MAC static int ref; #if QT_VERSION < QT_VERSION_CHECK(5,0,0) static QAbstractEventDispatcher::EventFilter prevEventFilter; @@ -67,7 +67,7 @@ public: #else virtual bool nativeEventFilter(const QByteArray & eventType, void * message, long * result); #endif // QT_VERSION < QT_VERSION_CHECK(5,0,0) -#endif // Q_WS_MAC +#endif // Q_OS_MAC static void activateShortcut(quint32 nativeKey, quint32 nativeMods); diff --git a/3rdparty/tinysvcmdns/CMakeLists.txt b/3rdparty/tinysvcmdns/CMakeLists.txt index 1c16a138a..50dd1f573 100644 --- a/3rdparty/tinysvcmdns/CMakeLists.txt +++ b/3rdparty/tinysvcmdns/CMakeLists.txt @@ -7,7 +7,7 @@ set(TINYSVCMDNS-SOURCES ) find_library(PTHREAD - pthreadGC2 + pthread ) add_library(tinysvcmdns STATIC diff --git a/CMakeLists.txt b/CMakeLists.txt index c1de26e3e..acd25175a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,20 +28,12 @@ if (CCACHE_EXECUTABLE) SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_EXECUTABLE}) endif () -if (UNIX AND NOT APPLE) - set(LINUX 1) -endif (UNIX AND NOT APPLE) - -set(QT_MIN_VERSION 5.6.0) - -find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core OpenGL Sql Network Xml Widgets Concurrent Test) -find_package(X11) -if(X11_FOUND) - find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS X11Extras) +if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + set(LINUX ON) +endif() +if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") + set(FREEBSD ON) endif() - -find_package(Qt5LinguistTools CONFIG REQUIRED) -set(QT_LCONVERT_EXECUTABLE Qt5::lconvert) if(APPLE) if(NOT QT_MAC_USE_COCOA) @@ -56,10 +48,22 @@ find_package(Gettext REQUIRED) find_package(PkgConfig REQUIRED) find_package(Protobuf REQUIRED) find_package(FFTW3) -find_package(ALSA) +if(LINUX) + find_package(ALSA REQUIRED) + pkg_check_modules(DBUS REQUIRED dbus-1) +else(LINUX) + find_package(ALSA) + pkg_check_modules(DBUS dbus-1) +endif(LINUX) if(ALSA_FOUND) set(HAVE_ALSA ON) endif() +if (NOT APPLE) + find_package(X11) +endif() +if(X11_FOUND) + set(HAVE_X11 ON) +endif() find_library(PROTOBUF_STATIC_LIBRARY libprotobuf.a libprotobuf) @@ -80,7 +84,7 @@ pkg_check_modules(LIBMTP libmtp>=1.0) pkg_check_modules(LIBMYGPO_QT5 libmygpo-qt5>=1.0.9) pkg_check_modules(LIBPULSE libpulse) pkg_check_modules(LIBXML libxml-2.0) -pkg_check_modules(SPOTIFY libspotify>=12.1.45) +pkg_check_modules(LIBSPOTIFY libspotify>=12.1.45) pkg_check_modules(TAGLIB taglib) if (WIN32) @@ -94,6 +98,44 @@ find_path(LASTFM51_INCLUDE_DIRS lastfm5/Track.h) find_path(SPARSEHASH_INCLUDE_DIRS google/sparsetable) +# QT +set(QT_MIN_VERSION 5.6.0) +find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Concurrent Widgets Network Sql Xml OpenGL Test) +if(X11_FOUND) + find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS X11Extras) +endif() +if(DBUS_FOUND) + find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS DBus) + get_target_property(QT_DBUSXML2CPP_EXECUTABLE Qt5::qdbusxml2cpp LOCATION) +endif() +if(APPLE) + find_package(Qt5 REQUIRED COMPONENTS MacExtras) +endif() +if(WIN32) + find_package(Qt5 REQUIRED COMPONENTS WinExtras) +endif() + +set(QT_LIBRARIES Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network Qt5::Sql Qt5::Xml Qt5::OpenGL Qt5::Test) + +if(DBUS_FOUND) + set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::DBus) +endif() +if(X11_FOUND) + set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::X11Extras) +endif() +if(APPLE) + set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::MacExtras) +endif() +if(WIN32) + set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::WinExtras) +endif() + +find_package(Qt5LinguistTools CONFIG) +if (Qt5LinguistTools_FOUND) + set(QT_LCONVERT_EXECUTABLE Qt5::lconvert) +endif() + + # Only use system taglib if it's greater than 1.11.1 # There is a bug in version 1.11.1 corrupting Ogg files, see: https://github.com/taglib/taglib/issues/864 # If you decide to use the systems taglib, make sure it has been patched with the following commit: @@ -136,13 +178,11 @@ endif() if (APPLE) find_library(SPARKLE Sparkle) - - find_library(SPOTIFY libspotify) - if (SPOTIFY) - set (SPOTIFY_FOUND ON) - set (SPOTIFY_INCLUDE_DIRS ${SPOTIFY}) - set (SPOTIFY_LIBRARIES ${SPOTIFY}) - endif (SPOTIFY) + find_library(LIBSPOTIFY libspotify) + if(LIBSPOTIFY_FOUND) + set(LIBSPOTIFY_INCLUDE_DIRS ${LIBSPOTIFY}) + set(LIBSPOTIFY_LIBRARIES ${LIBSPOTIFY}) + endif(LIBSPOTIFY_FOUND) add_subdirectory(3rdparty/SPMediaKeyTap) set(SPMEDIAKEYTAP_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/SPMediaKeyTap) @@ -251,22 +291,31 @@ optional_component(LIBLASTFM ON "Last.fm support" ) optional_component(DBUS ON "D-Bus support" - DEPENDS "Linux" LINUX + DEPENDS "D-Bus" DBUS_FOUND ) optional_component(WIIMOTEDEV ON "Wiimote support" - DEPENDS "D-Bus support" HAVE_DBUS + DEPENDS "D-Bus support" DBUS_FOUND ) optional_component(DEVICEKIT ON "Devices: DeviceKit backend" - DEPENDS "D-Bus support" HAVE_DBUS + DEPENDS "D-Bus support" DBUS_FOUND ) optional_component(UDISKS2 ON "Devices: UDisks2 backend" - DEPENDS "D-Bus support" HAVE_DBUS + DEPENDS "D-Bus support" DBUS_FOUND +) + +if (CRYPTOPP_FOUND OR HAVE_SPOTIFY_BLOB) + set(CRYPTOPP_OR_HAVE_SPOTIFY_BLOB ON) +endif() + +optional_component(SPOTIFY ON "Spotify support" + DEPENDS "cryptopp or spotify blob" CRYPTOPP_OR_HAVE_SPOTIFY_BLOB ) optional_component(SPOTIFY_BLOB ON "Spotify support: non-GPL binary helper" + DEPENDS "spotify support" HAVE_SPOTIFY DEPENDS "protobuf" PROTOBUF_FOUND PROTOBUF_PROTOC_EXECUTABLE DEPENDS "libspotify" SPOTIFY_FOUND ) @@ -286,26 +335,22 @@ optional_component(LIBPULSE ON "Pulse audio integration" optional_component(VISUALISATIONS ON "Visualisations") -if(NOT HAVE_SPOTIFY_BLOB AND NOT CRYPTOPP_FOUND) - message(FATAL_ERROR "Either crypto++ must be available or the non-GPL Spotify " - "code must be compiled in") -elseif(CRYPTOPP_FOUND) - set(HAVE_CRYPTOPP ON) - set(HAVE_SPOTIFY_DOWNLOADER ON) +optional_component(TRANSLATIONS ON "Translations" + DEPENDS "gettext" GETTEXT_XGETTEXT_EXECUTABLE + DEPENDS "Qt5LinguistTools" Qt5LinguistTools_FOUND +) + +option(USE_BUNDLE "Bundle macos/windows dependencies" ON) +if (APPLE AND USE_BUNDLE AND NOT USE_BUNDLE_DIR) + set(USE_BUNDLE_DIR "../PlugIns") endif() -# Find DBus if it's enabled -if (HAVE_DBUS) - find_package(Qt5 COMPONENTS DBus) - get_target_property(QT_DBUSXML2CPP_EXECUTABLE Qt5::qdbusxml2cpp LOCATION) -endif () - -# We can include the Qt definitions now -if(WIN32) - set(QT_LIBRARIES Qt5::Core Qt5::OpenGL Qt5::Sql Qt5::Network Qt5::Xml Qt5::Widgets Qt5::Concurrent) -else(WIN32) - set(QT_LIBRARIES Qt5::Core Qt5::OpenGL Qt5::Sql Qt5::Network Qt5::Xml Qt5::Widgets Qt5::Concurrent Qt5::X11Extras Qt5::DBus) -endif(WIN32) +if(CRYPTOPP_FOUND) + set(HAVE_CRYPTOPP ON) + if(HAVE_SPOTIFY) + set(HAVE_SPOTIFY_DOWNLOADER ON) + endif(HAVE_SPOTIFY) +endif(CRYPTOPP_FOUND) # Remove GLU and GL from the link line - they're not really required # and don't exist on my mingw toolchain @@ -420,7 +465,6 @@ add_subdirectory(3rdparty/qocoa) # Subdirectories add_subdirectory(src) if (WIN32) - add_subdirectory(3rdparty/qtwin) add_subdirectory(3rdparty/tinysvcmdns) endif (WIN32) add_subdirectory(tests) @@ -430,7 +474,9 @@ add_subdirectory(ext/libclementine-common) add_subdirectory(ext/libclementine-tagreader) add_subdirectory(ext/clementine-tagreader) add_subdirectory(ext/libclementine-remote) -add_subdirectory(ext/libclementine-spotifyblob) +if(HAVE_SPOTIFY) + add_subdirectory(ext/libclementine-spotifyblob) +endif(HAVE_SPOTIFY) option(WITH_DEBIAN OFF) if(WITH_DEBIAN) diff --git a/debian/compat b/debian/compat index 7f8f011eb..ec635144f 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -7 +9 diff --git a/debian/control b/debian/control index d8900cce4..1885e75aa 100644 --- a/debian/control +++ b/debian/control @@ -3,41 +3,42 @@ Section: sound Priority: optional Maintainer: David Sansome Build-Depends: debhelper (>= 7), - liblastfm-dev, - libtag1-dev, - libboost1.38-dev | - libboost1.40-dev | - libboost1.42-dev | - libboost-dev, - libboost-serialization1.38-dev | - libboost-serialization1.40-dev | - libboost-serialization1.42-dev | - libboost-serialization-dev, - libcdio-cdda1, - libchromaprint-dev, - libcrypto++-dev, - libechonest-dev, - libglew1.5-dev | - libglew-dev, - libqt4-dev, - qt4-dev-tools, - libqt4-opengl-dev, + make, cmake, + gcc, + protobuf-compiler, + libglib2.0-dev, + libdbus-1-dev, + libprotobuf-dev, + libboost-dev, + libsqlite3-dev, + libasound2-dev, + libpulse-dev, + libtag1-dev, + libqt5-dev, + qt5-dev-tools, + qtbase5-dev, + qtbase5-dev-tools, + qtbase5-private-dev, + libqt5x11extras5-dev, + libqt5opengl5-dev, libgstreamer1.0-dev, libgstreamer-plugins-base1.0-dev, + libcdio-dev, libgpod-dev, + libimobiledevice-dev, + libmtp-dev, libplist-dev, libusbmuxd-dev, - libmtp-dev, - libqjson-dev, - protobuf-compiler, - libprotobuf-dev, + libchromaprint-dev, + liblastfm5-dev, + libcrypto++-dev, + libglew-dev, libfftw3-dev, libsparsehash-dev, - libsqlite3-dev, - libpulse-dev, - libmygpo-qt-dev (>= 1.0.7) -Standards-Version: 3.8.1 + libmygpo-qt-dev (>= 1.0.7), + libprojectm-dev (>= 2.0.1+dfsg-6) +Standards-Version: 3.9.8 Homepage: http://www.clementine-player.org/ Package: clementine @@ -47,6 +48,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, gstreamer1.0-plugins-base, gstreamer1.0-plugins-good, gstreamer1.0-plugins-ugly, + gstreamer1.0-alsa, gstreamer1.0-pulseaudio, libprojectm-data | projectm-data Description: Modern music player and library organiser inspired by Amarok 1.4 diff --git a/debian/copyright b/debian/copyright index 499978c1e..d2292b471 100644 --- a/debian/copyright +++ b/debian/copyright @@ -93,12 +93,6 @@ Files: 3rdparty/qtsingleapplication/* Copyright: 2009, Nokia Corporation License: Qt Commercial or LGPL-2.1 or GPL-3 -Files: 3rdparty/qtwin/* -Copyright: 2009, Nokia Corporation -License: other - Use, modification and distribution is allowed without limitation, - warranty, liability or support of any kind. - Files: 3rdparty/qxt/* Copyright: 2007, Qxt Foundation License: CPL 1.0 and/or LGPL-2.1 diff --git a/dist/clementine.spec.in b/dist/clementine.spec.in index 6e9f5434e..119608270 100644 --- a/dist/clementine.spec.in +++ b/dist/clementine.spec.in @@ -9,15 +9,52 @@ URL: http://www.clementine-player.org/ Source0: %{name}-@CLEMENTINE_VERSION_SPARKLE@.tar.xz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) -BuildRequires: desktop-file-utils liblastfm-devel taglib-devel gettext -BuildRequires: qt5-devel boost-devel gcc-c++ glew-devel libgpod-devel -BuildRequires: cmake gstreamer1-devel gstreamer1-plugins-base-devel -BuildRequires: libmtp-devel protobuf-devel protobuf-compiler libcdio-devel -BuildRequires: qjson-devel cryptopp-devel fftw-devel sparsehash-devel -BuildRequires: sqlite-devel pulseaudio-libs-devel libechonest-devel -BuildRequires: libchromaprint-devel - -Requires: libgpod protobuf-lite libcdio qjson sqlite +BuildRequires: cmake +BuildRequires: make +BuildRequires: git +BuildRequires: gettext +BuildRequires: gcc-c++ +BuildRequires: boost-devel +BuildRequires: sparsehash-devel +BuildRequires: liblastfm-qt5-devel +BuildRequires: desktop-file-utils +BuildRequires: hicolor-icon-theme +BuildRequires: libappstream-glib +BuildRequires: pkgconfig +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(gio-2.0) +BuildRequires: pkgconfig(gio-unix-2.0) +BuildRequires: pkgconfig(gthread-2.0) +BuildRequires: pkgconfig(dbus-1) +BuildRequires: pkgconfig(alsa) +BuildRequires: pkgconfig(protobuf) +BuildRequires: pkgconfig(sqlite3) >= 3.7 +BuildRequires: pkgconfig(taglib) >= 1.11 +BuildRequires: pkgconfig(glew) +BuildRequires: pkgconfig(cryptopp) +BuildRequires: pkgconfig(Qt5Core) +BuildRequires: pkgconfig(Qt5Gui) +BuildRequires: pkgconfig(Qt5Widgets) +BuildRequires: pkgconfig(Qt5Concurrent) +BuildRequires: pkgconfig(Qt5Sql) +BuildRequires: pkgconfig(Qt5Network) +BuildRequires: pkgconfig(Qt5Xml) +BuildRequires: pkgconfig(Qt5X11Extras) +BuildRequires: pkgconfig(Qt5OpenGL) +BuildRequires: pkgconfig(Qt5DBus) +BuildRequires: pkgconfig(Qt5Test) +BuildRequires: pkgconfig(gstreamer-1.0) +BuildRequires: pkgconfig(gstreamer-app-1.0) +BuildRequires: pkgconfig(gstreamer-audio-1.0) +BuildRequires: pkgconfig(gstreamer-base-1.0) +BuildRequires: pkgconfig(gstreamer-tag-1.0) +BuildRequires: pkgconfig(libpulse) +BuildRequires: pkgconfig(libcdio) +BuildRequires: pkgconfig(libchromaprint) +BuildRequires: pkgconfig(libgpod-1.0) +BuildRequires: pkgconfig(libmtp) +BuildRequires: pkgconfig(libnotify) +BuildRequires: pkgconfig(libudf) # GStreamer codec dependencies Requires: gstreamer1-plugins-ugly @@ -80,7 +117,8 @@ make clean %doc %{_bindir}/clementine %{_bindir}/clementine-tagreader -%{_datadir}/appdata/clementine.appdata.xml +%dir %{_datadir}/metainfo/ +%{_datadir}/metainfo/clementine.appdata.xml %{_datadir}/applications/clementine.desktop %{_datadir}/clementine/projectm-presets %{_datadir}/kservices5/clementine-itms.protocol diff --git a/ext/libclementine-common/core/workerpool.h b/ext/libclementine-common/core/workerpool.h index 49fe099c0..ed3965e4c 100644 --- a/ext/libclementine-common/core/workerpool.h +++ b/ext/libclementine-common/core/workerpool.h @@ -229,8 +229,8 @@ void WorkerPool::DoStart() { QStringList search_path; search_path << qApp->applicationDirPath(); -#ifdef Q_OS_MAC - search_path << qApp->applicationDirPath() + "/../PlugIns"; +#if defined(Q_OS_MACOS) && defined(USE_BUNDLE) + search_path << qApp->applicationDirPath() + "/" + USE_BUNDLE_DIR; #endif for (const QString& path_prefix : search_path) { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 120f09949..9d0df7a78 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,9 +12,6 @@ endif(BUILD_WERROR) include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) include_directories(../3rdparty/gmock/gtest/include) -if(WIN32) - include_directories(../3rdparty/qtwin) -endif(WIN32) # Activate fast QString concatenation add_definitions(-DQT_USE_QSTRINGBUILDER) @@ -33,7 +30,7 @@ include_directories(${SHA2_INCLUDE_DIRS}) include_directories(${CHROMAPRINT_INCLUDE_DIRS}) include_directories(${MYGPOQT5_INCLUDE_DIRS}) -find_package(OpenGL) +find_package(OpenGL REQUIRED) include_directories(${OPENGL_INCLUDE_DIR}) if(HAVE_LIBLASTFM) @@ -49,12 +46,17 @@ include_directories(${CMAKE_SOURCE_DIR}/ext/libclementine-tagreader) include_directories(${CMAKE_BINARY_DIR}/ext/libclementine-tagreader) include_directories(${CMAKE_SOURCE_DIR}/ext/libclementine-remote) include_directories(${CMAKE_BINARY_DIR}/ext/libclementine-remote) -include_directories(${CMAKE_SOURCE_DIR}/ext/libclementine-spotifyblob) -include_directories(${CMAKE_BINARY_DIR}/ext/libclementine-spotifyblob) +if(HAVE_SPOTIFY) + include_directories(${CMAKE_SOURCE_DIR}/ext/libclementine-spotifyblob) + include_directories(${CMAKE_BINARY_DIR}/ext/libclementine-spotifyblob) +endif(HAVE_SPOTIFY) cmake_policy(SET CMP0011 NEW) include(../cmake/ParseArguments.cmake) -include(../cmake/Translations.cmake) + +if(HAVE_TRANSLATIONS) + include(../cmake/Translations.cmake) +endif(HAVE_TRANSLATIONS) set(SOURCES analyzers/analyzerbase.cpp @@ -148,7 +150,6 @@ set(SOURCES globalsearch/simplesearchprovider.cpp globalsearch/somafmsearchprovider.cpp globalsearch/intergalacticfmsearchprovider.cpp - globalsearch/spotifysearchprovider.cpp globalsearch/suggestionwidget.cpp globalsearch/urlsearchprovider.cpp @@ -185,9 +186,6 @@ set(SOURCES internet/somafm/somafmurlhandler.cpp internet/intergalacticfm/intergalacticfmservice.cpp internet/intergalacticfm/intergalacticfmurlhandler.cpp - internet/spotify/spotifyserver.cpp - internet/spotify/spotifyservice.cpp - internet/spotify/spotifysettingspage.cpp internet/subsonic/subsonicservice.cpp internet/subsonic/subsonicsettingspage.cpp internet/subsonic/subsonicurlhandler.cpp @@ -303,7 +301,6 @@ set(SOURCES songinfo/songkickconcerts.cpp songinfo/songkickconcertwidget.cpp songinfo/songplaystats.cpp - songinfo/spotifyimages.cpp songinfo/streamdiscoverer.cpp songinfo/taglyricsinfoprovider.cpp songinfo/ultimatelyricslyric.cpp @@ -459,7 +456,6 @@ set(HEADERS globalsearch/globalsearchview.h globalsearch/searchprovider.h globalsearch/simplesearchprovider.h - globalsearch/spotifysearchprovider.h globalsearch/suggestionwidget.h internet/core/cloudfileservice.h @@ -492,9 +488,6 @@ set(HEADERS internet/somafm/somafmurlhandler.h internet/intergalacticfm/intergalacticfmservice.h internet/intergalacticfm/intergalacticfmurlhandler.h - internet/spotify/spotifyserver.h - internet/spotify/spotifyservice.h - internet/spotify/spotifysettingspage.h internet/subsonic/subsonicservice.h internet/subsonic/subsonicsettingspage.h internet/subsonic/subsonicurlhandler.h @@ -596,7 +589,6 @@ set(HEADERS songinfo/songkickconcerts.h songinfo/songkickconcertwidget.h songinfo/songplaystats.h - songinfo/spotifyimages.h songinfo/streamdiscoverer.h songinfo/taglyricsinfoprovider.h songinfo/ultimatelyricslyric.h @@ -693,7 +685,6 @@ set(UI internet/magnatune/magnatunedownloaddialog.ui internet/magnatune/magnatunesettingspage.ui internet/core/searchboxwidget.ui - internet/spotify/spotifysettingspage.ui internet/subsonic/subsonicsettingspage.ui library/groupbydialog.ui @@ -780,22 +771,24 @@ set(RESOURCES set(OTHER_SOURCES) -set(LINGUAS "All" CACHE STRING "A space-seperated list of translations to compile in to Clementine, or \"None\".") -if (LINGUAS STREQUAL "All") - # build LANGUAGES from all existing .po files - file(GLOB pofiles translations/*.po) - foreach(pofile ${pofiles}) - get_filename_component(lang ${pofile} NAME_WE) - list(APPEND LANGUAGES ${lang}) - endforeach(pofile) -else (LINGUAS STREQUAL "All") - if (NOT LINGUAS OR LINGUAS STREQUAL "None") - set (LANGUAGES "") - else (NOT LINGUAS OR LINGUAS STREQUAL "None") - string(REGEX MATCHALL [a-zA-Z_@]+ +if (HAVE_TRANSLATIONS) + set(LINGUAS "All" CACHE STRING "A space-seperated list of translations to compile in to Clementine, or \"None\".") + if (LINGUAS STREQUAL "All") + # build LANGUAGES from all existing .po files + file(GLOB pofiles translations/*.po) + foreach(pofile ${pofiles}) + get_filename_component(lang ${pofile} NAME_WE) + list(APPEND LANGUAGES ${lang}) + endforeach(pofile) + else (LINGUAS STREQUAL "All") + if (NOT LINGUAS OR LINGUAS STREQUAL "None") + set (LANGUAGES "") + else (NOT LINGUAS OR LINGUAS STREQUAL "None") + string(REGEX MATCHALL [a-zA-Z_@]+ LANGUAGES ${LINGUAS}) - endif (NOT LINGUAS OR LINGUAS STREQUAL "None") -endif (LINGUAS STREQUAL "All") + endif (NOT LINGUAS OR LINGUAS STREQUAL "None") + endif (LINGUAS STREQUAL "All") +endif(HAVE_TRANSLATIONS) option(USE_INSTALL_PREFIX "Look for data in CMAKE_INSTALL_PREFIX" ON) @@ -838,16 +831,35 @@ optional_source(HAVE_LIBLASTFM internet/lastfm/lastfmsettingspage.ui ) - -optional_source(HAVE_SPOTIFY_DOWNLOADER +# Spotify support +optional_source(HAVE_SPOTIFY SOURCES - internet/spotify/spotifyblobdownloader.cpp + internet/spotify/spotifyserver.cpp + internet/spotify/spotifyservice.cpp + internet/spotify/spotifysettingspage.cpp + globalsearch/spotifysearchprovider.cpp + songinfo/spotifyimages.cpp HEADERS - internet/spotify/spotifyblobdownloader.h - INCLUDE_DIRECTORIES - ${CRYPTOPP_INCLUDE_DIRS} + globalsearch/spotifysearchprovider.h + internet/spotify/spotifyserver.h + internet/spotify/spotifyservice.h + internet/spotify/spotifysettingspage.h + songinfo/spotifyimages.h + UI + internet/spotify/spotifysettingspage.ui ) +if(HAVE_SPOTIFY) + optional_source(HAVE_SPOTIFY_DOWNLOADER + SOURCES + internet/spotify/spotifyblobdownloader.cpp + HEADERS + internet/spotify/spotifyblobdownloader.h + INCLUDE_DIRECTORIES + ${CRYPTOPP_INCLUDE_DIRS} + ) +endif(HAVE_SPOTIFY) + # Platform specific - OS X optional_source(APPLE INCLUDE_DIRECTORIES @@ -889,10 +901,10 @@ optional_source(WIN32 ) # Platform specific - X11 -optional_source(LINUX SOURCES widgets/osd_x11.cpp) +optional_source(HAVE_X11 SOURCES widgets/osd_x11.cpp) -# DBUS and MPRIS - Linux specific -if(HAVE_DBUS) +# DBUS and MPRIS - Unix specific +if(UNIX AND HAVE_DBUS) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dbus) # MPRIS 2.0 DBUS interfaces @@ -997,7 +1009,7 @@ if(HAVE_DBUS) dbus/org.wiimotedev.deviceEvents.xml dbus/wiimotedev) endif(ENABLE_WIIMOTEDEV) -endif(HAVE_DBUS) +endif(UNIX AND HAVE_DBUS) optional_source(HAVE_DBUS SOURCES @@ -1201,16 +1213,18 @@ qt5_wrap_cpp(MOC ${HEADERS}) qt5_wrap_ui(UIC ${UI}) qt5_add_resources(QRC ${RESOURCES}) -add_pot(POT - ${CMAKE_CURRENT_SOURCE_DIR}/translations/header - ${CMAKE_CURRENT_SOURCE_DIR}/translations/translations.pot - ${SOURCES} ${MOC} ${UIC} ${OTHER_SOURCES} - ../data/oauthsuccess.html -) -add_po(PO clementine_ - LANGUAGES ${LANGUAGES} - DIRECTORY translations -) +if(HAVE_TRANSLATIONS) + add_pot(POT + ${CMAKE_CURRENT_SOURCE_DIR}/translations/header + ${CMAKE_CURRENT_SOURCE_DIR}/translations/translations.pot + ${SOURCES} ${MOC} ${UIC} ${OTHER_SOURCES} + ../data/oauthsuccess.html + ) + add_po(PO clementine_ + LANGUAGES ${LANGUAGES} + DIRECTORY translations + ) +endif(HAVE_TRANSLATIONS) add_library(clementine_lib STATIC ${SOURCES} @@ -1223,7 +1237,6 @@ add_library(clementine_lib STATIC ) target_link_libraries(clementine_lib - clementine-spotifyblob-messages libclementine-common libclementine-tagreader libclementine-remote @@ -1288,6 +1301,10 @@ if(HAVE_BREAKPAD) endif (LINUX) endif(HAVE_BREAKPAD) +if(HAVE_SPOTIFY) + target_link_libraries(clementine_lib clementine-spotifyblob-messages) +endif(HAVE_SPOTIFY) + if(HAVE_SPOTIFY_DOWNLOADER) target_link_libraries(clementine_lib ${CRYPTOPP_LIBRARIES} @@ -1327,10 +1344,10 @@ target_link_libraries(clementine_lib qsqlite) if (WIN32) target_link_libraries(clementine_lib + protobuf ${ZLIB_LIBRARIES} ${QTSPARKLE_LIBRARIES} tinysvcmdns - qtwin dsound ${QT_QTGUI_LIBRARY} ) @@ -1343,7 +1360,7 @@ if (UNIX AND NOT APPLE) # they end up getting ignored. This appends them to the very end of the link # line, ensuring they're always used. find_package(X11) - if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + if (FREEBSD) target_link_libraries(clementine_lib ${X11_X11_LIB}) else () target_link_libraries(clementine_lib ${X11_X11_LIB} ${CMAKE_DL_LIBS}) @@ -1376,9 +1393,9 @@ add_executable(clementine main.cpp ) -if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") +if (FREEBSD) target_link_libraries(clementine execinfo) -endif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") +endif (FREEBSD) target_link_libraries(clementine clementine_lib @@ -1420,12 +1437,14 @@ if (APPLE) WORLD_READ WORLD_EXECUTE) endif (HAVE_BREAKPAD) - add_custom_command(TARGET clementine - POST_BUILD - COMMAND - ${CMAKE_CURRENT_SOURCE_DIR}/../dist/macdeploy.py ${PROJECT_BINARY_DIR}/clementine.app -f - WORKING_DIRECTORY ${PROJECT_BINARY_DIR} - ) + if (USE_BUNDLE) + add_custom_command(TARGET clementine + POST_BUILD + COMMAND + ${CMAKE_CURRENT_SOURCE_DIR}/../dist/macdeploy.py ${PROJECT_BINARY_DIR}/clementine.app -f + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + ) + endif(USE_BUNDLE) add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/clementine.breakpad COMMAND diff --git a/src/analyzers/analyzerbase.h b/src/analyzers/analyzerbase.h index 8074bfaef..d65e6c110 100644 --- a/src/analyzers/analyzerbase.h +++ b/src/analyzers/analyzerbase.h @@ -39,7 +39,7 @@ #include #include -#ifdef Q_WS_MACX +#ifdef Q_OS_MACX #include #include #else diff --git a/src/config.h.in b/src/config.h.in index 4475e28dc..c21c2ec4b 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -27,6 +27,7 @@ #cmakedefine HAVE_BREAKPAD #cmakedefine HAVE_CRYPTOPP #cmakedefine HAVE_DBUS +#cmakedefine HAVE_X11 #cmakedefine HAVE_DEVICEKIT #cmakedefine HAVE_DROPBOX #cmakedefine HAVE_GIO @@ -44,9 +45,14 @@ #cmakedefine HAVE_SPOTIFY_DOWNLOADER #cmakedefine HAVE_UDISKS2 #cmakedefine HAVE_WIIMOTEDEV +#cmakedefine HAVE_TRANSLATIONS +#cmakedefine HAVE_SPOTIFY #cmakedefine TAGLIB_HAS_OPUS #cmakedefine USE_INSTALL_PREFIX #cmakedefine USE_SYSTEM_PROJECTM #cmakedefine USE_SYSTEM_SHA2 +#cmakedefine USE_BUNDLE + +#define USE_BUNDLE_DIR "${USE_BUNDLE_DIR}" #endif // CONFIG_H_IN diff --git a/src/core/globalshortcuts.cpp b/src/core/globalshortcuts.cpp index 0f0749443..8aa7860dc 100644 --- a/src/core/globalshortcuts.cpp +++ b/src/core/globalshortcuts.cpp @@ -19,6 +19,7 @@ along with Clementine. If not, see . */ +#include "config.h" #include "globalshortcuts.h" #include "gnomeglobalshortcutbackend.h" #include "macglobalshortcutbackend.h" @@ -31,7 +32,7 @@ #include #include -#ifdef QT_DBUS_LIB +#ifdef HAVE_DBUS #include #endif @@ -147,10 +148,10 @@ GlobalShortcuts::Shortcut GlobalShortcuts::AddShortcut( } bool GlobalShortcuts::IsGsdAvailable() const { -#ifdef QT_DBUS_LIB +#ifdef HAVE_DBUS return QDBusConnection::sessionBus().interface()->isServiceRegistered( GnomeGlobalShortcutBackend::kGsdService); -#else // QT_DBUS_LIB +#else // HAVE_DBUS return false; #endif } diff --git a/src/core/gnomeglobalshortcutbackend.cpp b/src/core/gnomeglobalshortcutbackend.cpp index 8a0f58760..2d151dae4 100644 --- a/src/core/gnomeglobalshortcutbackend.cpp +++ b/src/core/gnomeglobalshortcutbackend.cpp @@ -17,13 +17,14 @@ along with Clementine. If not, see . */ +#include "config.h" #include "gnomeglobalshortcutbackend.h" #include "globalshortcuts.h" #include "core/closure.h" #include "core/logging.h" -#ifdef QT_DBUS_LIB -#include "dbus/gnomesettingsdaemon.h" +#ifdef HAVE_DBUS +#include #endif #include @@ -31,7 +32,7 @@ #include #include -#ifdef QT_DBUS_LIB +#ifdef HAVE_DBUS #include #endif @@ -48,7 +49,7 @@ GnomeGlobalShortcutBackend::GnomeGlobalShortcutBackend(GlobalShortcuts* parent) is_connected_(false) {} bool GnomeGlobalShortcutBackend::DoRegister() { -#ifdef QT_DBUS_LIB +#ifdef HAVE_DBUS qLog(Debug) << "registering"; // Check if the GSD service is available if (!QDBusConnection::sessionBus().interface()->isServiceRegistered( @@ -71,7 +72,7 @@ bool GnomeGlobalShortcutBackend::DoRegister() { SLOT(RegisterFinished(QDBusPendingCallWatcher*)), watcher); return true; -#else // QT_DBUS_LIB +#else // HAVE_DBUS qLog(Warning) << "dbus not available"; return false; #endif @@ -79,7 +80,7 @@ bool GnomeGlobalShortcutBackend::DoRegister() { void GnomeGlobalShortcutBackend::RegisterFinished( QDBusPendingCallWatcher* watcher) { -#ifdef QT_DBUS_LIB +#ifdef HAVE_DBUS QDBusMessage reply = watcher->reply(); watcher->deleteLater(); @@ -94,12 +95,12 @@ void GnomeGlobalShortcutBackend::RegisterFinished( is_connected_ = true; qLog(Debug) << "registered"; -#endif // QT_DBUS_LIB +#endif // HAVE_DBUS } void GnomeGlobalShortcutBackend::DoUnregister() { qLog(Debug) << "unregister"; -#ifdef QT_DBUS_LIB +#ifdef HAVE_DBUS // Check if the GSD service is available if (!QDBusConnection::sessionBus().interface()->isServiceRegistered( kGsdService)) diff --git a/src/core/metatypes.cpp b/src/core/metatypes.cpp index b0086cf9e..e6584568a 100644 --- a/src/core/metatypes.cpp +++ b/src/core/metatypes.cpp @@ -114,7 +114,6 @@ void RegisterMetaTypes() { qRegisterMetaType("QFileInfo"); #ifdef HAVE_DBUS - qDBusRegisterMetaType(); qDBusRegisterMetaType(); qDBusRegisterMetaType(); qDBusRegisterMetaType>(); @@ -124,5 +123,8 @@ void RegisterMetaTypes() { qDBusRegisterMetaType(); qDBusRegisterMetaType(); +#ifdef HAVE_X11 + qDBusRegisterMetaType(); +#endif #endif } diff --git a/src/covers/albumcoverloader.cpp b/src/covers/albumcoverloader.cpp index a1a4582ef..214fc8243 100644 --- a/src/covers/albumcoverloader.cpp +++ b/src/covers/albumcoverloader.cpp @@ -34,7 +34,9 @@ #include "core/tagreaderclient.h" #include "core/utilities.h" #include "internet/core/internetmodel.h" -#include "internet/spotify/spotifyservice.h" +#ifdef HAVE_SPOTIFY +# include "internet/spotify/spotifyservice.h" +#endif AlbumCoverLoader::AlbumCoverLoader(QObject* parent) : QObject(parent), @@ -176,7 +178,9 @@ AlbumCoverLoader::TryLoadResult AlbumCoverLoader::TryLoadImage( remote_tasks_.insert(reply, task); return TryLoadResult(true, false, QImage()); - } else if (filename.toLower().startsWith("spotify://image/")) { + } +#ifdef HAVE_SPOTIFY + else if (filename.toLower().startsWith("spotify://image/")) { // HACK: we should add generic image URL handlers SpotifyService* spotify = InternetModel::Service(); @@ -196,7 +200,9 @@ AlbumCoverLoader::TryLoadResult AlbumCoverLoader::TryLoadImage( QMetaObject::invokeMethod(spotify, "LoadImage", Qt::QueuedConnection, Q_ARG(QString, id)); return TryLoadResult(true, false, QImage()); - } else if (filename.isEmpty()) { + } +#endif + else if (filename.isEmpty()) { // Avoid "QFSFileEngine::open: No file name specified" messages if we know that the filename is empty return TryLoadResult(false, false, task.options.default_output_image_); } @@ -207,6 +213,7 @@ AlbumCoverLoader::TryLoadResult AlbumCoverLoader::TryLoadImage( image.isNull() ? task.options.default_output_image_ : image); } +#ifdef HAVE_SPOTIFY void AlbumCoverLoader::SpotifyImageLoaded(const QString& id, const QImage& image) { if (!remote_spotify_tasks_.contains(id)) return; @@ -216,6 +223,7 @@ void AlbumCoverLoader::SpotifyImageLoaded(const QString& id, emit ImageLoaded(task.id, scaled); emit ImageLoaded(task.id, scaled, image); } +#endif void AlbumCoverLoader::RemoteFetchFinished(QNetworkReply* reply) { reply->deleteLater(); diff --git a/src/covers/albumcoverloader.h b/src/covers/albumcoverloader.h index 4d3e4d571..e2b44cde4 100644 --- a/src/covers/albumcoverloader.h +++ b/src/covers/albumcoverloader.h @@ -21,6 +21,7 @@ #ifndef COVERS_ALBUMCOVERLOADER_H_ #define COVERS_ALBUMCOVERLOADER_H_ +#include "config.h" #include "albumcoverloaderoptions.h" #include "core/song.h" @@ -66,7 +67,9 @@ class AlbumCoverLoader : public QObject { protected slots: void ProcessTasks(); void RemoteFetchFinished(QNetworkReply* reply); +#ifdef HAVE_SPOTIFY void SpotifyImageLoaded(const QString& url, const QImage& image); +#endif protected: enum State { State_TryingManual, State_TryingAuto, }; diff --git a/src/devices/deviceview.cpp b/src/devices/deviceview.cpp index 7d62571aa..35300dd6b 100644 --- a/src/devices/deviceview.cpp +++ b/src/devices/deviceview.cpp @@ -56,9 +56,7 @@ void DeviceItemDelegate::paint(QPainter* p, const QStyleOptionViewItem& opt, } // Draw the background - const QStyleOptionViewItemV3* vopt = - qstyleoption_cast(&opt); - const QWidget* widget = vopt->widget; + const QWidget* widget = opt.widget; QStyle* style = widget->style() ? widget->style() : QApplication::style(); style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, p, widget); diff --git a/src/devices/macdevicelister.mm b/src/devices/macdevicelister.mm index e4d8934a8..2ac240776 100644 --- a/src/devices/macdevicelister.mm +++ b/src/devices/macdevicelister.mm @@ -42,11 +42,12 @@ #include -#include - -#include #include #include +#include +#include +#include +#include #ifndef kUSBSerialNumberString #define kUSBSerialNumberString "USB Serial Number" @@ -118,9 +119,9 @@ void MacDeviceLister::Init() { for (int i = 0; i < num; ++i) { LIBMTP_device_entry_t device = devices[i]; MTPDevice d; - d.vendor = QString::fromAscii(device.vendor); + d.vendor = QString::fromLatin1(device.vendor); d.vendor_id = device.vendor_id; - d.product = QString::fromAscii(device.product); + d.product = QString::fromLatin1(device.product); d.product_id = device.product_id; d.quirks = device.device_flags; sMTPDeviceList << d; @@ -305,7 +306,7 @@ QString GetSerialForMTPDevice(io_object_t device) { QString FindDeviceProperty(const QString& bsd_name, CFStringRef property) { ScopedCFTypeRef session(DASessionCreate(kCFAllocatorDefault)); ScopedCFTypeRef disk(DADiskCreateFromBSDName( - kCFAllocatorDefault, session.get(), bsd_name.toAscii().constData())); + kCFAllocatorDefault, session.get(), bsd_name.toLatin1().constData())); ScopedIOObject device(DADiskCopyIOMedia(disk.get())); QString ret = GetUSBRegistryEntryString(device.get(), property); @@ -358,7 +359,7 @@ void MacDeviceLister::DiskAddedCallback(DADiskRef disk, void* context) { #ifdef HAVE_AUDIOCD if (kind && strcmp([kind UTF8String], kIOCDMediaClass) == 0) { // CD inserted. - QString bsd_name = QString::fromAscii(DADiskGetBSDName(disk)); + QString bsd_name = QString::fromLatin1(DADiskGetBSDName(disk)); me->cd_devices_ << bsd_name; emit me->DeviceAdded(bsd_name); return; @@ -402,7 +403,7 @@ void MacDeviceLister::DiskRemovedCallback(DADiskRef disk, void* context) { // We cannot access the USB tree when the disk is removed but we still get // the BSD disk name. - QString bsd_name = QString::fromAscii(DADiskGetBSDName(disk)); + QString bsd_name = QString::fromLatin1(DADiskGetBSDName(disk)); if (me->cd_devices_.remove(bsd_name)) { emit me->DeviceRemoved(bsd_name); return; @@ -579,7 +580,7 @@ void MacDeviceLister::USBDeviceAddedCallback(void* refcon, io_iterator_t it) { 4, 256, &data); if (!ret || data.at(0) != 0x28) continue; - if (QString::fromAscii(data.data() + 0x12, 3) != "MTP") { + if (QString::fromLatin1(data.data() + 0x12, 3) != "MTP") { // Not quite. continue; } @@ -590,7 +591,7 @@ void MacDeviceLister::USBDeviceAddedCallback(void* refcon, io_iterator_t it) { continue; } - if (QString::fromAscii(data.data() + 0x12, 3) != "MTP") { + if (QString::fromLatin1(data.data() + 0x12, 3) != "MTP") { // Not quite. continue; } @@ -671,7 +672,7 @@ QString MacDeviceLister::MakeFriendlyName(const QString& serial) { IsCDDevice(serial) ? *cd_devices_.find(serial) : current_devices_[serial]; ScopedCFTypeRef session(DASessionCreate(kCFAllocatorDefault)); ScopedCFTypeRef disk(DADiskCreateFromBSDName( - kCFAllocatorDefault, session.get(), bsd_name.toAscii().constData())); + kCFAllocatorDefault, session.get(), bsd_name.toLatin1().constData())); if (IsCDDevice(serial)) { scoped_nsobject properties( @@ -700,12 +701,14 @@ QList MacDeviceLister::MakeDeviceUrls(const QString& serial) { const MTPDevice& device = mtp_devices_[serial]; QString str; str.sprintf("gphoto2://usb-%d-%d/", device.bus, device.address); + QUrlQuery url_query; + url_query.addQueryItem("vendor", device.vendor); + url_query.addQueryItem("vendor_id", QString::number(device.vendor_id)); + url_query.addQueryItem("product", device.product); + url_query.addQueryItem("product_id", QString::number(device.product_id)); + url_query.addQueryItem("quirks", QString::number(device.quirks)); QUrl url(str); - url.addQueryItem("vendor", device.vendor); - url.addQueryItem("vendor_id", QString::number(device.vendor_id)); - url.addQueryItem("product", device.product); - url.addQueryItem("product_id", QString::number(device.product_id)); - url.addQueryItem("quirks", QString::number(device.quirks)); + url.setQuery(url_query); return QList() << url; } @@ -716,7 +719,7 @@ QList MacDeviceLister::MakeDeviceUrls(const QString& serial) { QString bsd_name = current_devices_[serial]; ScopedCFTypeRef session(DASessionCreate(kCFAllocatorDefault)); ScopedCFTypeRef disk(DADiskCreateFromBSDName( - kCFAllocatorDefault, session.get(), bsd_name.toAscii().constData())); + kCFAllocatorDefault, session.get(), bsd_name.toLatin1().constData())); scoped_nsobject properties( (NSDictionary*)DADiskCopyDescription(disk.get())); @@ -745,7 +748,7 @@ QVariantList MacDeviceLister::DeviceIcons(const QString& serial) { QString bsd_name = current_devices_[serial]; ScopedCFTypeRef session(DASessionCreate(kCFAllocatorDefault)); ScopedCFTypeRef disk(DADiskCreateFromBSDName( - kCFAllocatorDefault, session.get(), bsd_name.toAscii().constData())); + kCFAllocatorDefault, session.get(), bsd_name.toLatin1().constData())); ScopedIOObject device(DADiskCopyIOMedia(disk.get())); QString icon = GetIconForDevice(device.get()); @@ -788,7 +791,7 @@ quint64 MacDeviceLister::DeviceCapacity(const QString& serial) { QString bsd_name = current_devices_[serial]; ScopedCFTypeRef session(DASessionCreate(kCFAllocatorDefault)); ScopedCFTypeRef disk(DADiskCreateFromBSDName( - kCFAllocatorDefault, session.get(), bsd_name.toAscii().constData())); + kCFAllocatorDefault, session.get(), bsd_name.toLatin1().constData())); io_object_t device = DADiskCopyIOMedia(disk); @@ -809,7 +812,7 @@ quint64 MacDeviceLister::DeviceFreeSpace(const QString& serial) { QString bsd_name = current_devices_[serial]; ScopedCFTypeRef session(DASessionCreate(kCFAllocatorDefault)); ScopedCFTypeRef disk(DADiskCreateFromBSDName( - kCFAllocatorDefault, session.get(), bsd_name.toAscii().constData())); + kCFAllocatorDefault, session.get(), bsd_name.toLatin1().constData())); scoped_nsobject properties( (NSDictionary*)DADiskCopyDescription(disk)); @@ -840,7 +843,7 @@ void MacDeviceLister::UnmountDevice(const QString& serial) { QString bsd_name = current_devices_[serial]; ScopedCFTypeRef disk(DADiskCreateFromBSDName( - kCFAllocatorDefault, loop_session_, bsd_name.toAscii().constData())); + kCFAllocatorDefault, loop_session_, bsd_name.toLatin1().constData())); DADiskUnmount(disk, kDADiskUnmountOptionDefault, &DiskUnmountCallback, this); } diff --git a/src/engines/gstenginepipeline.cpp b/src/engines/gstenginepipeline.cpp index 0bafeb8c1..f6094c41f 100644 --- a/src/engines/gstenginepipeline.cpp +++ b/src/engines/gstenginepipeline.cpp @@ -15,6 +15,8 @@ along with Clementine. If not, see . */ +#include "config.h" + #include #include @@ -33,8 +35,10 @@ #include "core/signalchecker.h" #include "core/utilities.h" #include "internet/core/internetmodel.h" -#include "internet/spotify/spotifyserver.h" -#include "internet/spotify/spotifyservice.h" +#ifdef HAVE_SPOTIFY +# include "internet/spotify/spotifyserver.h" +# include "internet/spotify/spotifyservice.h" +#endif const int GstEnginePipeline::kGstStateTimeoutNanosecs = 10000000; const int GstEnginePipeline::kFaderFudgeMsec = 2000; @@ -151,6 +155,7 @@ bool GstEnginePipeline::ReplaceDecodeBin(GstElement* new_bin) { bool GstEnginePipeline::ReplaceDecodeBin(const QUrl& url) { GstElement* new_bin = nullptr; +#ifdef HAVE_SPOTIFY if (url.scheme() == "spotify") { new_bin = gst_bin_new("spotify_bin"); @@ -181,6 +186,7 @@ bool GstEnginePipeline::ReplaceDecodeBin(const QUrl& url) { spotify_server, "StartPlayback", Qt::QueuedConnection, Q_ARG(QString, url.toString()), Q_ARG(quint16, port)); } else { +#endif QByteArray uri; if (url.scheme() == "cdda") { QString str = url.toString(); @@ -197,7 +203,9 @@ bool GstEnginePipeline::ReplaceDecodeBin(const QUrl& url) { CHECKED_GCONNECT(G_OBJECT(new_bin), "pad-added", &NewPadCallback, this); CHECKED_GCONNECT(G_OBJECT(new_bin), "notify::source", &SourceSetupCallback, this); +#ifdef HAVE_SPOTIFY } +#endif return ReplaceDecodeBin(new_bin); } @@ -1050,6 +1058,7 @@ GstState GstEnginePipeline::state() const { } QFuture GstEnginePipeline::SetState(GstState state) { +#ifdef HAVE_SPOTIFY if (url_.scheme() == "spotify" && !buffering_) { const GstState current_state = this->state(); @@ -1068,6 +1077,7 @@ QFuture GstEnginePipeline::SetState(GstState state) { Q_ARG(bool, false)); } } +#endif return ConcurrentRun::Run( &set_state_threadpool_, &gst_element_set_state, pipeline_, state); } diff --git a/src/internet/core/internetmodel.cpp b/src/internet/core/internetmodel.cpp index d7db2975b..756d48073 100644 --- a/src/internet/core/internetmodel.cpp +++ b/src/internet/core/internetmodel.cpp @@ -41,7 +41,6 @@ #include "internet/magnatune/magnatuneservice.h" #include "internet/podcasts/podcastservice.h" #include "internet/somafm/somafmservice.h" -#include "internet/spotify/spotifyservice.h" #include "internet/subsonic/subsonicservice.h" #include "smartplaylists/generatormimedata.h" @@ -60,6 +59,9 @@ #ifdef HAVE_SEAFILE #include "internet/seafile/seafileservice.h" #endif +#ifdef HAVE_SPOTIFY +#include "internet/spotify/spotifyservice.h" +#endif using smart_playlists::Generator; using smart_playlists::GeneratorMimeData; @@ -92,7 +94,9 @@ InternetModel::InternetModel(Application* app, QObject* parent) AddService(new RadioTunesService(app, this)); AddService(new SomaFMService(app, this)); AddService(new IntergalacticFMService(app, this)); +#ifdef HAVE_SPOTIFY AddService(new SpotifyService(app, this)); +#endif AddService(new SubsonicService(app, this)); #ifdef HAVE_BOX AddService(new BoxService(app, this)); diff --git a/src/internet/spotify/spotifyservice.cpp b/src/internet/spotify/spotifyservice.cpp index 9d9045266..e05aeb1b7 100644 --- a/src/internet/spotify/spotifyservice.cpp +++ b/src/internet/spotify/spotifyservice.cpp @@ -90,9 +90,9 @@ SpotifyService::SpotifyService(Application* app, InternetModel* parent) // Build the search path for the binary blob. // Look for one distributed alongside clementine first, then check in the // user's home directory for any that have been downloaded. -#ifdef Q_OS_MAC +#if defined(Q_OS_MACOS) && defined(USE_BUNDLE) system_blob_path_ = QCoreApplication::applicationDirPath() + - "/../PlugIns/clementine-spotifyblob"; + "/" + USE_BUNDLE_DIR + "/clementine-spotifyblob"; #else system_blob_path_ = QCoreApplication::applicationDirPath() + "/clementine-spotifyblob" CMAKE_EXECUTABLE_SUFFIX; diff --git a/src/main.cpp b/src/main.cpp index 48acf367c..0ee7a8fa7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,9 +20,11 @@ #include #ifdef Q_OS_WIN32 -#define _WIN32_WINNT 0x0600 -#include -#include +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0600 +# endif +# include +# include #endif // Q_OS_WIN32 #ifdef Q_OS_UNIX @@ -95,7 +97,7 @@ const QDBusArgument& operator>>(const QDBusArgument& arg, QImage& image); #endif #ifdef Q_OS_WIN32 -#include +#include #endif // Load sqlite plugin on windows and mac. @@ -151,14 +153,16 @@ void SetGstreamerEnvironment() { QString registry_filename; // On windows and mac we bundle the gstreamer plugins with clementine +#ifdef USE_BUNDLE #if defined(Q_OS_DARWIN) scanner_path = - QCoreApplication::applicationDirPath() + "/../PlugIns/gst-plugin-scanner"; + QCoreApplication::applicationDirPath() + "/" + USE_BUNDLE_DIR + "/gst-plugin-scanner"; plugin_path = - QCoreApplication::applicationDirPath() + "/../PlugIns/gstreamer"; + QCoreApplication::applicationDirPath() + "/" + USE_BUNDLE_DIR + "/gstreamer"; #elif defined(Q_OS_WIN32) plugin_path = QCoreApplication::applicationDirPath() + "/gstreamer-plugins"; #endif +#endif #if defined(Q_OS_WIN32) || defined(Q_OS_DARWIN) registry_filename = @@ -177,9 +181,9 @@ void SetGstreamerEnvironment() { SetEnv("GST_REGISTRY", registry_filename); } -#ifdef Q_OS_DARWIN +#if defined(Q_OS_DARWIN) && defined(USE_BUNDLE) SetEnv("GIO_EXTRA_MODULES", - QCoreApplication::applicationDirPath() + "/../PlugIns/gio-modules"); + QCoreApplication::applicationDirPath() + "/" + USE_BUNDLE_DIR + "/gio-modules"); #endif SetEnv("PULSE_PROP_media.role", "music"); @@ -339,9 +343,10 @@ int main(int argc, char* argv[]) { .toInt()); } -#ifdef Q_OS_DARWIN +#if defined(Q_OS_DARWIN) && defined(USE_BUNDLE) + qLog(Debug) << "Looking for resources in" + QCoreApplication::applicationDirPath() + "/" + USE_BUNDLE_DIR; QCoreApplication::setLibraryPaths( - QStringList() << QCoreApplication::applicationDirPath() + "/../PlugIns"); + QStringList() << QCoreApplication::applicationDirPath() + "/" + USE_BUNDLE_DIR); #endif a.setQuitOnLastWindowClosed(false); @@ -381,7 +386,9 @@ int main(int argc, char* argv[]) { // Resources Q_INIT_RESOURCE(data); +#ifdef HAVE_TRANSLATIONS Q_INIT_RESOURCE(translations); +#endif // Add root CA cert for SoundCloud, whose certificate is missing on OS X. QSslSocket::addDefaultCaCertificates( diff --git a/src/musicbrainz/chromaprinter.cpp b/src/musicbrainz/chromaprinter.cpp index 6d1c00c35..aad146b0e 100644 --- a/src/musicbrainz/chromaprinter.cpp +++ b/src/musicbrainz/chromaprinter.cpp @@ -29,6 +29,10 @@ #include "core/logging.h" #include "core/signalchecker.h" +#ifndef u_int32_t +typedef unsigned int u_int32_t; +#endif + static const int kDecodeRate = 11025; static const int kDecodeChannels = 1; static const int kPlayLengthSecs = 30; diff --git a/src/playlist/playlistdelegates.cpp b/src/playlist/playlistdelegates.cpp index 8d4b24bda..daf896e73 100644 --- a/src/playlist/playlistdelegates.cpp +++ b/src/playlist/playlistdelegates.cpp @@ -182,7 +182,7 @@ void PlaylistDelegateBase::paint(QPainter* painter, } } -QStyleOptionViewItemV4 PlaylistDelegateBase::Adjusted( +QStyleOptionViewItem PlaylistDelegateBase::Adjusted( const QStyleOptionViewItem& option, const QModelIndex& index) const { if (!view_) return option; @@ -192,7 +192,7 @@ QStyleOptionViewItemV4 PlaylistDelegateBase::Adjusted( if (view_->header()->logicalIndexAt(top_left) != index.column()) return option; - QStyleOptionViewItemV4 ret(option); + QStyleOptionViewItem ret(option); if (index.data(Playlist::Role_IsCurrent).toBool()) { // Move the text in a bit on the first column for the song that's currently @@ -320,10 +320,8 @@ void RatingItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { // Draw the background - const QStyleOptionViewItemV3* vopt = - qstyleoption_cast(&option); - vopt->widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, vopt, - painter, vopt->widget); + option.widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, + painter, option.widget); // Don't draw anything else if the user can't set the rating of this item if (!index.data(Playlist::Role_CanSetRating).toBool()) return; diff --git a/src/playlist/playlistdelegates.h b/src/playlist/playlistdelegates.h index 35008c81f..df6436d15 100644 --- a/src/playlist/playlistdelegates.h +++ b/src/playlist/playlistdelegates.h @@ -63,7 +63,7 @@ class PlaylistDelegateBase : public QueuedItemDelegate { QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; - QStyleOptionViewItemV4 Adjusted(const QStyleOptionViewItem& option, + QStyleOptionViewItem Adjusted(const QStyleOptionViewItem& option, const QModelIndex& index) const; static const int kMinHeight; diff --git a/src/playlist/playlistview.cpp b/src/playlist/playlistview.cpp index 572715187..9966cb997 100644 --- a/src/playlist/playlistview.cpp +++ b/src/playlist/playlistview.cpp @@ -466,7 +466,7 @@ void PlaylistView::drawTree(QPainter* painter, const QRegion& region) const { void PlaylistView::drawRow(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { - QStyleOptionViewItemV4 opt(option); + QStyleOptionViewItem opt(option); bool is_current = index.data(Playlist::Role_IsCurrent).toBool(); bool is_paused = index.data(Playlist::Role_IsPaused).toBool(); @@ -545,7 +545,7 @@ void PlaylistView::drawRow(QPainter* painter, } } -void PlaylistView::UpdateCachedCurrentRowPixmap(QStyleOptionViewItemV4 option, +void PlaylistView::UpdateCachedCurrentRowPixmap(QStyleOptionViewItem option, const QModelIndex& index) { cached_current_row_rect_ = option.rect; cached_current_row_row_ = index.row(); diff --git a/src/playlist/playlistview.h b/src/playlist/playlistview.h index 4e97f6347..aa4b144a1 100644 --- a/src/playlist/playlistview.h +++ b/src/playlist/playlistview.h @@ -164,7 +164,7 @@ signals: private: void ReloadBarPixmaps(); QList LoadBarPixmap(const QString& filename); - void UpdateCachedCurrentRowPixmap(QStyleOptionViewItemV4 option, + void UpdateCachedCurrentRowPixmap(QStyleOptionViewItem option, const QModelIndex& index); void set_background_image_type(BackgroundImageType bg) { diff --git a/src/songinfo/artistinfoview.cpp b/src/songinfo/artistinfoview.cpp index 8a1f77582..735a2b460 100644 --- a/src/songinfo/artistinfoview.cpp +++ b/src/songinfo/artistinfoview.cpp @@ -20,12 +20,16 @@ #include "songinfo/artistbiography.h" #include "songinfo/songinfofetcher.h" #include "songinfo/songkickconcerts.h" -#include "songinfo/spotifyimages.h" #include "widgets/prettyimageview.h" +#ifdef HAVE_SPOTIFY +#include "songinfo/spotifyimages.h" +#endif ArtistInfoView::ArtistInfoView(QWidget* parent) : SongInfoBase(parent) { fetcher_->AddProvider(new SongkickConcerts); +#ifdef HAVE_SPOTIFY fetcher_->AddProvider(new SpotifyImages); +#endif fetcher_->AddProvider(new ArtistBiography); } diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 9df0c2ca1..26a0163e9 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -39,7 +39,7 @@ #include #ifdef Q_OS_WIN32 -#include +#include #endif #include "core/appearance.h" diff --git a/src/ui/settingsdialog.cpp b/src/ui/settingsdialog.cpp index 7549446e1..354187ade 100644 --- a/src/ui/settingsdialog.cpp +++ b/src/ui/settingsdialog.cpp @@ -34,7 +34,6 @@ #include "internet/digitally/digitallyimportedsettingspage.h" #include "internet/magnatune/magnatunesettingspage.h" #include "internet/podcasts/podcastsettingspage.h" -#include "internet/spotify/spotifysettingspage.h" #include "internet/subsonic/subsonicsettingspage.h" #include "library/librarysettingspage.h" #include "mainwindow.h" @@ -78,6 +77,10 @@ #include "internet/seafile/seafilesettingspage.h" #endif +#ifdef HAVE_SPOTIFY +#include "internet/spotify/spotifysettingspage.h" +#endif + #include #include #include @@ -174,7 +177,9 @@ SettingsDialog::SettingsDialog(Application* app, BackgroundStreams* streams, AddPage(Page_Skydrive, new SkydriveSettingsPage(this), providers); #endif +#ifdef HAVE_SPOTIFY AddPage(Page_Spotify, new SpotifySettingsPage(this), providers); +#endif #ifdef HAVE_SEAFILE AddPage(Page_Seafile, new SeafileSettingsPage(this), providers); diff --git a/src/ui/windows7thumbbar.cpp b/src/ui/windows7thumbbar.cpp index b8fbdecb6..50b2254d5 100644 --- a/src/ui/windows7thumbbar.cpp +++ b/src/ui/windows7thumbbar.cpp @@ -22,10 +22,12 @@ #include #ifdef Q_OS_WIN32 -#define _WIN32_WINNT 0x0600 -#include -#include -#include +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0600 +# endif +# include +# include +# include #endif // Q_OS_WIN32 const int Windows7ThumbBar::kIconSize = 16; diff --git a/src/widgets/groupediconview.cpp b/src/widgets/groupediconview.cpp index 113516fc9..77801acb1 100644 --- a/src/widgets/groupediconview.cpp +++ b/src/widgets/groupediconview.cpp @@ -214,8 +214,8 @@ void GroupedIconView::paintEvent(QPaintEvent* e) { // This code was adapted from QListView::paintEvent(), changed to use the // visualRect() of items, and to draw headers. - QStyleOptionViewItemV4 option(viewOptions()); - if (isWrapping()) option.features = QStyleOptionViewItemV2::WrapText; + QStyleOptionViewItem option(viewOptions()); + if (isWrapping()) option.features = QStyleOptionViewItem::WrapText; option.locale = locale(); option.locale.setNumberOptions(QLocale::OmitGroupSeparator); option.widget = this; diff --git a/src/widgets/osd.cpp b/src/widgets/osd.cpp index 2d81eb12f..77178a145 100644 --- a/src/widgets/osd.cpp +++ b/src/widgets/osd.cpp @@ -233,12 +233,10 @@ void OSD::ShowMessage(const QString& summary, const QString& message, } } -#ifndef HAVE_DBUS +#if !defined(HAVE_X11) && defined(HAVE_DBUS) void OSD::CallFinished(QDBusPendingCallWatcher*) {} #endif -#ifdef HAVE_WIIMOTEDEV - void OSD::WiiremoteActived(int id) { ShowMessage(QString(tr("%1: Wiimotedev module")) .arg(QCoreApplication::applicationName()), @@ -277,8 +275,6 @@ void OSD::WiiremoteCriticalBattery(int id, int live) { .arg(QString::number(id), QString::number(live))); } -#endif - void OSD::ShuffleModeChanged(PlaylistSequence::ShuffleMode mode) { if (show_on_play_mode_change_) { QString current_mode = QString(); diff --git a/src/widgets/osd.h b/src/widgets/osd.h index 201481a1f..fc2e0575c 100644 --- a/src/widgets/osd.h +++ b/src/widgets/osd.h @@ -38,6 +38,7 @@ class QDBusPendingCallWatcher; #ifdef HAVE_DBUS #include +#include QDBusArgument& operator<<(QDBusArgument& arg, const QImage& image); const QDBusArgument& operator>>(const QDBusArgument& arg, QImage& image); @@ -81,14 +82,12 @@ class OSD : public QObject { void ReshowCurrentSong(); -#ifdef HAVE_WIIMOTEDEV void WiiremoteActived(int id); void WiiremoteDeactived(int id); void WiiremoteConnected(int id); void WiiremoteDisconnected(int id); void WiiremoteLowBattery(int id, int live); void WiiremoteCriticalBattery(int id, int live); -#endif void ShowPreview(const Behaviour type, const QString& line1, const QString& line2, const Song& song); @@ -106,7 +105,9 @@ class OSD : public QObject { QString ReplaceVariable(const QString& variable, const Song& song); private slots: +#if defined(HAVE_DBUS) void CallFinished(QDBusPendingCallWatcher* watcher); +#endif void AlbumArtLoaded(const Song& song, const QString& uri, const QImage& image); diff --git a/src/widgets/osdpretty.cpp b/src/widgets/osdpretty.cpp index 6c2241cac..9d95716d8 100644 --- a/src/widgets/osdpretty.cpp +++ b/src/widgets/osdpretty.cpp @@ -15,6 +15,7 @@ along with Clementine. If not, see . */ +#include "config.h" #include "osdpretty.h" #include "ui_osdpretty.h" @@ -31,12 +32,14 @@ #include -#ifdef Q_WS_X11 +#ifdef HAVE_X11 #include #endif +#ifdef Q_OS_WIN32 +# include +#endif #ifdef Q_OS_WIN32 -#include "qtwin.h" #include #endif @@ -137,7 +140,7 @@ OSDPretty::OSDPretty(Mode mode, QWidget* parent) OSDPretty::~OSDPretty() { delete ui_; } bool OSDPretty::IsTransparencyAvailable() { -#ifdef Q_WS_X11 +#if defined(HAVE_X11) && (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)) return QX11Info::isCompositingManagerRunning(); #endif return true; @@ -346,7 +349,7 @@ void OSDPretty::Reposition() { #ifdef Q_OS_WIN32 // On windows, enable blurbehind on the masked area - QtWin::enableBlurBehindWindow(this, true, QRegion(mask)); + QtWin::enableBlurBehindWindow(this, QRegion(mask)); #endif } diff --git a/tests/main.cpp b/tests/main.cpp index 036e02111..85e42b93f 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -23,7 +23,7 @@ #include "metatypes_env.h" #include "resources_env.h" -#ifndef Q_WS_X11 +#if defined(Q_OS_WIN32) || defined(Q_OS_DARWIN) # include Q_IMPORT_PLUGIN(QSQLiteDriverPlugin) #endif From 1d5783b8466a44c9204bd36bd6451fe3553a3ac5 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Sat, 17 Nov 2018 15:49:29 +0100 Subject: [PATCH 070/104] Fix formatting --- 3rdparty/qocoa/qocoa_mac.h | 17 +++++++------- 3rdparty/qtsingleapplication/qtlocalpeer.cpp | 3 +-- 3rdparty/qtsingleapplication/qtlocalpeer.h | 2 +- .../qtsingleapplication/qtlockedfile_win.cpp | 23 ++++++++++++++----- 3rdparty/qxt/qxtglobalshortcut.cpp | 10 ++++---- 3rdparty/qxt/qxtglobalshortcut_p.h | 2 +- src/core/gnomeglobalshortcutbackend.cpp | 4 ++-- src/covers/albumcoverloader.cpp | 2 +- src/covers/albumcoverloader.h | 2 +- 9 files changed, 37 insertions(+), 28 deletions(-) diff --git a/3rdparty/qocoa/qocoa_mac.h b/3rdparty/qocoa/qocoa_mac.h index f93a56b9d..35a9deb1d 100644 --- a/3rdparty/qocoa/qocoa_mac.h +++ b/3rdparty/qocoa/qocoa_mac.h @@ -22,10 +22,10 @@ THE SOFTWARE. #include #include +#include #include #include #include -#include static inline NSString* fromQString(const QString &string) { @@ -43,14 +43,13 @@ static inline QString toQString(NSString *string) static inline NSImage* fromQPixmap(const QPixmap &pixmap) { - CGImageRef cgImage = QtMac::toCGImageRef(pixmap); - return [[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize]; + CGImageRef cgImage = QtMac::toCGImageRef(pixmap); + return [[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize]; } -static inline void setupLayout(NSView *cocoaView, QWidget *parent) -{ - parent->setAttribute(Qt::WA_NativeWindow); - QVBoxLayout *layout = new QVBoxLayout(parent); - layout->setMargin(0); - layout->addWidget(new QMacCocoaViewContainer(cocoaView, parent)); +static inline void setupLayout(NSView* cocoaView, QWidget* parent) { + parent->setAttribute(Qt::WA_NativeWindow); + QVBoxLayout* layout = new QVBoxLayout(parent); + layout->setMargin(0); + layout->addWidget(new QMacCocoaViewContainer(cocoaView, parent)); } diff --git a/3rdparty/qtsingleapplication/qtlocalpeer.cpp b/3rdparty/qtsingleapplication/qtlocalpeer.cpp index 4b2fac915..d65dda3ee 100644 --- a/3rdparty/qtsingleapplication/qtlocalpeer.cpp +++ b/3rdparty/qtsingleapplication/qtlocalpeer.cpp @@ -111,8 +111,7 @@ bool QtLocalPeer::isClient() if (lockFile.isLocked()) return false; - if (!lockFile.lock(QtLockedFile::WriteLock, false)) - return true; + if (!lockFile.lock(QtLockedFile::WriteLock, false)) return true; bool res = server->listen(socketName); #if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0)) diff --git a/3rdparty/qtsingleapplication/qtlocalpeer.h b/3rdparty/qtsingleapplication/qtlocalpeer.h index bd25f137a..8b1945b6a 100644 --- a/3rdparty/qtsingleapplication/qtlocalpeer.h +++ b/3rdparty/qtsingleapplication/qtlocalpeer.h @@ -69,7 +69,7 @@ protected: QLocalServer* server; QtLockedFile lockFile; -private: + private: static const char* ack; }; diff --git a/3rdparty/qtsingleapplication/qtlockedfile_win.cpp b/3rdparty/qtsingleapplication/qtlockedfile_win.cpp index 737a23f86..7f37a94e3 100644 --- a/3rdparty/qtsingleapplication/qtlockedfile_win.cpp +++ b/3rdparty/qtsingleapplication/qtlockedfile_win.cpp @@ -59,10 +59,13 @@ Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) Qt::HANDLE mutex; if (doCreate) { #if (QT_VERSION < 0x050000) - QT_WA( { mutex = CreateMutexW(nullptr, FALSE, (WCHAR*)mname.utf16()); }, - { mutex = CreateMutexA(nullptr, FALSE, mname.toLocal8Bit().constData()); } ); + QT_WA({ mutex = CreateMutexW(nullptr, FALSE, (WCHAR*)mname.utf16()); }, + { + mutex = + CreateMutexA(nullptr, FALSE, mname.toLocal8Bit().constData()); + }); #else - mutex = CreateMutexW(nullptr, FALSE, (WCHAR*)mname.utf16()); + mutex = CreateMutexW(nullptr, FALSE, (WCHAR*)mname.utf16()); #endif if (!mutex) { qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); @@ -71,10 +74,18 @@ Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) } else { #if (QT_VERSION < 0x050000) - QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (WCHAR*)mname.utf16()); }, - { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } ); + QT_WA( + { + mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, + (WCHAR*)mname.utf16()); + }, + { + mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, + mname.toLocal8Bit().constData()); + }); #else - mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (WCHAR*)mname.utf16()); + mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, + (WCHAR*)mname.utf16()); #endif if (!mutex) { if (GetLastError() != ERROR_FILE_NOT_FOUND) diff --git a/3rdparty/qxt/qxtglobalshortcut.cpp b/3rdparty/qxt/qxtglobalshortcut.cpp index db483060e..cfc8bfbc4 100644 --- a/3rdparty/qxt/qxtglobalshortcut.cpp +++ b/3rdparty/qxt/qxtglobalshortcut.cpp @@ -39,31 +39,31 @@ int QxtGlobalShortcutPrivate::ref = 0; #if QT_VERSION < QT_VERSION_CHECK(5,0,0) QAbstractEventDispatcher::EventFilter QxtGlobalShortcutPrivate::prevEventFilter = 0; #endif -#endif // Q_OS_MAC +#endif // Q_OS_MAC QHash, QxtGlobalShortcut*> QxtGlobalShortcutPrivate::shortcuts; QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate() : enabled(true), key(Qt::Key(0)), mods(Qt::NoModifier) { #ifndef Q_OS_MAC - if (!ref++) + if (!ref++) #if QT_VERSION < QT_VERSION_CHECK(5,0,0) prevEventFilter = QAbstractEventDispatcher::instance()->setEventFilter(eventFilter); #else QAbstractEventDispatcher::instance()->installNativeEventFilter(this); #endif -#endif // Q_OS_MAC +#endif // Q_OS_MAC } QxtGlobalShortcutPrivate::~QxtGlobalShortcutPrivate() { #ifndef Q_OS_MAC - if (!--ref) + if (!--ref) #if QT_VERSION < QT_VERSION_CHECK(5,0,0) QAbstractEventDispatcher::instance()->setEventFilter(prevEventFilter); #else QAbstractEventDispatcher::instance()->removeNativeEventFilter(this); #endif -#endif // Q_OS_MAC +#endif // Q_OS_MAC } bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut) diff --git a/3rdparty/qxt/qxtglobalshortcut_p.h b/3rdparty/qxt/qxtglobalshortcut_p.h index 14088c457..98c6cd543 100644 --- a/3rdparty/qxt/qxtglobalshortcut_p.h +++ b/3rdparty/qxt/qxtglobalshortcut_p.h @@ -67,7 +67,7 @@ public: #else virtual bool nativeEventFilter(const QByteArray & eventType, void * message, long * result); #endif // QT_VERSION < QT_VERSION_CHECK(5,0,0) -#endif // Q_OS_MAC +#endif // Q_OS_MAC static void activateShortcut(quint32 nativeKey, quint32 nativeMods); diff --git a/src/core/gnomeglobalshortcutbackend.cpp b/src/core/gnomeglobalshortcutbackend.cpp index 2d151dae4..a0205cc9f 100644 --- a/src/core/gnomeglobalshortcutbackend.cpp +++ b/src/core/gnomeglobalshortcutbackend.cpp @@ -18,10 +18,10 @@ */ #include "config.h" -#include "gnomeglobalshortcutbackend.h" -#include "globalshortcuts.h" #include "core/closure.h" #include "core/logging.h" +#include "globalshortcuts.h" +#include "gnomeglobalshortcutbackend.h" #ifdef HAVE_DBUS #include diff --git a/src/covers/albumcoverloader.cpp b/src/covers/albumcoverloader.cpp index 214fc8243..a04cd923a 100644 --- a/src/covers/albumcoverloader.cpp +++ b/src/covers/albumcoverloader.cpp @@ -35,7 +35,7 @@ #include "core/utilities.h" #include "internet/core/internetmodel.h" #ifdef HAVE_SPOTIFY -# include "internet/spotify/spotifyservice.h" +#include "internet/spotify/spotifyservice.h" #endif AlbumCoverLoader::AlbumCoverLoader(QObject* parent) diff --git a/src/covers/albumcoverloader.h b/src/covers/albumcoverloader.h index e2b44cde4..c5fae6b4c 100644 --- a/src/covers/albumcoverloader.h +++ b/src/covers/albumcoverloader.h @@ -21,8 +21,8 @@ #ifndef COVERS_ALBUMCOVERLOADER_H_ #define COVERS_ALBUMCOVERLOADER_H_ -#include "config.h" #include "albumcoverloaderoptions.h" +#include "config.h" #include "core/song.h" #include From caedd6bcf437cfcbecb2be19bd58aae4b3ac03a1 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Sat, 17 Nov 2018 16:00:32 +0100 Subject: [PATCH 071/104] Allow build without alsa on linux --- CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index acd25175a..a6f0c0aa3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,16 +48,12 @@ find_package(Gettext REQUIRED) find_package(PkgConfig REQUIRED) find_package(Protobuf REQUIRED) find_package(FFTW3) +find_package(ALSA) if(LINUX) - find_package(ALSA REQUIRED) pkg_check_modules(DBUS REQUIRED dbus-1) else(LINUX) - find_package(ALSA) pkg_check_modules(DBUS dbus-1) endif(LINUX) -if(ALSA_FOUND) - set(HAVE_ALSA ON) -endif() if (NOT APPLE) find_package(X11) endif() @@ -329,6 +325,10 @@ optional_component(SPARKLE ON "Sparkle integration" DEPENDS "Sparkle" SPARKLE ) +optional_component(ALSA ON "ALSA integration" + DEPENDS "ALSA" ALSA_FOUND +) + optional_component(LIBPULSE ON "Pulse audio integration" DEPENDS "libpulse" LIBPULSE_FOUND ) From 4321ecf7d26c5eed577a97d230786bb9f56ea37f Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Sat, 17 Nov 2018 16:13:00 +0100 Subject: [PATCH 072/104] Make dbus optional to please CI --- CMakeLists.txt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a6f0c0aa3..e0c72ebc4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,11 +49,7 @@ find_package(PkgConfig REQUIRED) find_package(Protobuf REQUIRED) find_package(FFTW3) find_package(ALSA) -if(LINUX) - pkg_check_modules(DBUS REQUIRED dbus-1) -else(LINUX) - pkg_check_modules(DBUS dbus-1) -endif(LINUX) +pkg_check_modules(DBUS dbus-1) if (NOT APPLE) find_package(X11) endif() From 647279a0002dd7cf4bf847c55009f29cb938314c Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Sun, 18 Nov 2018 20:16:41 +0100 Subject: [PATCH 073/104] Move spotifyimages out of spotify support --- src/CMakeLists.txt | 4 ++-- src/songinfo/artistinfoview.cpp | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9d0df7a78..34f65a33e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -301,6 +301,7 @@ set(SOURCES songinfo/songkickconcerts.cpp songinfo/songkickconcertwidget.cpp songinfo/songplaystats.cpp + songinfo/spotifyimages.cpp songinfo/streamdiscoverer.cpp songinfo/taglyricsinfoprovider.cpp songinfo/ultimatelyricslyric.cpp @@ -589,6 +590,7 @@ set(HEADERS songinfo/songkickconcerts.h songinfo/songkickconcertwidget.h songinfo/songplaystats.h + songinfo/spotifyimages.h songinfo/streamdiscoverer.h songinfo/taglyricsinfoprovider.h songinfo/ultimatelyricslyric.h @@ -838,13 +840,11 @@ optional_source(HAVE_SPOTIFY internet/spotify/spotifyservice.cpp internet/spotify/spotifysettingspage.cpp globalsearch/spotifysearchprovider.cpp - songinfo/spotifyimages.cpp HEADERS globalsearch/spotifysearchprovider.h internet/spotify/spotifyserver.h internet/spotify/spotifyservice.h internet/spotify/spotifysettingspage.h - songinfo/spotifyimages.h UI internet/spotify/spotifysettingspage.ui ) diff --git a/src/songinfo/artistinfoview.cpp b/src/songinfo/artistinfoview.cpp index 735a2b460..af1f5d0c4 100644 --- a/src/songinfo/artistinfoview.cpp +++ b/src/songinfo/artistinfoview.cpp @@ -21,15 +21,11 @@ #include "songinfo/songinfofetcher.h" #include "songinfo/songkickconcerts.h" #include "widgets/prettyimageview.h" -#ifdef HAVE_SPOTIFY #include "songinfo/spotifyimages.h" -#endif ArtistInfoView::ArtistInfoView(QWidget* parent) : SongInfoBase(parent) { fetcher_->AddProvider(new SongkickConcerts); -#ifdef HAVE_SPOTIFY fetcher_->AddProvider(new SpotifyImages); -#endif fetcher_->AddProvider(new ArtistBiography); } From 2affbafa9a8d4d063071c867c9414d23eeba1f76 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Tue, 20 Nov 2018 01:12:14 +0100 Subject: [PATCH 074/104] Fix libspotify depend --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e0c72ebc4..41e4dbabc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -309,7 +309,7 @@ optional_component(SPOTIFY ON "Spotify support" optional_component(SPOTIFY_BLOB ON "Spotify support: non-GPL binary helper" DEPENDS "spotify support" HAVE_SPOTIFY DEPENDS "protobuf" PROTOBUF_FOUND PROTOBUF_PROTOC_EXECUTABLE - DEPENDS "libspotify" SPOTIFY_FOUND + DEPENDS "libspotify" LIBSPOTIFY_FOUND ) optional_component(MOODBAR ON "Moodbar support" From d260c8b6d8c876280f8ac883870916bdf4b64df5 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Thu, 29 Nov 2018 22:33:52 +0100 Subject: [PATCH 075/104] Fix saving playlist columns (#6222) --- src/playlist/playlistview.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/playlist/playlistview.cpp b/src/playlist/playlistview.cpp index 9966cb997..63a8b4b49 100644 --- a/src/playlist/playlistview.cpp +++ b/src/playlist/playlistview.cpp @@ -150,6 +150,12 @@ PlaylistView::PlaylistView(QWidget* parent) currenttrack_pause_ = currenttrack_pause.pixmap(currenttrack_pause.actualSize(QSize(32, 32))); + connect(header_, SIGNAL(sectionResized(int, int, int)), SLOT(SaveGeometry())); + connect(header_, SIGNAL(sectionMoved(int, int, int)), SLOT(SaveGeometry())); + connect(header_, SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), + SLOT(SaveGeometry())); + connect(header_, SIGNAL(SectionVisibilityChanged(int, bool)), + SLOT(SaveGeometry())); connect(header_, SIGNAL(SectionRatingLockStatusChanged(bool)), SLOT(SetRatingLockStatus(bool))); connect(header_, SIGNAL(sectionResized(int, int, int)), @@ -282,7 +288,7 @@ void PlaylistView::SetPlaylist(Playlist* playlist) { } playlist_ = playlist; - if (!header_loaded_) LoadGeometry(); + LoadGeometry(); LoadRatingLockStatus(); ReloadSettings(); DynamicModeChanged(playlist->is_dynamic()); @@ -408,7 +414,7 @@ void PlaylistView::LoadRatingLockStatus() { } void PlaylistView::SaveGeometry() { - if (read_only_settings_) return; + if (read_only_settings_ || !header_loaded_) return; QSettings settings; settings.beginGroup(Playlist::kSettingsGroup); @@ -1183,6 +1189,7 @@ void PlaylistView::SaveSettings() { void PlaylistView::StretchChanged(bool stretch) { setHorizontalScrollBarPolicy(stretch ? Qt::ScrollBarAlwaysOff : Qt::ScrollBarAsNeeded); + SaveGeometry(); } void PlaylistView::DynamicModeChanged(bool dynamic) { From 1d954f2eb127e94f9095898a94984cc9f0b7d7ed Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Thu, 29 Nov 2018 23:31:38 +0100 Subject: [PATCH 076/104] Fix USE_BUNDLE appearing twice --- CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 82b310034..e660a376a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -346,11 +346,6 @@ if (APPLE AND USE_BUNDLE AND NOT USE_BUNDLE_DIR) set(USE_BUNDLE_DIR "../PlugIns") endif() -option(USE_BUNDLE "Bundle macos/windows dependencies" ON) -if (APPLE AND USE_BUNDLE AND NOT USE_BUNDLE_DIR) - set(USE_BUNDLE_DIR "../PlugIns") -endif() - if(CRYPTOPP_FOUND) set(HAVE_CRYPTOPP ON) if(HAVE_SPOTIFY) From f579422643b07c3b48e89cb76cf61d68ca8b2f13 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Fri, 30 Nov 2018 20:43:21 +0100 Subject: [PATCH 077/104] Fix formatting --- 3rdparty/qxt/qxtglobalshortcut_mac.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/3rdparty/qxt/qxtglobalshortcut_mac.cpp b/3rdparty/qxt/qxtglobalshortcut_mac.cpp index 048711fcb..0b5137685 100644 --- a/3rdparty/qxt/qxtglobalshortcut_mac.cpp +++ b/3rdparty/qxt/qxtglobalshortcut_mac.cpp @@ -15,7 +15,8 @@ ** names of its contributors may be used to endorse or promote products ** derived from this software without specific prior written permission. ** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +*AND ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ** DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY From 1f87535c2fdaf2d70bb92783d3c05449d0f6cd24 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Mon, 3 Dec 2018 01:45:20 +0100 Subject: [PATCH 078/104] Replace sha2 with QCryptographicHash (#6230) --- 3rdparty/sha2/CMakeLists.txt | 3 - 3rdparty/sha2/sha2.cpp | 588 ----------------------------------- 3rdparty/sha2/sha2.h | 79 ----- CMakeLists.txt | 14 - src/CMakeLists.txt | 2 - src/core/utilities.cpp | 27 +- src/core/utilities.h | 1 - 7 files changed, 4 insertions(+), 710 deletions(-) delete mode 100644 3rdparty/sha2/CMakeLists.txt delete mode 100644 3rdparty/sha2/sha2.cpp delete mode 100644 3rdparty/sha2/sha2.h diff --git a/3rdparty/sha2/CMakeLists.txt b/3rdparty/sha2/CMakeLists.txt deleted file mode 100644 index 3a5da0a2f..000000000 --- a/3rdparty/sha2/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -cmake_minimum_required(VERSION 2.6) - -add_library(sha2 STATIC sha2.cpp) diff --git a/3rdparty/sha2/sha2.cpp b/3rdparty/sha2/sha2.cpp deleted file mode 100644 index caeed14cf..000000000 --- a/3rdparty/sha2/sha2.cpp +++ /dev/null @@ -1,588 +0,0 @@ -/* - * FILE: sha2.c - * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ - * - * Copyright (c) 2000-2001, Aaron D. Gifford - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include /* memcpy()/memset() or bcopy()/bzero() */ -#include /* assert() */ -#include "sha2.h" - -/* - * ASSERT NOTE: - * Some sanity checking code is included using assert(). On my FreeBSD - * system, this additional code can be removed by compiling with NDEBUG - * defined. Check your own systems manpage on assert() to see how to - * compile WITHOUT the sanity checking code on your system. - * - * UNROLLED TRANSFORM LOOP NOTE: - * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform - * loop version for the hash transform rounds (defined using macros - * later in this file). Either define on the command line, for example: - * - * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c - * - * or define below: - * - * #define SHA2_UNROLL_TRANSFORM - * - */ - - -/*** SHA-256/384/512 Machine Architecture Definitions *****************/ -/* - * BYTE_ORDER NOTE: - * - * Please make sure that your system defines BYTE_ORDER. If your - * architecture is little-endian, make sure it also defines - * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are - * equivilent. - * - * If your system does not define the above, then you can do so by - * hand like this: - * - * #define LITTLE_ENDIAN 1234 - * #define BIG_ENDIAN 4321 - * - * And for little-endian machines, add: - * - * #define BYTE_ORDER LITTLE_ENDIAN - * - * Or for big-endian machines: - * - * #define BYTE_ORDER BIG_ENDIAN - * - * The FreeBSD machine this was written on defines BYTE_ORDER - * appropriately by including (which in turn includes - * where the appropriate definitions are actually - * made). - */ -#ifdef __MINGW32__ -#include -#endif - -#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) -#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN -#endif - -namespace clementine_sha2 { - -/* - * Define the followingsha2_* types to types of the correct length on - * the native archtecture. Most BSD systems and Linux define u_intXX_t - * types. Machines with very recent ANSI C headers, can use the - * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H - * during compile or in the sha.h header file. - * - * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t - * will need to define these three typedefs below (and the appropriate - * ones in sha.h too) by hand according to their system architecture. - * - * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t - * types and pointing out recent ANSI C support for uintXX_t in inttypes.h. - */ -#ifdef SHA2_USE_INTTYPES_H - -typedef uint8_t sha2_byte; /* Exactly 1 byte */ -typedef uint32_t sha2_word32; /* Exactly 4 bytes */ -typedef uint64_t sha2_word64; /* Exactly 8 bytes */ - -#else /* SHA2_USE_INTTYPES_H */ - -typedef u_int8_t sha2_byte; /* Exactly 1 byte */ -typedef u_int32_t sha2_word32; /* Exactly 4 bytes */ -typedef u_int64_t sha2_word64; /* Exactly 8 bytes */ - -#endif /* SHA2_USE_INTTYPES_H */ - - -/*** SHA-256/384/512 Various Length Definitions ***********************/ -/* NOTE: Most of these are in sha2.h */ -#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) - - -/*** ENDIAN REVERSAL MACROS *******************************************/ -#if BYTE_ORDER == LITTLE_ENDIAN -#define REVERSE32(w,x) { \ - sha2_word32 tmp = (w); \ - tmp = (tmp >> 16) | (tmp << 16); \ - (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ -} -#define REVERSE64(w,x) { \ - sha2_word64 tmp = (w); \ - tmp = (tmp >> 32) | (tmp << 32); \ - tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ - ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ - (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ - ((tmp & 0x0000ffff0000ffffULL) << 16); \ -} -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - -/* - * Macro for incrementally adding the unsigned 64-bit integer n to the - * unsigned 128-bit integer (represented using a two-element array of - * 64-bit words): - */ -#define ADDINC128(w,n) { \ - (w)[0] += (sha2_word64)(n); \ - if ((w)[0] < (n)) { \ - (w)[1]++; \ - } \ -} - -/* - * Macros for copying blocks of memory and for zeroing out ranges - * of memory. Using these macros makes it easy to switch from - * using memset()/memcpy() and using bzero()/bcopy(). - * - * Please define either SHA2_USE_MEMSET_MEMCPY or define - * SHA2_USE_BZERO_BCOPY depending on which function set you - * choose to use: - */ -#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY) -/* Default to memset()/memcpy() if no option is specified */ -#define SHA2_USE_MEMSET_MEMCPY 1 -#endif -#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY) -/* Abort with an error if BOTH options are defined */ -#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both! -#endif - -#ifdef SHA2_USE_MEMSET_MEMCPY -#define MEMSET_BZERO(p,l) memset((p), 0, (l)) -#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) -#endif -#ifdef SHA2_USE_BZERO_BCOPY -#define MEMSET_BZERO(p,l) bzero((p), (l)) -#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l)) -#endif - - -/*** THE SIX LOGICAL FUNCTIONS ****************************************/ -/* - * Bit shifting and rotation (used by the six SHA-XYZ logical functions: - * - * NOTE: The naming of R and S appears backwards here (R is a SHIFT and - * S is a ROTATION) because the SHA-256/384/512 description document - * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this - * same "backwards" definition. - */ -/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ -#define R(b,x) ((x) >> (b)) -/* 32-bit Rotate-right (used in SHA-256): */ -#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) - -/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ -#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) -#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) - -/* Four of six logical functions used in SHA-256: */ -#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) -#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) -#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) -#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) - -/*** INTERNAL FUNCTION PROTOTYPES *************************************/ -/* NOTE: These should not be accessed directly from outside this - * library -- they are intended for private internal visibility/use - * only. - */ -void SHA256_Transform(SHA256_CTX*, const sha2_word32*); - - -/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ -/* Hash constant words K for SHA-256: */ -const static sha2_word32 K256[64] = { - 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, - 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, - 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, - 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, - 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, - 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, - 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, - 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, - 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, - 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, - 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, - 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, - 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, - 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, - 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, - 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL -}; - -/* Initial hash value H for SHA-256: */ -const static sha2_word32 sha256_initial_hash_value[8] = { - 0x6a09e667UL, - 0xbb67ae85UL, - 0x3c6ef372UL, - 0xa54ff53aUL, - 0x510e527fUL, - 0x9b05688cUL, - 0x1f83d9abUL, - 0x5be0cd19UL -}; - - -/* - * Constant used by SHA256/384/512_End() functions for converting the - * digest to a readable hexadecimal character string: - */ -static const char *sha2_hex_digits = "0123456789abcdef"; - - -/*** SHA-256: *********************************************************/ -void SHA256_Init(SHA256_CTX* context) { - if (context == (SHA256_CTX*)0) { - return; - } - MEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH); - MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH); - context->bitcount = 0; -} - -#ifdef SHA2_UNROLL_TRANSFORM - -/* Unrolled SHA-256 round macros: */ - -#if BYTE_ORDER == LITTLE_ENDIAN - -#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ - REVERSE32(*data++, W256[j]); \ - T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ - K256[j] + W256[j]; \ - (d) += T1; \ - (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ - j++ - - -#else /* BYTE_ORDER == LITTLE_ENDIAN */ - -#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ - T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ - K256[j] + (W256[j] = *data++); \ - (d) += T1; \ - (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ - j++ - -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - -#define ROUND256(a,b,c,d,e,f,g,h) \ - s0 = W256[(j+1)&0x0f]; \ - s0 = sigma0_256(s0); \ - s1 = W256[(j+14)&0x0f]; \ - s1 = sigma1_256(s1); \ - T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \ - (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ - (d) += T1; \ - (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ - j++ - -void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) { - sha2_word32 a, b, c, d, e, f, g, h, s0, s1; - sha2_word32 T1, *W256; - int j; - - W256 = (sha2_word32*)context->buffer; - - /* Initialize registers with the prev. intermediate value */ - a = context->state[0]; - b = context->state[1]; - c = context->state[2]; - d = context->state[3]; - e = context->state[4]; - f = context->state[5]; - g = context->state[6]; - h = context->state[7]; - - j = 0; - do { - /* Rounds 0 to 15 (unrolled): */ - ROUND256_0_TO_15(a,b,c,d,e,f,g,h); - ROUND256_0_TO_15(h,a,b,c,d,e,f,g); - ROUND256_0_TO_15(g,h,a,b,c,d,e,f); - ROUND256_0_TO_15(f,g,h,a,b,c,d,e); - ROUND256_0_TO_15(e,f,g,h,a,b,c,d); - ROUND256_0_TO_15(d,e,f,g,h,a,b,c); - ROUND256_0_TO_15(c,d,e,f,g,h,a,b); - ROUND256_0_TO_15(b,c,d,e,f,g,h,a); - } while (j < 16); - - /* Now for the remaining rounds to 64: */ - do { - ROUND256(a,b,c,d,e,f,g,h); - ROUND256(h,a,b,c,d,e,f,g); - ROUND256(g,h,a,b,c,d,e,f); - ROUND256(f,g,h,a,b,c,d,e); - ROUND256(e,f,g,h,a,b,c,d); - ROUND256(d,e,f,g,h,a,b,c); - ROUND256(c,d,e,f,g,h,a,b); - ROUND256(b,c,d,e,f,g,h,a); - } while (j < 64); - - /* Compute the current intermediate hash value */ - context->state[0] += a; - context->state[1] += b; - context->state[2] += c; - context->state[3] += d; - context->state[4] += e; - context->state[5] += f; - context->state[6] += g; - context->state[7] += h; - - /* Clean up */ - a = b = c = d = e = f = g = h = T1 = 0; -} - -#else /* SHA2_UNROLL_TRANSFORM */ - -void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) { - sha2_word32 a, b, c, d, e, f, g, h, s0, s1; - sha2_word32 T1, T2, *W256; - int j; - - W256 = (sha2_word32*)context->buffer; - - /* Initialize registers with the prev. intermediate value */ - a = context->state[0]; - b = context->state[1]; - c = context->state[2]; - d = context->state[3]; - e = context->state[4]; - f = context->state[5]; - g = context->state[6]; - h = context->state[7]; - - j = 0; - do { -#if BYTE_ORDER == LITTLE_ENDIAN - /* Copy data while converting to host byte order */ - REVERSE32(*data++,W256[j]); - /* Apply the SHA-256 compression function to update a..h */ - T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; -#else /* BYTE_ORDER == LITTLE_ENDIAN */ - /* Apply the SHA-256 compression function to update a..h with copy */ - T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++); -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - T2 = Sigma0_256(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 16); - - do { - /* Part of the message block expansion: */ - s0 = W256[(j+1)&0x0f]; - s0 = sigma0_256(s0); - s1 = W256[(j+14)&0x0f]; - s1 = sigma1_256(s1); - - /* Apply the SHA-256 compression function to update a..h */ - T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + - (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); - T2 = Sigma0_256(a) + Maj(a, b, c); - h = g; - g = f; - f = e; - e = d + T1; - d = c; - c = b; - b = a; - a = T1 + T2; - - j++; - } while (j < 64); - - /* Compute the current intermediate hash value */ - context->state[0] += a; - context->state[1] += b; - context->state[2] += c; - context->state[3] += d; - context->state[4] += e; - context->state[5] += f; - context->state[6] += g; - context->state[7] += h; - - /* Clean up */ - a = b = c = d = e = f = g = h = T1 = T2 = 0; -} - -#endif /* SHA2_UNROLL_TRANSFORM */ - -void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) { - unsigned int freespace, usedspace; - - if (len == 0) { - /* Calling with no data is valid - we do nothing */ - return; - } - - /* Sanity check: */ - assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0); - - usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; - if (usedspace > 0) { - /* Calculate how much free space is available in the buffer */ - freespace = SHA256_BLOCK_LENGTH - usedspace; - - if (len >= freespace) { - /* Fill the buffer completely and process it */ - MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); - context->bitcount += freespace << 3; - len -= freespace; - data += freespace; - SHA256_Transform(context, (sha2_word32*)context->buffer); - } else { - /* The buffer is not yet full */ - MEMCPY_BCOPY(&context->buffer[usedspace], data, len); - context->bitcount += len << 3; - /* Clean up: */ - usedspace = freespace = 0; - return; - } - } - while (len >= SHA256_BLOCK_LENGTH) { - /* Process as many complete blocks as we can */ - SHA256_Transform(context, (sha2_word32*)data); - context->bitcount += SHA256_BLOCK_LENGTH << 3; - len -= SHA256_BLOCK_LENGTH; - data += SHA256_BLOCK_LENGTH; - } - if (len > 0) { - /* There's left-overs, so save 'em */ - MEMCPY_BCOPY(context->buffer, data, len); - context->bitcount += len << 3; - } - /* Clean up: */ - usedspace = freespace = 0; -} - -void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) { - sha2_word32 *d = (sha2_word32*)digest; - unsigned int usedspace; - - /* Sanity check: */ - assert(context != (SHA256_CTX*)0); - - /* If no digest buffer is passed, we don't bother doing this: */ - if (digest != (sha2_byte*)0) { - usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH; -#if BYTE_ORDER == LITTLE_ENDIAN - /* Convert FROM host byte order */ - REVERSE64(context->bitcount,context->bitcount); -#endif - if (usedspace > 0) { - /* Begin padding with a 1 bit: */ - context->buffer[usedspace++] = 0x80; - - if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { - /* Set-up for the last transform: */ - MEMSET_BZERO(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace); - } else { - if (usedspace < SHA256_BLOCK_LENGTH) { - MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace); - } - /* Do second-to-last transform: */ - SHA256_Transform(context, (sha2_word32*)context->buffer); - - /* And set-up for the last transform: */ - MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); - } - } else { - /* Set-up for the last transform: */ - MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); - - /* Begin padding with a 1 bit: */ - *context->buffer = 0x80; - } - /* Set the bit count: */ - *(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount; - - /* Final transform: */ - SHA256_Transform(context, (sha2_word32*)context->buffer); - -#if BYTE_ORDER == LITTLE_ENDIAN - { - /* Convert TO host byte order */ - int j; - for (j = 0; j < 8; j++) { - REVERSE32(context->state[j],context->state[j]); - *d++ = context->state[j]; - } - } -#else - MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH); -#endif - } - - /* Clean up state data: */ - MEMSET_BZERO(context, sizeof(SHA256_CTX)); - usedspace = 0; -} - -char *SHA256_End(SHA256_CTX* context, char buffer[]) { - sha2_byte digest[SHA256_DIGEST_LENGTH], *d = digest; - int i; - - /* Sanity check: */ - assert(context != (SHA256_CTX*)0); - - if (buffer != (char*)0) { - SHA256_Final(digest, context); - - for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { - *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; - *buffer++ = sha2_hex_digits[*d & 0x0f]; - d++; - } - *buffer = (char)0; - } else { - MEMSET_BZERO(context, sizeof(SHA256_CTX)); - } - MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH); - return buffer; -} - -char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) { - SHA256_CTX context; - - SHA256_Init(&context); - SHA256_Update(&context, data, len); - return SHA256_End(&context, digest); -} - -} // namespace clementine_sha2 diff --git a/3rdparty/sha2/sha2.h b/3rdparty/sha2/sha2.h deleted file mode 100644 index 836da77f6..000000000 --- a/3rdparty/sha2/sha2.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * FILE: sha2.h - * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ - * - * Copyright (c) 2000-2001, Aaron D. Gifford - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $ - */ - -#ifndef __CLEMENTINE_SHA2_H__ -#define __CLEMENTINE_SHA2_H__ - -/* - * Import u_intXX_t size_t type definitions from system headers. You - * may need to change this, or define these things yourself in this - * file. - */ -#include - -namespace clementine_sha2 { - -/*** SHA-256/384/512 Various Length Definitions ***********************/ -static const int SHA256_BLOCK_LENGTH = 64; -static const int SHA256_DIGEST_LENGTH = 32; -static const int SHA256_DIGEST_STRING_LENGTH = (SHA256_DIGEST_LENGTH * 2 + 1); - - -/*** SHA-256/384/512 Context Structures *******************************/ -/* NOTE: If your architecture does not define either u_intXX_t types or - * uintXX_t (from inttypes.h), you may need to define things by hand - * for your system: - */ -#ifdef __MINGW32__ -typedef unsigned char u_int8_t; /* 1-byte (8-bits) */ -typedef unsigned int u_int32_t; /* 4-bytes (32-bits) */ -typedef unsigned long long u_int64_t; /* 8-bytes (64-bits) */ -#endif - -typedef struct _SHA256_CTX { - u_int32_t state[8]; - u_int64_t bitcount; - u_int8_t buffer[SHA256_BLOCK_LENGTH]; -} SHA256_CTX; - - -void SHA256_Init(SHA256_CTX *); -void SHA256_Update(SHA256_CTX*, const u_int8_t*, size_t); -void SHA256_Final(u_int8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*); -char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]); -char* SHA256_Data(const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]); - -} // namespace clementine_sha2 - -#endif /* __CLEMENTINE_SHA2_H__ */ diff --git a/CMakeLists.txt b/CMakeLists.txt index e660a376a..dbc2c96e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -435,20 +435,6 @@ if(GMOCK_INCLUDE_DIRS) endif(GTEST_INCLUDE_DIRS) endif(GMOCK_INCLUDE_DIRS) -# Use the system's sha2 if it's available. -find_path(SHA2_INCLUDE_DIRS sha2.h) -find_library(SHA2_LIBRARIES sha2) -if(SHA2_LIBRARIES AND SHA2_INCLUDE_DIRS) - message(STATUS "Using system sha2 library") - set(USE_SYSTEM_SHA2 ON) -else() - message(STATUS "Using builtin sha2 library") - set(USE_SYSTEM_SHA2 OFF) - add_subdirectory(3rdparty/sha2) - set(SHA2_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/sha2) - set(SHA2_LIBRARIES sha2) -endif() - # Use the system libmygpo-qt5 if a recent enough version was found if(LIBMYGPO_QT5_FOUND) set(MYGPOQT5_LIBRARIES ${LIBMYGPO_QT5_LIBRARIES}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0eb14e28c..76654a4c3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,7 +25,6 @@ include_directories(${GOBJECT_INCLUDE_DIRS}) include_directories(${QTSINGLEAPPLICATION_INCLUDE_DIRS}) include_directories(${QTIOCOMPRESSOR_INCLUDE_DIRS}) include_directories(${QXT_INCLUDE_DIRS}) -include_directories(${SHA2_INCLUDE_DIRS}) include_directories(${CHROMAPRINT_INCLUDE_DIRS}) include_directories(${MYGPOQT5_INCLUDE_DIRS}) @@ -1245,7 +1244,6 @@ target_link_libraries(clementine_lib libclementine-common libclementine-tagreader libclementine-remote - ${SHA2_LIBRARIES} ${TAGLIB_LIBRARIES} ${MYGPOQT5_LIBRARIES} ${CHROMAPRINT_LIBRARIES} diff --git a/src/core/utilities.cpp b/src/core/utilities.cpp index 2c6774fc3..fe106e2b7 100644 --- a/src/core/utilities.cpp +++ b/src/core/utilities.cpp @@ -52,8 +52,6 @@ #include "config.h" #include "timeconstants.h" -#include "sha2.h" - #if defined(Q_OS_UNIX) #include #elif defined(Q_OS_WIN32) @@ -469,7 +467,10 @@ QByteArray Hmac(const QByteArray& key, const QByteArray& data, QCryptographicHash::Sha1), QCryptographicHash::Sha1); } else { // Sha256_Algo, currently default - return Sha256(outer_padding + Sha256(inner_padding + data)); + return QCryptographicHash::hash( + outer_padding + QCryptographicHash::hash(inner_padding + data, + QCryptographicHash::Sha256), + QCryptographicHash::Sha256); } } @@ -485,26 +486,6 @@ QByteArray HmacSha1(const QByteArray& key, const QByteArray& data) { return Hmac(key, data, Sha1_Algo); } -QByteArray Sha256(const QByteArray& data) { -#ifndef USE_SYSTEM_SHA2 - using clementine_sha2::SHA256_CTX; - using clementine_sha2::SHA256_Init; - using clementine_sha2::SHA256_Update; - using clementine_sha2::SHA256_Final; - using clementine_sha2::SHA256_DIGEST_LENGTH; -#endif - - SHA256_CTX context; - SHA256_Init(&context); - SHA256_Update(&context, reinterpret_cast(data.constData()), - data.length()); - - QByteArray ret(SHA256_DIGEST_LENGTH, '\0'); - SHA256_Final(reinterpret_cast(ret.data()), &context); - - return ret; -} - // File must not be open and will be closed afterwards! QByteArray Sha1File(QFile& file) { file.open(QIODevice::ReadOnly); diff --git a/src/core/utilities.h b/src/core/utilities.h index 7345a1140..021ded6cf 100644 --- a/src/core/utilities.h +++ b/src/core/utilities.h @@ -74,7 +74,6 @@ QByteArray Hmac(const QByteArray& key, const QByteArray& data, QByteArray HmacMd5(const QByteArray& key, const QByteArray& data); QByteArray HmacSha256(const QByteArray& key, const QByteArray& data); QByteArray HmacSha1(const QByteArray& key, const QByteArray& data); -QByteArray Sha256(const QByteArray& data); QByteArray Sha1File(QFile& file); QByteArray Sha1CoverHash(const QString& artist, const QString& album); From 453270c8b5015f39a44fd34c659e811c6b8048cf Mon Sep 17 00:00:00 2001 From: John Maguire Date: Wed, 5 Dec 2018 18:16:34 +0100 Subject: [PATCH 079/104] Fixes for compiling against qt5 on mac --- 3rdparty/libmygpo-qt5/src/CMakeLists.txt | 3 +-- 3rdparty/qocoa/CMakeLists.txt | 2 +- CMakeLists.txt | 6 ------ dist/macdeploy.py | 23 ++++++++++++++++------- ext/clementine-tagreader/CMakeLists.txt | 4 ++-- ext/libclementine-common/CMakeLists.txt | 5 ++--- src/CMakeLists.txt | 15 ++++++++++++--- 7 files changed, 34 insertions(+), 24 deletions(-) diff --git a/3rdparty/libmygpo-qt5/src/CMakeLists.txt b/3rdparty/libmygpo-qt5/src/CMakeLists.txt index c15771c3e..5098160aa 100644 --- a/3rdparty/libmygpo-qt5/src/CMakeLists.txt +++ b/3rdparty/libmygpo-qt5/src/CMakeLists.txt @@ -84,5 +84,4 @@ QT_WRAP_CPP(LIBMYGPO_QT_MOC_SRC ${LIBMYGPO_QT_MOC_H} ) add_library( ${MYGPO_QT_TARGET_NAME} STATIC ${LIBMYGPO_QT_SRC} ${LIBMYGPO_QT_MOC_SRC} ) -target_link_libraries( ${MYGPO_QT_TARGET_NAME} ${QJSON_LIBRARIES} ${QT_QTCORE_LIBRARY} ${QT_QTNETWORK_LIBRARY} ) -target_link_libraries( ${MYGPO_QT_TARGET_NAME} Qt5::Core Qt5::Network ) +target_link_libraries( ${MYGPO_QT_TARGET_NAME} ${QJSON_LIBRARIES} Qt5::Core Qt5::Network ) diff --git a/3rdparty/qocoa/CMakeLists.txt b/3rdparty/qocoa/CMakeLists.txt index b3b7fa4aa..a52ee2e24 100644 --- a/3rdparty/qocoa/CMakeLists.txt +++ b/3rdparty/qocoa/CMakeLists.txt @@ -29,4 +29,4 @@ endif() add_library(Qocoa STATIC ${SOURCES} ${MOC_SOURCES} ${RESOURCES_SOURCES} ) -target_link_libraries(Qocoa ${QT_LIBRARIES}) +target_link_libraries(Qocoa Qt5::Widgets Qt5::MacExtras) diff --git a/CMakeLists.txt b/CMakeLists.txt index dbc2c96e0..c8130577e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,12 +35,6 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") set(FREEBSD ON) endif() -if(APPLE) - if(NOT QT_MAC_USE_COCOA) - message(FATAL_ERROR "Cocoa support is required") - endif(NOT QT_MAC_USE_COCOA) -endif(APPLE) - set(OpenGL_GL_PREFERENCE LEGACY) find_package(OpenGL) if(OPENGL_FOUND) diff --git a/dist/macdeploy.py b/dist/macdeploy.py index 3371eaed7..08fa5ca7e 100755 --- a/dist/macdeploy.py +++ b/dist/macdeploy.py @@ -30,6 +30,11 @@ FRAMEWORK_SEARCH_PATH = [ os.path.join(os.environ['HOME'], 'Library/Frameworks') ] +STRIP_PREFIX = [ + '@@HOMEBREW_PREFIX@@/opt/qt5/lib/', + '@@HOMEBREW_CELLAR@@/qt5/5.8.0_1/lib/', +] + LIBRARY_SEARCH_PATH = ['/target', '/target/lib', '/usr/local/lib', '/sw/lib'] GSTREAMER_PLUGINS = [ @@ -54,7 +59,7 @@ GSTREAMER_PLUGINS = [ 'libgstapetag.so', 'libgstasf.so', 'libgstaudioparsers.so', - 'libgstfaac.so', + #'libgstfaac.so', 'libgstfaad.so', 'libgstflac.so', 'libgstid3demux.so', @@ -94,16 +99,16 @@ GSTREAMER_SEARCH_PATH = [ ] QT_PLUGINS = [ - 'accessible/libqtaccessiblewidgets.dylib', - 'codecs/libqcncodecs.dylib', - 'codecs/libqjpcodecs.dylib', - 'codecs/libqkrcodecs.dylib', - 'codecs/libqtwcodecs.dylib', + #'accessible/libqtaccessiblewidgets.dylib', + #'codecs/libqcncodecs.dylib', + #'codecs/libqjpcodecs.dylib', + #'codecs/libqkrcodecs.dylib', + #'codecs/libqtwcodecs.dylib', 'iconengines/libqsvgicon.dylib', 'imageformats/libqgif.dylib', 'imageformats/libqico.dylib', 'imageformats/libqjpeg.dylib', - 'imageformats/libqmng.dylib', + #'imageformats/libqmng.dylib', 'imageformats/libqsvg.dylib', ] QT_PLUGINS_SEARCH_PATH = [ @@ -206,6 +211,10 @@ def GetBrokenLibraries(binary): def FindFramework(path): + for prefix in STRIP_PREFIX: + if path.startswith(prefix): + path = path[len(prefix):] + break for search_path in FRAMEWORK_SEARCH_PATH: abs_path = os.path.join(search_path, path) if os.path.exists(abs_path): diff --git a/ext/clementine-tagreader/CMakeLists.txt b/ext/clementine-tagreader/CMakeLists.txt index d846efecd..855e390cf 100644 --- a/ext/clementine-tagreader/CMakeLists.txt +++ b/ext/clementine-tagreader/CMakeLists.txt @@ -29,8 +29,8 @@ target_link_libraries(clementine-tagreader ${TAGLIB_LIBRARIES} libclementine-common libclementine-tagreader - ${QT_QTCORE_LIBRARY} - ${QT_QTNETWORK_LIBRARY} + Qt5::Core + Qt5::Network z ) diff --git a/ext/libclementine-common/CMakeLists.txt b/ext/libclementine-common/CMakeLists.txt index 200f73c96..694836c9e 100644 --- a/ext/libclementine-common/CMakeLists.txt +++ b/ext/libclementine-common/CMakeLists.txt @@ -35,9 +35,8 @@ add_library(libclementine-common STATIC ) target_link_libraries(libclementine-common - ${QT_LIBRARIES} + Qt5::Core + Qt5::Network ${TAGLIB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ) - -target_link_libraries(libclementine-common Qt5::Core Qt5::Network) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 76654a4c3..88dff3c20 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1244,13 +1244,22 @@ target_link_libraries(clementine_lib libclementine-common libclementine-tagreader libclementine-remote + + Qt5::Concurrent + Qt5::Core + Qt5::Network + Qt5::OpenGL + Qt5::OpenGL + Qt5::Sql + Qt5::Widgets + Qt5::Xml + ${TAGLIB_LIBRARIES} ${MYGPOQT5_LIBRARIES} ${CHROMAPRINT_LIBRARIES} ${GOBJECT_LIBRARIES} ${GLIB_LIBRARIES} ${GIO_LIBRARIES} - ${QT_LIBRARIES} ${GSTREAMER_BASE_LIBRARIES} ${GSTREAMER_LIBRARIES} ${GSTREAMER_APP_LIBRARIES} @@ -1261,8 +1270,9 @@ target_link_libraries(clementine_lib ${QTIOCOMPRESSOR_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${SQLITE_LIBRARIES} - z + Qocoa + z ) if(HAVE_VISUALISATIONS) @@ -1352,7 +1362,6 @@ if (WIN32) ${QTSPARKLE_LIBRARIES} tinysvcmdns dsound - ${QT_QTGUI_LIBRARY} ) endif (WIN32) From 09538d84f250032619d73db0786771570b9062e4 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Wed, 2 Jan 2019 16:02:34 +0100 Subject: [PATCH 080/104] Fix Qt 5 build (#6246) --- 3rdparty/qocoa/CMakeLists.txt | 7 ++++++- src/CMakeLists.txt | 10 +--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/3rdparty/qocoa/CMakeLists.txt b/3rdparty/qocoa/CMakeLists.txt index a52ee2e24..df6ec7c5c 100644 --- a/3rdparty/qocoa/CMakeLists.txt +++ b/3rdparty/qocoa/CMakeLists.txt @@ -29,4 +29,9 @@ endif() add_library(Qocoa STATIC ${SOURCES} ${MOC_SOURCES} ${RESOURCES_SOURCES} ) -target_link_libraries(Qocoa Qt5::Widgets Qt5::MacExtras) + +if(APPLE) + target_link_libraries(Qocoa Qt5::Widgets Qt5::MacExtras) +else() + target_link_libraries(Qocoa Qt5::Widgets) +endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 88dff3c20..95515a30c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1245,21 +1245,13 @@ target_link_libraries(clementine_lib libclementine-tagreader libclementine-remote - Qt5::Concurrent - Qt5::Core - Qt5::Network - Qt5::OpenGL - Qt5::OpenGL - Qt5::Sql - Qt5::Widgets - Qt5::Xml - ${TAGLIB_LIBRARIES} ${MYGPOQT5_LIBRARIES} ${CHROMAPRINT_LIBRARIES} ${GOBJECT_LIBRARIES} ${GLIB_LIBRARIES} ${GIO_LIBRARIES} + ${QT_LIBRARIES} ${GSTREAMER_BASE_LIBRARIES} ${GSTREAMER_LIBRARIES} ${GSTREAMER_APP_LIBRARIES} From 4ff370ce1ef41a8dc9b95a367c23eef43a918ad9 Mon Sep 17 00:00:00 2001 From: Andreas Sturmlechner Date: Wed, 2 Jan 2019 16:03:24 +0100 Subject: [PATCH 081/104] Fix build without Qt5DBus (#6187) * Qt5::Test is not required in the global QT_LIBRARIES definition * Qt5::DBus had already been optional, drop bogus pkgconfig search This partially reverts commit 4321ecf7d26c5eed577a97d230786bb9f56ea37f. * Find X11 only once, in root CMakeLists.txt Since we have HAVE_X11, use HAVE_X11 in cmake. --- 3rdparty/qxt/CMakeLists.txt | 1 - CMakeLists.txt | 23 ++++++++++------------- src/CMakeLists.txt | 1 - 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/3rdparty/qxt/CMakeLists.txt b/3rdparty/qxt/CMakeLists.txt index 8fd9220ae..73c67a9fa 100644 --- a/3rdparty/qxt/CMakeLists.txt +++ b/3rdparty/qxt/CMakeLists.txt @@ -10,7 +10,6 @@ set(QXT-MOC-HEADERS qxtglobalshortcut.h ) -find_package(X11) include_directories(${X11_INCLUDE_DIR}) include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) diff --git a/CMakeLists.txt b/CMakeLists.txt index c8130577e..894448efd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,7 +46,6 @@ find_package(PkgConfig REQUIRED) find_package(Protobuf REQUIRED) find_package(FFTW3) find_package(ALSA) -pkg_check_modules(DBUS dbus-1) if (NOT APPLE) find_package(X11) endif() @@ -90,13 +89,10 @@ find_path(SPARSEHASH_INCLUDE_DIRS google/sparsetable) # QT set(QT_MIN_VERSION 5.6.0) find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Concurrent Widgets Network Sql Xml OpenGL Test) -if(X11_FOUND) +find_package(Qt5DBus ${QT_MIN_VERSION}) +if(HAVE_X11) find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS X11Extras) endif() -if(DBUS_FOUND) - find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS DBus) - get_target_property(QT_DBUSXML2CPP_EXECUTABLE Qt5::qdbusxml2cpp LOCATION) -endif() if(APPLE) find_package(Qt5 REQUIRED COMPONENTS MacExtras) endif() @@ -104,12 +100,13 @@ if(WIN32) find_package(Qt5 REQUIRED COMPONENTS WinExtras) endif() -set(QT_LIBRARIES Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network Qt5::Sql Qt5::Xml Qt5::OpenGL Qt5::Test) +set(QT_LIBRARIES Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network Qt5::Sql Qt5::Xml Qt5::OpenGL) -if(DBUS_FOUND) +if(Qt5DBus_FOUND) set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::DBus) + get_target_property(QT_DBUSXML2CPP_EXECUTABLE Qt5::qdbusxml2cpp LOCATION) endif() -if(X11_FOUND) +if(HAVE_X11) set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::X11Extras) endif() if(APPLE) @@ -280,19 +277,19 @@ optional_component(LIBLASTFM ON "Last.fm support" ) optional_component(DBUS ON "D-Bus support" - DEPENDS "D-Bus" DBUS_FOUND + DEPENDS "Qt5DBus" Qt5DBus_FOUND ) optional_component(WIIMOTEDEV ON "Wiimote support" - DEPENDS "D-Bus support" DBUS_FOUND + DEPENDS "D-Bus support" Qt5DBus_FOUND ) optional_component(DEVICEKIT ON "Devices: DeviceKit backend" - DEPENDS "D-Bus support" DBUS_FOUND + DEPENDS "D-Bus support" Qt5DBus_FOUND ) optional_component(UDISKS2 ON "Devices: UDisks2 backend" - DEPENDS "D-Bus support" DBUS_FOUND + DEPENDS "D-Bus support" Qt5DBus_FOUND ) if (CRYPTOPP_FOUND OR HAVE_SPOTIFY_BLOB) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 95515a30c..8ec05d4d4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1363,7 +1363,6 @@ if (UNIX AND NOT APPLE) # command but they're actually used by libraries that appear after them, so # they end up getting ignored. This appends them to the very end of the link # line, ensuring they're always used. - find_package(X11) if (FREEBSD) target_link_libraries(clementine_lib ${X11_X11_LIB}) else () From 6d50e0b041810ee65b1ad10efeb51651e1e5ff89 Mon Sep 17 00:00:00 2001 From: Martin Delille Date: Tue, 15 Jan 2019 18:54:08 +0100 Subject: [PATCH 082/104] Specify cpp11 compatibility Fix #6199 (#6237) --- ext/libclementine-remote/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/libclementine-remote/CMakeLists.txt b/ext/libclementine-remote/CMakeLists.txt index 5f860fbcd..70761b493 100644 --- a/ext/libclementine-remote/CMakeLists.txt +++ b/ext/libclementine-remote/CMakeLists.txt @@ -1,5 +1,7 @@ include_directories(${PROTOBUF_INCLUDE_DIRS}) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++0x") + set(MESSAGES remotecontrolmessages.proto ) From 89f40ee88f9e6b982aafa7676c4060d6aed488f9 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Fri, 18 Jan 2019 01:47:26 +0100 Subject: [PATCH 083/104] Use QUrlQuery --- src/devices/giolister.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/devices/giolister.cpp b/src/devices/giolister.cpp index 5aac8dfbf..c7e330a14 100644 --- a/src/devices/giolister.cpp +++ b/src/devices/giolister.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "giolister.h" #include "core/logging.h" @@ -187,8 +188,10 @@ QList GioLister::MakeDeviceUrls(const QString& id) { if (url.isValid()) { QRegExp device_re("usb/(\\d+)/(\\d+)"); if (device_re.indexIn(unix_device) >= 0) { - url.addQueryItem("busnum", device_re.cap(1)); - url.addQueryItem("devnum", device_re.cap(2)); + QUrlQuery url_query(url); + url_query.addQueryItem("busnum", device_re.cap(1)); + url_query.addQueryItem("devnum", device_re.cap(2)); + url.setQuery(url_query); } // Special case for file:// GIO URIs - we have to check whether they point From d772c8078db2d7b25b58eb2d1177ca4d09966f53 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Fri, 18 Jan 2019 01:49:17 +0100 Subject: [PATCH 084/104] Fix formatting --- src/devices/giolister.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/devices/giolister.cpp b/src/devices/giolister.cpp index c7e330a14..7021ba427 100644 --- a/src/devices/giolister.cpp +++ b/src/devices/giolister.cpp @@ -22,8 +22,8 @@ #include #include -#include #include +#include #include "giolister.h" #include "core/logging.h" From 85558d242ccb795269654b2ff3bc6ec169b47f3c Mon Sep 17 00:00:00 2001 From: Ali Allaoui Date: Fri, 18 Jan 2019 16:36:52 +0100 Subject: [PATCH 085/104] [qxt] Compil fix for qt version > 5.6 --- 3rdparty/qxt/qxtglobalshortcut_x11.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/3rdparty/qxt/qxtglobalshortcut_x11.cpp b/3rdparty/qxt/qxtglobalshortcut_x11.cpp index 9ddb1e088..1b670e52f 100644 --- a/3rdparty/qxt/qxtglobalshortcut_x11.cpp +++ b/3rdparty/qxt/qxtglobalshortcut_x11.cpp @@ -29,8 +29,11 @@ ** *****************************************************************************/ -#if QT_VERSION < QT_VERSION_CHECK(5,0,0) +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) || QT_VERSION > QT_VERSION_CHECK(5,6,0) # include +#if QT_VERSION > QT_VERSION_CHECK(5,6,0) +# include +#endif #else # include # include @@ -92,7 +95,7 @@ class QxtX11Data { public: QxtX11Data() { -#if QT_VERSION < QT_VERSION_CHECK(5,0,0) +#if QT_VERSION < QT_VERSION_CHECK(5,0,0) || QT_VERSION > QT_VERSION_CHECK(5,6,0) m_display = QX11Info::display(); #else QPlatformNativeInterface *native = qApp->platformNativeInterface(); From 1176d9eb9348a508f8a356da068d58972395c7b7 Mon Sep 17 00:00:00 2001 From: Ali Allaoui Date: Sat, 9 Feb 2019 16:06:16 +0100 Subject: [PATCH 086/104] [qxt] No need to check qt versionat all, Qt 5.6 is required. So just use QX11Info --- 3rdparty/qxt/qxtglobalshortcut_x11.cpp | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/3rdparty/qxt/qxtglobalshortcut_x11.cpp b/3rdparty/qxt/qxtglobalshortcut_x11.cpp index 1b670e52f..5768a017f 100644 --- a/3rdparty/qxt/qxtglobalshortcut_x11.cpp +++ b/3rdparty/qxt/qxtglobalshortcut_x11.cpp @@ -29,16 +29,8 @@ ** *****************************************************************************/ -#if QT_VERSION < QT_VERSION_CHECK(5,0,0) || QT_VERSION > QT_VERSION_CHECK(5,6,0) -# include -#if QT_VERSION > QT_VERSION_CHECK(5,6,0) -# include -#endif -#else -# include -# include -# include -#endif +#include +#include #include #include #include "keymapper_x11.h" @@ -95,14 +87,7 @@ class QxtX11Data { public: QxtX11Data() { -#if QT_VERSION < QT_VERSION_CHECK(5,0,0) || QT_VERSION > QT_VERSION_CHECK(5,6,0) m_display = QX11Info::display(); -#else - QPlatformNativeInterface *native = qApp->platformNativeInterface(); - void *display = native->nativeResourceForScreen(QByteArray("display"), - QGuiApplication::primaryScreen()); - m_display = reinterpret_cast(display); -#endif } bool isValid() From 783dada13e76a7ef1afb64209b2d4e3076a0918e Mon Sep 17 00:00:00 2001 From: Antonio Russo Date: Tue, 22 May 2018 18:28:54 -0400 Subject: [PATCH 087/104] Revert "Blacklist all NVidia drivers" In 2011, there was a bug that caused NVIDIA drivers to hang Clementine on shutdown. In 2012, only some drivers had the fix for this issue. Now, in 2019, we do not need to work around this bug. By reverting commit c2723008a22c5a4c4e307ba9a278fd2162ef6bdb we work around known bad drivers, but do not penalize all NVIDIA users for this ancient bug. --- src/main.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 0ee7a8fa7..ecf47b9d4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -480,7 +480,11 @@ int main(int argc, char* argv[]) { QFile self_maps("/proc/self/maps"); if (self_maps.open(QIODevice::ReadOnly)) { QByteArray data = self_maps.readAll(); - if (data.contains("libnvidia-tls.so.")) { + if (data.contains("libnvidia-tls.so.304.37") || + data.contains("libnvidia-tls.so.285.03") || + data.contains("libnvidia-tls.so.280.13") || + data.contains("libnvidia-tls.so.275.28") || + data.contains("libnvidia-tls.so.275.19")) { qLog(Warning) << "Exiting immediately to work around NVIDIA driver bug"; _exit(ret); } From 40326bb94b8f26779fabd45299609797d1cab7f9 Mon Sep 17 00:00:00 2001 From: Antonio Russo Date: Sun, 21 Apr 2019 20:26:00 -0400 Subject: [PATCH 088/104] setFirstSectionMovable() in playlistview.cpp Qt 5.11 added a function allowing the first column in a list to be set to be movable. Contingent on its availability, make the first column of the playlist viewer draggable. --- src/playlist/playlistview.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/playlist/playlistview.cpp b/src/playlist/playlistview.cpp index 63a8b4b49..2a74e3ed1 100644 --- a/src/playlist/playlistview.cpp +++ b/src/playlist/playlistview.cpp @@ -138,6 +138,9 @@ PlaylistView::PlaylistView(QWidget* parent) dynamic_controls_(new DynamicPlaylistControls(this)) { setHeader(header_); header_->setSectionsMovable(true); +#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) + header_->setFirstSectionMovable(true); +#endif setStyle(style_); setMouseTracking(true); From 9e85eb2c0f356d838a0703f07f9ddef07b67aab9 Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Fri, 26 Apr 2019 20:40:42 +0200 Subject: [PATCH 089/104] Fix gst_buffer_unref assertion in chromaprinter --- src/musicbrainz/chromaprinter.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/musicbrainz/chromaprinter.cpp b/src/musicbrainz/chromaprinter.cpp index aad146b0e..1a4d3ccec 100644 --- a/src/musicbrainz/chromaprinter.cpp +++ b/src/musicbrainz/chromaprinter.cpp @@ -208,12 +208,16 @@ GstFlowReturn Chromaprinter::NewBufferCallback(GstAppSink* app_sink, Chromaprinter* me = reinterpret_cast(self); GstSample* sample = gst_app_sink_pull_sample(app_sink); + if (!sample) return GST_FLOW_ERROR; GstBuffer* buffer = gst_sample_get_buffer(sample); - GstMapInfo map; - gst_buffer_map(buffer, &map, GST_MAP_READ); - me->buffer_.write(reinterpret_cast(map.data), map.size); - gst_buffer_unmap(buffer, &map); - gst_buffer_unref(buffer); + if (buffer) { + GstMapInfo map; + if (gst_buffer_map(buffer, &map, GST_MAP_READ)) { + me->buffer_.write(reinterpret_cast(map.data), map.size); + gst_buffer_unmap(buffer, &map); + } + } + gst_sample_unref(sample); return GST_FLOW_OK; } From c9800a4dc9a345bfa71e1096bbdc7ee0a34e1f28 Mon Sep 17 00:00:00 2001 From: lordlethis Date: Sat, 13 Jul 2019 13:57:27 +0200 Subject: [PATCH 090/104] Fix blank window when restoring from systray (#6351) * Fix blank window when restoring from systray This applies the fix qBittorrent used for this same issue: https://github.com/qbittorrent/qBittorrent/issues/9240, so credit goes to those guys * Fix whitespace --- src/ui/mainwindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 2944d46ec..58419de01 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -1441,7 +1441,7 @@ void MainWindow::closeEvent(QCloseEvent* event) { keep_running = s.value("keeprunning", tray_icon_->IsVisible()).toBool(); if (keep_running && event->spontaneous()) { - event->accept(); + event->ignore(); SetHiddenInTray(true); } else { Exit(); @@ -1454,7 +1454,7 @@ void MainWindow::SetHiddenInTray(bool hidden) { // Some window managers don't remember maximized state between calls to // hide() and show(), so we have to remember it ourself. if (hidden) { - hide(); + QTimer::singleShot(0, this, &QWidget::hide); } else { if (was_maximized_) showMaximized(); From 66fdc935acfd48095037f67d5debc2706702c17b Mon Sep 17 00:00:00 2001 From: Jonas Kvinge Date: Sun, 21 Jul 2019 14:38:15 +0200 Subject: [PATCH 091/104] Fix formatting --- ext/libclementine-tagreader/tagreader.cpp | 2 +- src/engines/gstenginepipeline.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/libclementine-tagreader/tagreader.cpp b/ext/libclementine-tagreader/tagreader.cpp index a5dc8d2c4..467995591 100644 --- a/ext/libclementine-tagreader/tagreader.cpp +++ b/ext/libclementine-tagreader/tagreader.cpp @@ -1299,7 +1299,7 @@ QByteArray TagReader::LoadEmbeddedArt(const QString& filename) const { int pos = data.find('\0') + 1; if ((pos > 0) && (pos < data.size())) { - cover = QByteArray(data.data() + pos, data.size() - pos); + cover = QByteArray(data.data() + pos, data.size() - pos); } } diff --git a/src/engines/gstenginepipeline.cpp b/src/engines/gstenginepipeline.cpp index ba3b5e87e..0edf6df87 100644 --- a/src/engines/gstenginepipeline.cpp +++ b/src/engines/gstenginepipeline.cpp @@ -162,7 +162,7 @@ GstElement* GstEnginePipeline::CreateDecodeBinFromUrl(const QUrl& url) { #ifdef HAVE_SPOTIFY if (url.scheme() == "spotify") { new_bin = gst_bin_new("spotify_bin"); - if (!new_bin) return nullptr; + if (!new_bin) return nullptr; // Create elements GstElement* src = engine_->CreateElement("tcpserversrc", new_bin); @@ -207,7 +207,7 @@ GstElement* GstEnginePipeline::CreateDecodeBinFromUrl(const QUrl& url) { uri = url.toEncoded(); } new_bin = engine_->CreateElement("uridecodebin"); - if (!new_bin) return nullptr; + if (!new_bin) return nullptr; g_object_set(G_OBJECT(new_bin), "uri", uri.constData(), nullptr); CHECKED_GCONNECT(G_OBJECT(new_bin), "drained", &SourceDrainedCallback, this); @@ -468,7 +468,7 @@ bool GstEnginePipeline::Init() { gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, HandoffCallback, this, nullptr); gst_object_unref(pad); - GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline_)); + GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline_)); gst_bus_set_sync_handler(bus, BusCallbackSync, this, nullptr); bus_cb_id_ = gst_bus_add_watch(bus, BusCallback, this); gst_object_unref(bus); @@ -531,7 +531,7 @@ bool GstEnginePipeline::InitFromUrl(const QUrl& url, qint64 end_nanosec) { GstEnginePipeline::~GstEnginePipeline() { if (pipeline_) { - GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline_)); + GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline_)); gst_bus_set_sync_handler(bus, nullptr, nullptr, nullptr); gst_object_unref(bus); From c76697b42c30d50f87efc4b0beeca5a2e89795f3 Mon Sep 17 00:00:00 2001 From: Andrew Reading Date: Thu, 28 Mar 2019 09:37:54 -0700 Subject: [PATCH 092/104] Introduce limit for number of tag client processes. Previously, the number of processes spawned was always QThread::idealThreadCount() (returning the number of logical CPU cores). On new systems with many cores, however, this can result in 12, 16, 24, or ... processes being spawned, which is a bit excessive. This establishes a new config variable, 'max_numprocs_tagclients' within the Settings group, in order to limit the maximum number of tag client processes that get spawned. It also adds a means of setting this via the Behavior page in Settings. It can be set to any integer in the interval [1, QThread::idealThreadCount()]; it defaults to the maximal value so as to emulate the old behavior. --- src/core/tagreaderclient.cpp | 9 ++++++- src/ui/behavioursettingspage.cpp | 20 +++++++++++++++ src/ui/behavioursettingspage.h | 1 + src/ui/behavioursettingspage.ui | 42 ++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/core/tagreaderclient.cpp b/src/core/tagreaderclient.cpp index 96434be52..853c2733e 100644 --- a/src/core/tagreaderclient.cpp +++ b/src/core/tagreaderclient.cpp @@ -18,6 +18,7 @@ along with Clementine. If not, see . */ +#include "player.h" #include "tagreaderclient.h" #include @@ -34,8 +35,14 @@ TagReaderClient::TagReaderClient(QObject* parent) : QObject(parent), worker_pool_(new WorkerPool(this)) { sInstance = this; + QSettings s; + s.beginGroup(Player::kSettingsGroup); + + int max_workers = QThread::idealThreadCount(); + int num_workers = s.value("max_numprocs_tagclients", max_workers).toInt(); + worker_pool_->SetExecutableName(kWorkerExecutableName); - worker_pool_->SetWorkerCount(QThread::idealThreadCount()); + worker_pool_->SetWorkerCount(num_workers); connect(worker_pool_, SIGNAL(WorkerFailedToStart()), SLOT(WorkerFailedToStart())); } diff --git a/src/ui/behavioursettingspage.cpp b/src/ui/behavioursettingspage.cpp index 62287b69d..b32816891 100644 --- a/src/ui/behavioursettingspage.cpp +++ b/src/ui/behavioursettingspage.cpp @@ -40,6 +40,15 @@ BehaviourSettingsPage::BehaviourSettingsPage(SettingsDialog* dialog) connect(ui_->b_show_tray_icon_, SIGNAL(toggled(bool)), SLOT(ShowTrayIconToggled(bool))); + connect(ui_->max_numprocs_tagclients, SIGNAL(valueChanged(int)), + SLOT(MaxNumProcsTagClientsChanged(int))); + ui_->max_numprocs_tagclients_value_label->setMinimumWidth( + QFontMetrics(ui_->max_numprocs_tagclients_value_label->font()) + .width("WWW")); + + // Limit max tag clients to number of CPU cores. + ui_->max_numprocs_tagclients->setMaximum(QThread::idealThreadCount()); + ui_->doubleclick_addmode->setItemData(0, MainWindow::AddBehaviour_Append); ui_->doubleclick_addmode->setItemData(1, MainWindow::AddBehaviour_Load); ui_->doubleclick_addmode->setItemData(2, MainWindow::AddBehaviour_OpenInNew); @@ -171,6 +180,12 @@ void BehaviourSettingsPage::Load() { .toInt())); ui_->seek_step_sec->setValue(s.value("seek_step_sec", 10).toInt()); + int max_numprocs_tagclients = + s.value("max_numprocs_tagclients", QThread::idealThreadCount()).toInt(); + ui_->max_numprocs_tagclients->setValue(max_numprocs_tagclients); + ui_->max_numprocs_tagclients_value_label->setText( + QString::number(max_numprocs_tagclients)); + if (s.value("play_count_short_duration", false).toBool()) { ui_->b_play_count_short_duration->setChecked(true); ui_->b_play_count_normal_duration->setChecked(false); @@ -283,6 +298,7 @@ void BehaviourSettingsPage::Save() { ui_->stop_play_if_fail_->isChecked()); s.setValue("menu_previousmode", menu_previousmode); s.setValue("seek_step_sec", ui_->seek_step_sec->value()); + s.setValue("max_numprocs_tagclients", ui_->max_numprocs_tagclients->value()); if (ui_->b_play_count_short_duration->isChecked()) { s.setValue("play_count_short_duration", true); @@ -321,3 +337,7 @@ void BehaviourSettingsPage::ShowTrayIconToggled(bool on) { ui_->b_keep_running_->setChecked(on); ui_->b_scroll_tray_icon_->setEnabled(on); } + +void BehaviourSettingsPage::MaxNumProcsTagClientsChanged(int value) { + ui_->max_numprocs_tagclients_value_label->setText(QString::number(value)); +} diff --git a/src/ui/behavioursettingspage.h b/src/ui/behavioursettingspage.h index 9f73c0f77..36be11880 100644 --- a/src/ui/behavioursettingspage.h +++ b/src/ui/behavioursettingspage.h @@ -36,6 +36,7 @@ class BehaviourSettingsPage : public SettingsPage { private slots: void ShowTrayIconToggled(bool on); + void MaxNumProcsTagClientsChanged(int value); private: Ui_BehaviourSettingsPage* ui_; diff --git a/src/ui/behavioursettingspage.ui b/src/ui/behavioursettingspage.ui index 2005d707c..88567d8dd 100644 --- a/src/ui/behavioursettingspage.ui +++ b/src/ui/behavioursettingspage.ui @@ -339,6 +339,48 @@ + + + + Maximum number of child processes for tag handling (requires restart) + + + + + + Number of processes: + + + + + + + + + + + + + + 1 + + + 32 + + + 4 + + + Qt::Horizontal + + + 1 + + + + + + From e66fdd86da03f5de5b5ac990ae5f462eb7b992b0 Mon Sep 17 00:00:00 2001 From: Antonio Russo Date: Fri, 6 Sep 2019 22:02:48 -0600 Subject: [PATCH 093/104] Periodically save settings Instead of immediately saving, which leads to poor performance, and possible hardware damage (see #6057), limit saves to once per second (similar to how KDE does it). It also guarantees that only one save is required per second, by sharing a QSettings object, and establishes a signaling framework to put other setting save events into (but only uses this for the two major offenders: playlist tab switching and window resizing). This is in contrast to 6a312e7, which simply deferred the save until program exit, and caused problems for some people (see #6217 and #6209). Signed-off-by: Antonio Russo --- src/core/application.cpp | 17 +++++- src/core/application.h | 8 +++ src/main.cpp | 1 + src/playlist/playlistview.cpp | 63 +++++++++++++++-------- src/playlist/playlistview.h | 9 +++- src/ui/mainwindow.cpp | 94 +++++++++++++++++++--------------- src/ui/mainwindow.h | 9 +++- src/widgets/fancytabwidget.cpp | 15 +++--- src/widgets/fancytabwidget.h | 3 +- 9 files changed, 141 insertions(+), 78 deletions(-) diff --git a/src/core/application.cpp b/src/core/application.cpp index 50092ab95..e3704df6a 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -20,6 +20,9 @@ along with Clementine. If not, see . */ +#include +#include + #include "application.h" #include "config.h" @@ -67,7 +70,8 @@ bool Application::kIsPortable = false; class ApplicationImpl { public: ApplicationImpl(Application* app) - : tag_reader_client_([=]() { + : settings_timer_(app), + tag_reader_client_([=]() { TagReaderClient* client = new TagReaderClient(app); app->MoveToNewThread(client); client->Start(); @@ -150,6 +154,9 @@ class ApplicationImpl { }) { } + QTimer settings_timer_; + QSettings settings_; + Lazy tag_reader_client_; Lazy database_; Lazy album_cover_loader_; @@ -188,6 +195,10 @@ Application::Application(QObject* parent) // TODO(John Maguire): Make this not a weird singleton. tag_reader_client(); + + p_->settings_timer_.setInterval(1000); + p_->settings_timer_.setSingleShot(true); + connect(&(p_->settings_timer_), SIGNAL(timeout()), SLOT(SaveSettings_())); } Application::~Application() { @@ -229,6 +240,8 @@ QString Application::language_without_region() const { return language_name_; } +void Application::SaveSettings_() { emit SaveSettings(&(p_->settings_)); } + void Application::ReloadSettings() { emit SettingsChanged(); } void Application::OpenSettingsDialogAtPage(SettingsDialog::Page page) { @@ -326,3 +339,5 @@ TagReaderClient* Application::tag_reader_client() const { TaskManager* Application::task_manager() const { return p_->task_manager_.get(); } + +void Application::DirtySettings() { p_->settings_timer_.start(); } diff --git a/src/core/application.h b/src/core/application.h index 679c45335..1c1a1cb07 100644 --- a/src/core/application.h +++ b/src/core/application.h @@ -28,6 +28,8 @@ #include "ui/settingsdialog.h" +class QSettings; + class AlbumCoverLoader; class Appearance; class ApplicationImpl; @@ -98,6 +100,8 @@ class Application : public QObject { TagReaderClient* tag_reader_client() const; TaskManager* task_manager() const; + void DirtySettings(); + void MoveToNewThread(QObject* object); void MoveToThread(QObject* object, QThread* thread); @@ -109,8 +113,12 @@ class Application : public QObject { signals: void ErrorAdded(const QString& message); void SettingsChanged(); + void SaveSettings(QSettings* settings); void SettingsDialogRequested(SettingsDialog::Page page); + private slots: + void SaveSettings_(); + private: QString language_name_; std::unique_ptr p_; diff --git a/src/main.cpp b/src/main.cpp index ecf47b9d4..edb883a12 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -430,6 +430,7 @@ int main(int argc, char* argv[]) { QtConcurrent::run(&ParseAProto); Application app; + QObject::connect(&a, SIGNAL(aboutToQuit()), &app, SLOT(SaveSettings_())); app.set_language_name(language); // Network proxy diff --git a/src/playlist/playlistview.cpp b/src/playlist/playlistview.cpp index 28137b110..963715c3f 100644 --- a/src/playlist/playlistview.cpp +++ b/src/playlist/playlistview.cpp @@ -135,6 +135,8 @@ PlaylistView::PlaylistView(QWidget* parent) cached_current_row_row_(-1), drop_indicator_row_(-1), drag_over_(false), + dirty_geometry_(false), + dirty_settings_(false), dynamic_controls_(new DynamicPlaylistControls(this)) { setHeader(header_); header_->setSectionsMovable(true); @@ -153,12 +155,13 @@ PlaylistView::PlaylistView(QWidget* parent) currenttrack_pause_ = currenttrack_pause.pixmap(currenttrack_pause.actualSize(QSize(32, 32))); - connect(header_, SIGNAL(sectionResized(int, int, int)), SLOT(SaveGeometry())); - connect(header_, SIGNAL(sectionMoved(int, int, int)), SLOT(SaveGeometry())); + connect(header_, SIGNAL(sectionResized(int, int, int)), + SLOT(DirtyGeometry())); + connect(header_, SIGNAL(sectionMoved(int, int, int)), SLOT(DirtyGeometry())); connect(header_, SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), - SLOT(SaveGeometry())); + SLOT(DirtyGeometry())); connect(header_, SIGNAL(SectionVisibilityChanged(int, bool)), - SLOT(SaveGeometry())); + SLOT(DirtyGeometry())); connect(header_, SIGNAL(SectionRatingLockStatusChanged(bool)), SLOT(SetRatingLockStatus(bool))); connect(header_, SIGNAL(sectionResized(int, int, int)), @@ -167,7 +170,7 @@ PlaylistView::PlaylistView(QWidget* parent) SLOT(InvalidateCachedCurrentPixmap())); connect(header_, SIGNAL(SectionVisibilityChanged(int, bool)), SLOT(InvalidateCachedCurrentPixmap())); - connect(header_, SIGNAL(StretchEnabledChanged(bool)), SLOT(SaveSettings())); + connect(header_, SIGNAL(StretchEnabledChanged(bool)), SLOT(DirtySettings())); connect(header_, SIGNAL(StretchEnabledChanged(bool)), SLOT(StretchChanged(bool))); connect(header_, SIGNAL(MouseEntered()), SLOT(RatingHoverOut())); @@ -196,7 +199,6 @@ PlaylistView::PlaylistView(QWidget* parent) } PlaylistView::~PlaylistView() { - SaveGeometry(); delete style_; } @@ -210,6 +212,10 @@ void PlaylistView::SetApplication(Application* app) { connect(app_->player(), SIGNAL(Playing()), SLOT(StartGlowing())); connect(app_->player(), SIGNAL(Stopped()), SLOT(StopGlowing())); connect(app_->player(), SIGNAL(Stopped()), SLOT(PlayerStopped())); + connect(app_, SIGNAL(SaveSettings(QSettings*)), + SLOT(SaveGeometry(QSettings*))); + connect(app_, SIGNAL(SaveSettings(QSettings*)), + SLOT(SaveSettings(QSettings*))); } void PlaylistView::SetItemDelegates(LibraryBackend* backend) { @@ -416,13 +422,19 @@ void PlaylistView::LoadRatingLockStatus() { ratings_locked_ = s.value("RatingLocked", false).toBool(); } -void PlaylistView::SaveGeometry() { - if (read_only_settings_ || !header_loaded_) return; +void PlaylistView::DirtyGeometry() { + dirty_geometry_ = true; + app_->DirtySettings(); +} - QSettings settings; - settings.beginGroup(Playlist::kSettingsGroup); - settings.setValue("state", header_->SaveState()); - settings.setValue("state_version", kStateVersion); +void PlaylistView::SaveGeometry(QSettings* settings) { + if (!dirty_geometry_ || read_only_settings_ || !header_loaded_) return; + dirty_geometry_ = false; + + settings->beginGroup(Playlist::kSettingsGroup); + settings->setValue("state", header_->SaveState()); + settings->setValue("state_version", kStateVersion); + settings->endGroup(); } void PlaylistView::SetRatingLockStatus(bool state) { @@ -1179,20 +1191,28 @@ void PlaylistView::ReloadSettings() { setEditTriggers(editTriggers() | QAbstractItemView::SelectedClicked); } -void PlaylistView::SaveSettings() { - if (read_only_settings_) return; +void PlaylistView::DirtySettings() { + dirty_settings_ = true; + app_->DirtySettings(); +} - QSettings s; - s.beginGroup(Playlist::kSettingsGroup); - s.setValue("glow_effect", glow_enabled_); - s.setValue("column_alignments", QVariant::fromValue(column_alignment_)); - s.setValue(kSettingBackgroundImageType, background_image_type_); +void PlaylistView::SaveSettings(QSettings* settings) { + if (!dirty_settings_ || read_only_settings_) return; + dirty_settings_ = false; + + settings->beginGroup(Playlist::kSettingsGroup); + settings->setValue("glow_effect", glow_enabled_); + settings->setValue("column_alignments", + QVariant::fromValue(column_alignment_)); + settings->setValue(kSettingBackgroundImageType, background_image_type_); + settings->endGroup(); } void PlaylistView::StretchChanged(bool stretch) { setHorizontalScrollBarPolicy(stretch ? Qt::ScrollBarAlwaysOff : Qt::ScrollBarAsNeeded); - SaveGeometry(); + dirty_geometry_ = true; + app_->DirtySettings(); } void PlaylistView::DynamicModeChanged(bool dynamic) { @@ -1261,7 +1281,8 @@ void PlaylistView::SetColumnAlignment(int section, Qt::Alignment alignment) { column_alignment_[section] = alignment; emit ColumnAlignmentChanged(column_alignment_); - SaveSettings(); + dirty_settings_ = true; + app_->DirtySettings(); } Qt::Alignment PlaylistView::column_alignment(int section) const { diff --git a/src/playlist/playlistview.h b/src/playlist/playlistview.h index aa4b144a1..8e24e6b46 100644 --- a/src/playlist/playlistview.h +++ b/src/playlist/playlistview.h @@ -145,7 +145,9 @@ signals: private slots: void LoadGeometry(); void LoadRatingLockStatus(); - void SaveGeometry(); + void DirtyGeometry(); + void DirtySettings(); + void SaveGeometry(QSettings* settings); void SetRatingLockStatus(bool state); void GlowIntensityChanged(); void InhibitAutoscrollTimeout(); @@ -153,7 +155,7 @@ signals: void InvalidateCachedCurrentPixmap(); void PlaylistDestroyed(); - void SaveSettings(); + void SaveSettings(QSettings* s); void StretchChanged(bool stretch); void RatingHoverIn(const QModelIndex& index, const QPoint& pos); @@ -251,6 +253,9 @@ signals: int drop_indicator_row_; bool drag_over_; + bool dirty_geometry_; + bool dirty_settings_; + bool ratings_locked_; // To store Ratings section lock status DynamicPlaylistControls* dynamic_controls_; diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 58419de01..2922b6508 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -223,6 +223,8 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd, track_position_timer_(new QTimer(this)), track_slider_timer_(new QTimer(this)), initialized_(false), + dirty_geometry_(false), + dirty_playback_(false), saved_playback_position_(0), saved_playback_state_(Engine::Empty), doubleclick_addmode_(AddBehaviour_Append), @@ -258,6 +260,9 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd, connect(global_search_view_, SIGNAL(AddToPlaylist(QMimeData*)), SLOT(AddToPlaylist(QMimeData*))); + // Set up the settings group early + settings_.beginGroup(kSettingsGroup); + // Add tabs to the fancy tab widget ui_->tabs->addTab(global_search_view_, IconLoader::Load("search", IconLoader::Base), @@ -301,6 +306,9 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd, connect(track_slider_timer_, SIGNAL(timeout()), SLOT(UpdateTrackSliderPosition())); + connect(app_, SIGNAL(SaveSettings(QSettings*)), + SLOT(SaveSettings(QSettings*))); + // Start initialising the player qLog(Debug) << "Initialising player"; app_->player()->Init(); @@ -977,7 +985,6 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd, // Load settings qLog(Debug) << "Loading settings"; - settings_.beginGroup(kSettingsGroup); // Set last used geometry to position window on the correct monitor // Set window state only if the window was last maximized @@ -1064,13 +1071,11 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd, if (!options.contains_play_options()) LoadPlaybackStatus(); initialized_ = true; - SaveGeometry(); qLog(Debug) << "Started"; } MainWindow::~MainWindow() { - SaveGeometry(); delete ui_; } @@ -1085,18 +1090,15 @@ void MainWindow::ReloadSettings() { show(); #endif - QSettings s; - s.beginGroup(kSettingsGroup); - - doubleclick_addmode_ = - AddBehaviour(s.value("doubleclick_addmode", AddBehaviour_Append).toInt()); + doubleclick_addmode_ = AddBehaviour( + settings_.value("doubleclick_addmode", AddBehaviour_Append).toInt()); doubleclick_playmode_ = PlayBehaviour( - s.value("doubleclick_playmode", PlayBehaviour_IfStopped).toInt()); - doubleclick_playlist_addmode_ = - PlaylistAddBehaviour(s.value("doubleclick_playlist_addmode", - PlaylistAddBehaviour_Play).toInt()); - menu_playmode_ = - PlayBehaviour(s.value("menu_playmode", PlayBehaviour_IfStopped).toInt()); + settings_.value("doubleclick_playmode", PlayBehaviour_IfStopped).toInt()); + doubleclick_playlist_addmode_ = PlaylistAddBehaviour( + settings_.value("doubleclick_playlist_addmode", PlaylistAddBehaviour_Play) + .toInt()); + menu_playmode_ = PlayBehaviour( + settings_.value("menu_playmode", PlayBehaviour_IfStopped).toInt()); bool show_sidebar = settings_.value("show_sidebar", true).toBool(); ui_->sidebar_layout->setVisible(show_sidebar); @@ -1278,54 +1280,61 @@ void MainWindow::ScrobbleButtonVisibilityChanged(bool value) { } } -void MainWindow::changeEvent(QEvent*) { +void MainWindow::SaveSettings(QSettings* settings) { if (!initialized_) return; - SaveGeometry(); + settings->beginGroup(kSettingsGroup); + if (dirty_geometry_) SaveGeometry(settings); + if (dirty_playback_) SavePlaybackStatus(settings); + settings->endGroup(); +} + +void MainWindow::changeEvent(QEvent*) { + dirty_geometry_ = true; + app_->DirtySettings(); } void MainWindow::resizeEvent(QResizeEvent*) { - if (!initialized_) return; - SaveGeometry(); + dirty_geometry_ = true; + app_->DirtySettings(); } -void MainWindow::SaveGeometry() { +void MainWindow::SaveGeometry(QSettings* settings) { if (!initialized_) return; + dirty_geometry_ = false; was_maximized_ = isMaximized(); - settings_.setValue("maximized", was_maximized_); + settings->setValue("maximized", was_maximized_); // Save the geometry only when mainwindow is not in maximized state if (!was_maximized_) { - settings_.setValue("geometry", saveGeometry()); + settings->setValue("geometry", saveGeometry()); } - settings_.setValue("splitter_state", ui_->splitter->saveState()); - settings_.setValue("current_tab", ui_->tabs->currentIndex()); - settings_.setValue("tab_mode", ui_->tabs->mode()); + settings->setValue("splitter_state", ui_->splitter->saveState()); + settings->setValue("current_tab", ui_->tabs->currentIndex()); + settings->setValue("tab_mode", ui_->tabs->mode()); - ui_->tabs->saveSettings(kSettingsGroup); + // Leaving this here for now + ui_->tabs->saveSettings(settings); } -void MainWindow::SavePlaybackStatus() { - QSettings settings; - settings.beginGroup(MainWindow::kSettingsGroup); - settings.setValue("playback_state", app_->player()->GetState()); +void MainWindow::SavePlaybackStatus(QSettings* settings) { + dirty_playback_ = false; + settings->setValue("playback_state", app_->player()->GetState()); if (app_->player()->GetState() == Engine::Playing || app_->player()->GetState() == Engine::Paused) { - settings.setValue( + settings->setValue( "playback_position", app_->player()->engine()->position_nanosec() / kNsecPerSec); } else { - settings.setValue("playback_position", 0); + settings->setValue("playback_position", 0); } } void MainWindow::LoadPlaybackStatus() { - QSettings settings; - settings.beginGroup(MainWindow::kSettingsGroup); bool resume_playback = - settings.value("resume_playback_after_start", false).toBool(); + settings_.value("resume_playback_after_start", false).toBool(); saved_playback_state_ = static_cast( - settings.value("playback_state", Engine::Empty).toInt()); - saved_playback_position_ = settings.value("playback_position", 0).toDouble(); + settings_.value("playback_state", Engine::Empty).toInt()); + saved_playback_position_ = settings_.value("playback_position", 0).toDouble(); if (!resume_playback || saved_playback_state_ == Engine::Empty || saved_playback_state_ == Engine::Idle) { return; @@ -1433,12 +1442,10 @@ void MainWindow::StopAfterCurrent() { } void MainWindow::closeEvent(QCloseEvent* event) { - QSettings s; - s.beginGroup(kSettingsGroup); - bool keep_running(false); if (tray_icon_) - keep_running = s.value("keeprunning", tray_icon_->IsVisible()).toBool(); + keep_running = + settings_.value("keeprunning", tray_icon_->IsVisible()).toBool(); if (keep_running && event->spontaneous()) { event->ignore(); @@ -2794,10 +2801,13 @@ bool MainWindow::winEvent(MSG* msg, long*) { #endif // Q_OS_WIN32 void MainWindow::Exit() { - SaveGeometry(); - SavePlaybackStatus(); + // FIXME: This may add an extra write. + dirty_playback_ = true; settings_.setValue("show_sidebar", ui_->action_toggle_show_sidebar->isChecked()); + settings_.endGroup(); + SaveSettings(&settings_); + settings_.sync(); if (app_->player()->engine()->is_fadeout_enabled()) { // To shut down the application when fadeout will be finished diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h index 2f62f8375..74a6ff8cb 100644 --- a/src/ui/mainwindow.h +++ b/src/ui/mainwindow.h @@ -151,6 +151,7 @@ signals: private slots: void FilePathChanged(const QString& path); + void SaveSettings(QSettings* settings); void MediaStopped(); void MediaPaused(); void MediaPlaying(); @@ -266,8 +267,8 @@ signals: void OpenSettingsDialogAtPage(SettingsDialog::Page page); void ShowSongInfoConfig(); - void SaveGeometry(); - void SavePlaybackStatus(); + void SaveGeometry(QSettings* settings); + void SavePlaybackStatus(QSettings* settings); void LoadPlaybackStatus(); void ResumePlayback(); @@ -380,6 +381,10 @@ signals: QSettings settings_; bool initialized_; + + bool dirty_geometry_; + bool dirty_playback_; + bool was_maximized_; int saved_playback_position_; Engine::State saved_playback_state_; diff --git a/src/widgets/fancytabwidget.cpp b/src/widgets/fancytabwidget.cpp index 78f1e6e69..ec14a5d34 100644 --- a/src/widgets/fancytabwidget.cpp +++ b/src/widgets/fancytabwidget.cpp @@ -307,16 +307,13 @@ void FancyTabWidget::loadSettings(const char *kSettingsGroup) { } } -void FancyTabWidget::saveSettings(const char *kSettingsGroup) { - QSettings settings; - settings.beginGroup(kSettingsGroup); +void FancyTabWidget::saveSettings(QSettings* settings) { + for (int i = 0; i < count(); i++) { + int originalIndex = tabBar()->tabData(i).toInt(); + std::string k = "tab_index_" + std::to_string(originalIndex); - for(int i =0;itabData(i).toInt(); - std::string k = "tab_index_" + std::to_string(originalIndex); - - settings.setValue(QString::fromStdString(k), i); - } + settings->setValue(QString::fromStdString(k), i); + } } diff --git a/src/widgets/fancytabwidget.h b/src/widgets/fancytabwidget.h index e426ef46f..5a4acc2d6 100644 --- a/src/widgets/fancytabwidget.h +++ b/src/widgets/fancytabwidget.h @@ -25,6 +25,7 @@ class QActionGroup; class QMenu; +class QSettings; class QSignalMapper; namespace Core { @@ -44,7 +45,7 @@ class FancyTabWidget : public QTabWidget { void addSpacer(); void loadSettings(const char *); - void saveSettings(const char *); + void saveSettings(QSettings*); // Values are persisted - only add to the end enum Mode { Mode_None = 0, From ccaa59cc667592208df71a05f0a71bb3a68eaafa Mon Sep 17 00:00:00 2001 From: Antonio Russo Date: Fri, 6 Sep 2019 20:29:19 -0600 Subject: [PATCH 094/104] Periodically save current playlist tab Building on the previous commit, we save the current playlist (tab) periodically as well. Signed-off-by: Antonio Russo --- src/playlist/playlistcontainer.cpp | 29 ++++++++++++++++++++++++----- src/playlist/playlistcontainer.h | 8 +++++++- src/ui/mainwindow.cpp | 3 +-- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/playlist/playlistcontainer.cpp b/src/playlist/playlistcontainer.cpp index 0907f69f6..ad92e3edc 100644 --- a/src/playlist/playlistcontainer.cpp +++ b/src/playlist/playlistcontainer.cpp @@ -16,6 +16,7 @@ */ #include "core/appearance.h" +#include "core/application.h" #include "core/logging.h" #include "core/player.h" #include "core/timeconstants.h" @@ -43,6 +44,7 @@ const int PlaylistContainer::kFilterDelayPlaylistSizeThreshold = 5000; PlaylistContainer::PlaylistContainer(QWidget* parent) : QWidget(parent), + app_(nullptr), ui_(new Ui_PlaylistContainer), manager_(nullptr), undo_(nullptr), @@ -52,7 +54,8 @@ PlaylistContainer::PlaylistContainer(QWidget* parent) tab_bar_visible_(false), tab_bar_animation_(new QTimeLine(500, this)), no_matches_label_(nullptr), - filter_timer_(new QTimer(this)) { + filter_timer_(new QTimer(this)), + dirty_(false) { ui_->setupUi(this); no_matches_label_ = new QLabel(ui_->playlist); @@ -96,6 +99,7 @@ PlaylistContainer::PlaylistContainer(QWidget* parent) ui_->tab_bar->setMaximumHeight(0); // Connections + connect(ui_->tab_bar, SIGNAL(currentChanged(int)), SLOT(DirtyTabBar())); connect(ui_->tab_bar, SIGNAL(Save(int)), SLOT(SavePlaylist(int))); // set up timer for delayed filter updates @@ -111,10 +115,17 @@ PlaylistContainer::PlaylistContainer(QWidget* parent) } PlaylistContainer::~PlaylistContainer() { - Save(); delete ui_; } +void PlaylistContainer::SetApplication(Application* app) { + Q_ASSERT(app); + app_ = app; + SetManager(app_->playlist_manager()); + ui_->playlist->SetApplication(app_); + connect(app_, SIGNAL(SaveSettings(QSettings*)), SLOT(Save(QSettings*))); +} + PlaylistView* PlaylistContainer::view() const { return ui_->playlist; } void PlaylistContainer::SetActions(QAction* new_playlist, @@ -334,10 +345,18 @@ void PlaylistContainer::GoToPreviousPlaylistTab() { manager_->SetCurrentPlaylist(id_previous); } -void PlaylistContainer::Save() { - if (starting_up_) return; +void PlaylistContainer::DirtyTabBar() { + dirty_ = true; + app_->DirtySettings(); +} - settings_.setValue("current_playlist", ui_->tab_bar->current_id()); +void PlaylistContainer::Save(QSettings* settings_) { + if (starting_up_ || !dirty_) return; + dirty_ = false; + + settings_->beginGroup(kSettingsGroup); + settings_->setValue("current_playlist", ui_->tab_bar->current_id()); + settings_->endGroup(); } void PlaylistContainer::SetTabBarVisible(bool visible) { diff --git a/src/playlist/playlistcontainer.h b/src/playlist/playlistcontainer.h index 804c10445..76a6cded7 100644 --- a/src/playlist/playlistcontainer.h +++ b/src/playlist/playlistcontainer.h @@ -23,6 +23,7 @@ class Ui_PlaylistContainer; +class Application; class LineEditInterface; class Playlist; class PlaylistManager; @@ -41,6 +42,7 @@ class PlaylistContainer : public QWidget { static const char* kSettingsGroup; + void SetApplication(Application* app); void SetActions(QAction* new_playlist, QAction* load_playlist, QAction* save_playlist, QAction* next_playlist, QAction* previous_playlist); @@ -83,7 +85,8 @@ signals: void ActivePaused(); void ActiveStopped(); - void Save(); + void DirtyTabBar(); + void Save(QSettings* settings_); void SetTabBarVisible(bool visible); void SetTabBarHeight(int height); @@ -103,6 +106,7 @@ signals: static const int kFilterDelayMs; static const int kFilterDelayPlaylistSizeThreshold; + Application* app_; Ui_PlaylistContainer* ui_; PlaylistManager* manager_; @@ -119,6 +123,8 @@ signals: QLabel* no_matches_label_; QTimer* filter_timer_; + + bool dirty_; }; #endif // PLAYLISTCONTAINER_H diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 2922b6508..b5423af3f 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -325,8 +325,7 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd, connect(ui_->playlist, SIGNAL(ViewSelectionModelChanged()), SLOT(PlaylistViewSelectionModelChanged())); - ui_->playlist->SetManager(app_->playlist_manager()); - ui_->playlist->view()->SetApplication(app_); + ui_->playlist->SetApplication(app_); library_view_->view()->setModel(library_sort_model_); library_view_->view()->SetApplication(app_); From e2de5cd62ea9f12527bdb6abe70d088ffbf84b0d Mon Sep 17 00:00:00 2001 From: Antonio Russo Date: Tue, 10 Sep 2019 17:27:08 -0600 Subject: [PATCH 095/104] fancytabwidget.cpp: prefer QString to std::string Consistently use QString, rather than creating a std::string and immediately casting to std::string --- src/widgets/fancytabwidget.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/widgets/fancytabwidget.cpp b/src/widgets/fancytabwidget.cpp index ec14a5d34..37030feb5 100644 --- a/src/widgets/fancytabwidget.cpp +++ b/src/widgets/fancytabwidget.cpp @@ -294,25 +294,25 @@ void FancyTabWidget::loadSettings(const char *kSettingsGroup) { QSettings settings; settings.beginGroup(kSettingsGroup); - for(int i =0;itabData(i).toInt(); - std::string k = "tab_index_" + std::to_string(originalIndex); + for (int i = 0; i < count(); i++) { + int originalIndex = tabBar()->tabData(i).toInt(); + QString k = "tab_index_" + QString::number(originalIndex); - int newIndex = settings.value(QString::fromStdString(k), i).toInt(); + int newIndex = settings.value(k, i).toInt(); - if(newIndex >= 0) - tabBar()->moveTab(i,newIndex); - else - removeTab(i); // Does not delete page - } + if (newIndex >= 0) + tabBar()->moveTab(i, newIndex); + else + removeTab(i); // Does not delete page + } } void FancyTabWidget::saveSettings(QSettings* settings) { for (int i = 0; i < count(); i++) { int originalIndex = tabBar()->tabData(i).toInt(); - std::string k = "tab_index_" + std::to_string(originalIndex); + QString k = "tab_index_" + QString::number(originalIndex); - settings->setValue(QString::fromStdString(k), i); + settings->setValue(k, i); } } From c5c294ba14c2366a6d1a54e2013e73836937bb74 Mon Sep 17 00:00:00 2001 From: Antonio Russo Date: Tue, 10 Sep 2019 17:29:48 -0600 Subject: [PATCH 096/104] fancytabwidget.cpp: reuse QSettings object avoid excessive locking by reusing a common QSettings object in loadSettings. --- src/ui/mainwindow.cpp | 2 +- src/widgets/fancytabwidget.cpp | 5 +---- src/widgets/fancytabwidget.h | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index b5423af3f..28cac46a9 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -297,7 +297,7 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd, ui_->tabs->setBackgroundPixmap(QPixmap(":/sidebar_background.png")); // Do this only after all default tabs have been added - ui_->tabs->loadSettings(kSettingsGroup); + ui_->tabs->loadSettings(settings_); track_position_timer_->setInterval(kTrackPositionUpdateTimeMs); connect(track_position_timer_, SIGNAL(timeout()), diff --git a/src/widgets/fancytabwidget.cpp b/src/widgets/fancytabwidget.cpp index 37030feb5..98f4b2daf 100644 --- a/src/widgets/fancytabwidget.cpp +++ b/src/widgets/fancytabwidget.cpp @@ -290,10 +290,7 @@ FancyTabWidget::FancyTabWidget(QWidget* parent) : QTabWidget(parent), connect(tabBar, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int))); } -void FancyTabWidget::loadSettings(const char *kSettingsGroup) { - QSettings settings; - settings.beginGroup(kSettingsGroup); - +void FancyTabWidget::loadSettings(const QSettings& settings) { for (int i = 0; i < count(); i++) { int originalIndex = tabBar()->tabData(i).toInt(); QString k = "tab_index_" + QString::number(originalIndex); diff --git a/src/widgets/fancytabwidget.h b/src/widgets/fancytabwidget.h index 5a4acc2d6..c18de5221 100644 --- a/src/widgets/fancytabwidget.h +++ b/src/widgets/fancytabwidget.h @@ -44,7 +44,7 @@ class FancyTabWidget : public QTabWidget { void setBackgroundPixmap(const QPixmap& pixmap); void addSpacer(); - void loadSettings(const char *); + void loadSettings(const QSettings&); void saveSettings(QSettings*); // Values are persisted - only add to the end enum Mode { From 664c5a31f9cf519af5a4c3adcb30dbbc73d037d6 Mon Sep 17 00:00:00 2001 From: John Maguire Date: Fri, 4 Oct 2019 17:23:59 +0100 Subject: [PATCH 097/104] Setup qt5 build with Bionic --- .circleci/config.yml | 67 +++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 38 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1bb13ed53..258d2167d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -144,41 +144,33 @@ commands: name: Install Dependencies command: > apt-get update && apt-get install -y + build-essential cmake - fakeroot gettext git libasound2-dev libboost-dev - libboost-serialization-dev - libcdio-cdda2 libcdio-dev libchromaprint-dev - libcrypto++-dev libdbus-1-dev libfftw3-dev libglew1.5-dev + libglib2.0-dev libgpod-dev libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev - liblastfm-dev libmtp-dev - libmygpo-qt-dev - libplist-dev libprotobuf-dev libpulse-dev - libqca2-dev - libqca2-plugins - libqjson-dev - libqt4-dev - libqt4-opengl-dev - libqtwebkit-dev - libsparsehash-dev + libqt5x11extras5-dev libsqlite3-dev libtag1-dev - libusbmuxd-dev + pkg-config protobuf-compiler - qt4-dev-tools + qtbase5-dev + qttools5-dev-tools + qttools5-dev + libsparsehash-dev ssh install_disco_dependencies: description: Install Disco dependencies @@ -474,26 +466,25 @@ workflows: version: 2 build_all: jobs: - - build_xenial_32 - - build_xenial_64 - - build_bionic_32 + # - build_xenial_32 + # - build_xenial_64 + # - build_bionic_32 - build_bionic_64 - - build_disco_32 - - build_disco_64 - - build_fedora_29_64 - - build_fedora_30_64 - - - upload_artifacts: - context: gcp - requires: - - build_xenial_32 - - build_xenial_64 - - build_bionic_32 - - build_bionic_64 - - build_disco_32 - - build_disco_64 - - build_fedora_29_64 - - build_fedora_30_64 - filters: - branches: - only: master + # - build_disco_32 + # - build_disco_64 + # - build_fedora_29_64 + # - build_fedora_30_64 + # - upload_artifacts: + # context: gcp + # requires: + # - build_xenial_32 + # - build_xenial_64 + # - build_bionic_32 + # - build_bionic_64 + # - build_disco_32 + # - build_disco_64 + # - build_fedora_29_64 + # - build_fedora_30_64 + # filters: + # branches: + # only: master From 992311c185b10776556c9b248766a4da13a6ae92 Mon Sep 17 00:00:00 2001 From: John Maguire Date: Wed, 16 Oct 2019 19:42:21 +0100 Subject: [PATCH 098/104] Bunch of mac build fixes --- .circleci/config.yml | 43 +++++++++++++++++++++++-------------------- CMakeLists.txt | 1 + dist/macdeploy.py | 22 +++++++++++++--------- src/CMakeLists.txt | 9 ++++++--- 4 files changed, 43 insertions(+), 32 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f81660d45..973deb526 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -442,9 +442,10 @@ jobs: - run: name: Setup PATH command: | - echo 'export Qt5_DIR=/usr/local/opt/qt5/lib/cmake' >> $BASH_ENV - echo 'export Qt5LinguistTools_DIR=/usr/local/Cellar/qt/5.11.2/lib/cmake/Qt5LinguistTools' >> $BASH_ENV - echo 'export GST_SCANNER_PATH=/usr/local/Cellar/gstreamer/1.14.4/libexec/gstreamer-1.0/gst-plugin-scanner' >> $BASH_ENV + echo 'export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig' >> $BASH_ENV + echo 'export Qt5_DIR=/usr/local/Cellar/qt/5.13.1/lib/cmake/Qt5' >> $BASH_ENV + echo 'export Qt5LinguistTools_DIR=/usr/local/Cellar/qt/5.13.1/lib/cmake/Qt5LinguistTools' >> $BASH_ENV + echo 'export GST_SCANNER_PATH=/usr/local/Cellar/gstreamer/1.16.1/libexec/gstreamer-1.0/gst-plugin-scanner' >> $BASH_ENV echo 'export GST_PLUGIN_PATH=/usr/local/lib/gstreamer-1.0' >> $BASH_ENV echo 'export PATH=/usr/local/opt/gettext/bin:$PATH' >> $BASH_ENV source $BASH_ENV @@ -456,35 +457,37 @@ jobs: chromaprint cmake cryptopp + fftw gettext + glew glib - liblastfm + google-sparsehash + gst-libav + gst-plugins-bad + gst-plugins-base + gst-plugins-good + gst-plugins-ugly + gstreamer pkgconfig protobuf protobuf-c qt - - run: - name: Install sqlite - command: brew install sqlite --with-fts - - run: - name: Install gstreamer - command: brew install gstreamer gst-plugins-base - - run: - name: Install gst-plugins-good - command: brew install gst-plugins-good --with-flac - - run: - name: Install gst-plugins - command: brew install gst-plugins-bad gst-plugins-ugly - - run: - name: Install other dependencies - command: brew install chromaprint liblastfm + sqlite - checkout - run: name: Checkout qt5 branch command: git checkout qt5 - run: name: cmake - command: cmake .. -DUSE_VISUALISATIONS=OFF + command: > + cmake + .. + -Wno-dev + -DCMAKE_BUILD_TYPE=Release + -DCMAKE_OSX_ARCHITECTURES=x86_64 + -DGETTEXT_MSGMERGE_EXECUTABLE=/usr/local/Cellar/gettext/0.20.1/bin/msgmerge + -DGETTEXT_MSGFMT_EXECUTABLE=/usr/local/Cellar/gettext/0.20.1/bin/msgfmt + -DGETTEXT_XGETTEXT_EXECUTABLE=/usr/local/Cellar/gettext/0.20.1/bin/xgettext working_directory: bin - run: name: make diff --git a/CMakeLists.txt b/CMakeLists.txt index e4fc73466..cd772ac6b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required(VERSION 2.8.11) cmake_policy(SET CMP0011 OLD) +cmake_policy(SET CMP0053 OLD) include(CheckCXXCompilerFlag) include(FindPkgConfig) diff --git a/dist/macdeploy.py b/dist/macdeploy.py index 08fa5ca7e..5f89a855e 100755 --- a/dist/macdeploy.py +++ b/dist/macdeploy.py @@ -1,4 +1,4 @@ -#!/usr/bin/python2 +#!/usr/bin/python # This file is part of Clementine. # @@ -66,7 +66,6 @@ GSTREAMER_PLUGINS = [ 'libgstisomp4.so', 'libgstlame.so', 'libgstlibav.so', - 'libgstmad.so', 'libgstmms.so', # TODO: Bring back Musepack support. 'libgstogg.so', @@ -75,27 +74,25 @@ GSTREAMER_PLUGINS = [ 'libgstspeex.so', 'libgsttaglib.so', 'libgstvorbis.so', - 'libgstwavpack.so', 'libgstwavparse.so', 'libgstxingmux.so', # HTTP src support - 'libgstsouphttpsrc.so', + 'libgstsoup.so', # Icecast support 'libgsticydemux.so', - # CD support - 'libgstcdio.so', - # RTSP streaming 'libgstrtp.so', 'libgstrtsp.so', ] GSTREAMER_SEARCH_PATH = [ + '/usr/local/lib/gstreamer-1.0', '/target/lib/gstreamer-1.0', '/target/libexec/gstreamer-1.0', + '/usr/local/Cellar/gstreamer/1.16.1/libexec/gstreamer-1.0', ] QT_PLUGINS = [ @@ -110,14 +107,19 @@ QT_PLUGINS = [ 'imageformats/libqjpeg.dylib', #'imageformats/libqmng.dylib', 'imageformats/libqsvg.dylib', + 'platforms/libqcocoa.dylib', ] QT_PLUGINS_SEARCH_PATH = [ + '/usr/local/Cellar/qt/5.13.1/plugins', '/target/plugins', '/usr/local/Trolltech/Qt-4.7.0/plugins', '/Developer/Applications/Qt/plugins', ] -GIO_MODULES_SEARCH_PATH = ['/target/lib/gio/modules',] +GIO_MODULES_SEARCH_PATH = [ + '/usr/local/lib/gio/modules', + '/target/lib/gio/modules', +] INSTALL_NAME_TOOL_APPLE = 'install_name_tool' INSTALL_NAME_TOOL_CROSS = 'x86_64-apple-darwin-%s' % INSTALL_NAME_TOOL_APPLE @@ -303,6 +305,7 @@ def CopyLibrary(path): new_path = os.path.join(frameworks_dir, os.path.basename(path)) args = ['cp', path, new_path] commands.append(args) + commands.append(['chmod', '+w', new_path]) LOGGER.info("Copying library '%s'", path) return new_path @@ -313,6 +316,7 @@ def CopyPlugin(path, subdir): commands.append(args) args = ['cp', path, new_path] commands.append(args) + commands.append(['chmod', '+w', new_path]) LOGGER.info("Copying plugin '%s'", path) return new_path @@ -337,6 +341,7 @@ def CopyFramework(src_binary): commands.append(['mkdir', '-p', dest_dir]) commands.append(['cp', src_binary, dest_binary]) + commands.append(['chmod', '+w', dest_binary]) # Copy special files from various places: # QtCore has Resources/qt_menu.nib (copy to app's Resources) @@ -469,7 +474,6 @@ def main(): FixPlugin(FindGstreamerPlugin('gst-plugin-scanner'), '.') FixPlugin(FindGioModule('libgiognutls.so'), 'gio-modules') - FixPlugin(FindGioModule('libgiolibproxy.so'), 'gio-modules') try: FixPlugin('clementine-spotifyblob', '.') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d635aee7c..e19419559 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1267,6 +1267,12 @@ target_link_libraries(clementine_lib z ) +link_directories( + ${CHROMAPRINT_LIBRARY_DIRS} + ${GSTREAMER_APP_LIBRARY_DIRS} + ${GLEW_LIBRARY_DIRS} +) + if(HAVE_VISUALISATIONS) target_link_libraries(clementine_lib ${LIBPROJECTM_LIBRARIES}) endif(HAVE_VISUALISATIONS) @@ -1424,9 +1430,6 @@ if (APPLE) install(FILES ../dist/cacert.pem DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Resources") - install(DIRECTORY "${QT_QTGUI_LIBRARY_RELEASE}/Versions/Current/Resources/" - DESTINATION "${CMAKE_BINARY_DIR}/clementine.app/Contents/Resources") - if (HAVE_BREAKPAD) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../3rdparty/google-breakpad/client/mac/build/Release/Breakpad.framework From b7d7ac4623b5a4a4a4747a9cbcb822e651d07740 Mon Sep 17 00:00:00 2001 From: John Maguire Date: Wed, 16 Oct 2019 19:43:07 +0100 Subject: [PATCH 099/104] Revert "Create dmg with genisoimage & libdmg-hfsplus" This reverts commit 08e1db494d82a466f4c8959247157c220abd0ab0. --- dist/create-dmg.sh | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/dist/create-dmg.sh b/dist/create-dmg.sh index 45746c0ad..ce05225b3 100755 --- a/dist/create-dmg.sh +++ b/dist/create-dmg.sh @@ -38,8 +38,21 @@ cp ../dist/dmg_background.png "$TMP/.background/background.png" cp ../dist/DS_Store.in "$TMP/.DS_Store" chmod go-rwx "$TMP/.DS_Store" ln -s /Applications "$TMP/Applications" -# copies the prepared bundle into the dir that will become the DMG +# copies the prepared bundle into the dir that will become the DMG cp -R "$IN" "$TMP" -genisoimage -D -V "Clementine" -no-pad -r -apple -o $NAME.iso $TMP -dmg dmg $NAME.iso $OUT +# create +hdiutil makehybrid -hfs -hfs-volume-name Clementine -hfs-openfolder "$TMP" "$TMP" -o tmp.dmg +hdiutil convert -format UDZO -imagekey zlib-level=9 tmp.dmg -o "$OUT" + +# cleanup +rm tmp.dmg + +#hdiutil create -srcfolder "$TMP" \ +# -format UDZO -imagekey zlib-level=9 \ +# -scrub \ +# "$OUT" \ +# || die "Error creating DMG :(" + +# done ! +echo 'DMG size:' `du -hs "$OUT" | awk '{print $1}'` From c035e664b77e9bffc89ef730d0972b9644a092ea Mon Sep 17 00:00:00 2001 From: John Maguire Date: Wed, 16 Oct 2019 21:07:00 +0100 Subject: [PATCH 100/104] Store useful cmake debug artifacts --- .circleci/config.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 973deb526..a1e9c9150 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -511,6 +511,10 @@ jobs: root: /tmp/artifacts paths: - mac/* + - store_artifacts: + path: bin/CMakeCache.txt + - store_artifacts: + path: bin/src/CMakeFiles/clementine.dir - store_artifacts: path: /tmp/artifacts/mac From b7f67ca7105be591e4859ecaa4d8bc8269820bf5 Mon Sep 17 00:00:00 2001 From: John Maguire Date: Wed, 16 Oct 2019 21:10:41 +0100 Subject: [PATCH 101/104] Try building faster --- .circleci/config.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a1e9c9150..c9292f202 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -447,7 +447,6 @@ jobs: echo 'export Qt5LinguistTools_DIR=/usr/local/Cellar/qt/5.13.1/lib/cmake/Qt5LinguistTools' >> $BASH_ENV echo 'export GST_SCANNER_PATH=/usr/local/Cellar/gstreamer/1.16.1/libexec/gstreamer-1.0/gst-plugin-scanner' >> $BASH_ENV echo 'export GST_PLUGIN_PATH=/usr/local/lib/gstreamer-1.0' >> $BASH_ENV - echo 'export PATH=/usr/local/opt/gettext/bin:$PATH' >> $BASH_ENV source $BASH_ENV - run: name: Install dependencies from homebrew @@ -491,7 +490,7 @@ jobs: working_directory: bin - run: name: make - command: make + command: make -j2 working_directory: bin - run: name: Copy icon file and resources From 08e5d52a84f9ef726bf44c01d2a1ac10abe085de Mon Sep 17 00:00:00 2001 From: John Maguire Date: Wed, 16 Oct 2019 21:44:38 +0100 Subject: [PATCH 102/104] Actually build the right branch --- .circleci/config.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c9292f202..bba5a1251 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -473,9 +473,6 @@ jobs: qt sqlite - checkout - - run: - name: Checkout qt5 branch - command: git checkout qt5 - run: name: cmake command: > From 6201247c07885ce916cd1bfd0c51340a4e51ab6e Mon Sep 17 00:00:00 2001 From: John Maguire Date: Wed, 16 Oct 2019 22:45:10 +0100 Subject: [PATCH 103/104] Upload mac qt5 DMG --- .circleci/config.yml | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index bba5a1251..65e544005 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -533,26 +533,13 @@ workflows: version: 2 build_all: jobs: - # - build_xenial_32 - # - build_xenial_64 - # - build_bionic_32 - build_bionic_64 - build_mac - # - build_disco_32 - # - build_disco_64 - # - build_fedora_29_64 - # - build_fedora_30_64 - # - upload_artifacts: - # context: gcp - # requires: - # - build_xenial_32 - # - build_xenial_64 - # - build_bionic_32 - # - build_bionic_64 - # - build_disco_32 - # - build_disco_64 - # - build_fedora_29_64 - # - build_fedora_30_64 - # filters: - # branches: - # only: master + - upload_artifacts: + context: gcp + requires: + - build_bionic_64 + - build_mac + filters: + branches: + only: qt5 From 18c2b416159ac031078c58f03e3c6a6c843984ac Mon Sep 17 00:00:00 2001 From: Dmitry Valter Date: Sat, 2 Nov 2019 10:16:42 +0300 Subject: [PATCH 104/104] Revert "Attempt to fix track change hang" Queue2 tends to hang up on pause, unable to start playing again. Pipeline actually stays PLAYING with ASYNC state change, so it becomes impossible to unpause the player without stop or forward/backward seeks. This reverts commit 2b280de663bc53b4f37dbb3f875cd630bad22c82. --- src/engines/gstenginepipeline.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engines/gstenginepipeline.cpp b/src/engines/gstenginepipeline.cpp index 29392f5b0..f3d468592 100644 --- a/src/engines/gstenginepipeline.cpp +++ b/src/engines/gstenginepipeline.cpp @@ -302,7 +302,7 @@ bool GstEnginePipeline::Init() { audioconvert_ = engine_->CreateElement("audioconvert", audiobin_); tee = engine_->CreateElement("tee", audiobin_); - probe_queue = engine_->CreateElement("queue2", audiobin_); + probe_queue = engine_->CreateElement("queue", audiobin_); probe_converter = engine_->CreateElement("audioconvert", audiobin_); probe_sink = engine_->CreateElement("fakesink", audiobin_);