diff --git a/.gersemirc b/.gersemirc new file mode 100644 index 000000000..8459e681b --- /dev/null +++ b/.gersemirc @@ -0,0 +1,10 @@ +# SPDX-FileCopyrightText: no +# SPDX-License-Identifier: CC0-1.0 +# +# Gersemi configuration +color: false +definitions: [ CMakeModules/CalamaresAddTest.cmake ] +line_length: 120 +quiet: false +unsafe: false + diff --git a/3rdparty/kdsingleapplicationguard/LICENSE.LGPL.txt b/3rdparty/kdsingleapplicationguard/LICENSE.LGPL.txt deleted file mode 100644 index df942b1ff..000000000 --- a/3rdparty/kdsingleapplicationguard/LICENSE.LGPL.txt +++ /dev/null @@ -1,488 +0,0 @@ - - The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. - - You may use, distribute and copy the KD Tools Library under the terms of - GNU Library General Public License version 2, which is displayed below. - -------------------------------------------------------------------------- - GNU LIBRARY GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1991 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the library GPL. It is - numbered 2 because it goes with version 2 of the ordinary GPL.] - - 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 Library General Public License, applies to some -specially designated Free Software Foundation software, and to any -other libraries whose authors decide to use it. You can use it for -your libraries, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if -you distribute copies of the 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 a program 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. - - Our method of protecting your rights has two steps: (1) copyright -the library, and (2) offer you this license which gives you legal -permission to copy, distribute and/or modify the library. - - Also, for each distributor's protection, we want to make certain -that everyone understands that there is no warranty for this free -library. If the library is modified by someone else and passed on, we -want its recipients to know that what they have is not the original -version, so that any problems introduced by others will not reflect on -the original authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that companies distributing free -software will individually obtain patent licenses, thus in effect -transforming the program into proprietary software. To prevent this, -we have made it clear that any patent must be licensed for everyone's -free use or not licensed at all. - - Most GNU software, including some libraries, is covered by the ordinary -GNU General Public License, which was designed for utility programs. This -license, the GNU Library General Public License, applies to certain -designated libraries. This license is quite different from the ordinary -one; be sure to read it in full, and don't assume that anything in it is -the same as in the ordinary license. - - The reason we have a separate public license for some libraries is that -they blur the distinction we usually make between modifying or adding to a -program and simply using it. Linking a program with a library, without -changing the library, is in some sense simply using the library, and is -analogous to running a utility program or application program. However, in -a textual and legal sense, the linked executable is a combined work, a -derivative of the original library, and the ordinary General Public License -treats it as such. - - Because of this blurred distinction, using the ordinary General -Public License for libraries did not effectively promote software -sharing, because most developers did not use the libraries. We -concluded that weaker conditions might promote sharing better. - - However, unrestricted linking of non-free programs would deprive the -users of those programs of all benefit from the free status of the -libraries themselves. This Library General Public License is intended to -permit developers of non-free programs to use free libraries, while -preserving your freedom as a user of such programs to change the free -libraries that are incorporated in them. (We have not seen how to achieve -this as regards changes in header files, but we have achieved it as regards -changes in the actual functions of the Library.) The hope is that this -will lead to faster development of free libraries. - - 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, while the latter only -works together with the library. - - Note that it is possible for a library to be covered by the ordinary -General Public License rather than by this special one. - - GNU LIBRARY GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library which -contains a notice placed by the copyright holder or other authorized -party saying it may be distributed under the terms of this Library -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 compile 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) 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. - - c) 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. - - d) 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 source code distributed need not include anything that is normally -distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - 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 to -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 Library 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 Library General Public - License as published by the Free Software Foundation; either - version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp b/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp deleted file mode 100644 index 284870e06..000000000 --- a/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp +++ /dev/null @@ -1,481 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB. - * SPDX-License-Identifier: LGPL-2.0-only - * - * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. - */ -#include "kdlockedsharedmemorypointer.h" - -#if QT_VERSION >= 0x040400 || defined( DOXYGEN_RUN ) -#ifndef QT_NO_SHAREDMEMORY - -namespace kdtools -{ -} -using namespace kdtools; - -KDLockedSharedMemoryPointerBase::KDLockedSharedMemoryPointerBase( QSharedMemory * m ) - : locker( m ), - mem( m ) -{ - -} - -KDLockedSharedMemoryPointerBase::KDLockedSharedMemoryPointerBase( QSharedMemory & m ) - : locker( &m ), - mem( &m ) -{ - -} - -KDLockedSharedMemoryPointerBase::~KDLockedSharedMemoryPointerBase() {} - -void * KDLockedSharedMemoryPointerBase::get() { - return mem ? mem->data() : 0 ; -} - -const void * KDLockedSharedMemoryPointerBase::get() const { - return mem ? mem->data() : 0 ; -} - -size_t KDLockedSharedMemoryPointerBase::byteSize() const { - return mem ? mem->size() : 0; -} - -/*! - \class KDLockedSharedMemoryPointer - \ingroup core raii smartptr - \brief Locking pointer for Qt shared memory segments - \since_c 2.1 - - (The exception safety of this class has not been evaluated yet.) - - KDLockedSharedMemoryPointer is a smart immutable pointer, which gives convenient and safe access to a QSharedMemory data segment. - The content of a KDLockedSharedMemoryPointer cannot be changed during it's lifetime. - - You can use this class like a normal pointer to the shared memory segment and be sure it's locked while accessing it. - \note You can only put simple types/structs/classes into it. structs and classes shall not contain any other pointers. See the - documentation of QSharedMemory for details. -*/ - -/*! - \fn KDLockedSharedMemoryPointer::KDLockedSharedMemoryPointer( QSharedMemory * mem ) - - Constructor. Constructs a KDLockedSharedMemory pointer which points to the data segment of \a mem. - The constructor locks \a mem. If the memory segment is already locked by another process, this constructor - blocks until the lock is released. - - \post data() == mem->data() and the memory segment has been locked -*/ - -/*! - \fn KDLockedSharedMemoryPointer::KDLockedSharedMemoryPointer( QSharedMemory & mem ) - - \overload - - \post data() == mem.data() and the memory segment has been locked -*/ - -/*! - \fn KDLockedSharedMemoryPointer::~KDLockedSharedMemoryPointer() - - Destructor. Unlocks the shared memory segment. - - \post The shared memory segment has been unlocked -*/ - -/*! - \fn T * KDLockedSharedMemoryPointer::get() - - \returns a pointer to the contained object. -*/ - -/*! - \fn const T * KDLockedSharedMemoryPointer::get() const - - \returns a const pointer to the contained object - \overload -*/ - -/*! - \fn T * KDLockedSharedMemoryPointer::data() - - Equivalent to get(), provided for consistency with Qt naming conventions. -*/ - -/*! - \fn const T * KDLockedSharedMemoryPointer::data() const - - \overload -*/ - -/*! - \fn T & KDLockedSharedMemoryPointer::operator*() - - Dereference operator. Returns \link get() *get()\endlink. -*/ - -/*! - \fn const T & KDLockedSharedMemoryPointer::operator*() const - - Dereference operator. Returns \link get() *get()\endlink. - \overload -*/ - -/*! - \fn T * KDLockedSharedMemoryPointer::operator->() - - Member-by-pointer operator. Returns get(). -*/ - -/*! - \fn const T * KDLockedSharedMemoryPointer::operator->() const - - Member-by-pointer operator. Returns get(). - \overload -*/ - -/*! - \class KDLockedSharedMemoryArray - \ingroup core raii smartptr - \brief Locking array pointer to Qt shared memory segments - \since_c 2.1 - - (The exception safety of this class has not been evaluated yet.) - - KDLockedSharedMemoryArray is a smart immutable pointer, which gives convenient and safe access to array data stored in a QSharedMemory - data segment. - The content of a KDLockedSharedMemoryArray cannot be changed during it's lifetime. - - You can use this class like a normal pointer to the shared memory segment and be sure it's locked while accessing it. - \note You can only put arrays of simple types/structs/classes into it. structs and classes shall not contain any other pointers. See the - documentation of QSharedMemory for details. - - \sa KDLockedSharedMemoryPointer -*/ - -/*! - \fn KDLockedSharedMemoryArray::KDLockedSharedMemoryArray( QSharedMemory* mem ) - Constructor. Constructs a KDLockedSharedMemoryArray which points to the data segment of \a mem. The constructor locks \a mem. If the memory - segment is already locked by another process, this constructor blocks until the lock is release. - - \post get() == mem->data() and the memory segment has been locked -*/ - -/*! - \fn KDLockedSharedMemoryArray::KDLockedSharedMemoryArray( QSharedMemory& mem ) - \overload - - \post get() == mem->data() and the memory segment has been locked -*/ - - -/*! - \typedef KDLockedSharedMemoryArray::size_type - Typedef for std::size_t. Provided for STL compatibility. -*/ - -/*! - \typedef KDLockedSharedMemoryArray::difference_type - Typedef for std::ptrdiff_t. Provided for STL compatibility. -*/ - -/*! - \typedef KDLockedSharedMemoryArray::iterator - Typedef for T*. Provided for STL compatibility. - \since_t 2.2 -*/ - -/*! - \typedef KDLockedSharedMemoryArray::const_iterator - Typedef for const T*. Provided for STL compatibility. - \since_t 2.2 -*/ - -/*! - \typedef KDLockedSharedMemoryArray::reverse_iterator - Typedef for std::reverse_iterator< \link KDLockedSharedMemoryArray::iterator iterator\endlink >. Provided for STL compatibility. - \since_t 2.2 -*/ - -/*! - \typedef KDLockedSharedMemoryArray::const_reverse_iterator - Typedef for std::reverse_iterator< \link KDLockedSharedMemoryArray::const_iterator const_iterator\endlink >. Provided for STL compatibility. - \since_t 2.2 -*/ - -/*! - \fn KDLockedSharedMemoryArray::iterator KDLockedSharedMemoryArray::begin() - Returns an \link KDLockedSharedMemoryArray::iterator iterator\endlink pointing to the first item of the array. - \since_f 2.2 -*/ - -/*! - \fn KDLockedSharedMemoryArray::const_iterator KDLockedSharedMemoryArray::begin() const - \overload - \since_f 2.2 -*/ - -/*! - \fn KDLockedSharedMemoryArray::iterator KDLockedSharedMemoryArray::end() - Returns an \link KDLockedSharedMemoryArray::iterator iterator\endlink pointing to the item after the last item of the array. - \since_f 2.2 -*/ - -/*! - \fn KDLockedSharedMemoryArray::const_iterator KDLockedSharedMemoryArray::end() const - \overload - \since_f 2.2 -*/ - -/*! - \fn KDLockedSharedMemoryArray::reverse_iterator KDLockedSharedMemoryArray::rbegin() - Returns an \link KDLockedSharedMemoryArray::reverse_iterator reverse_iterator\endlink pointing to the item after the last item of the array. - \since_f 2.2 -*/ - -/*! - \fn KDLockedSharedMemoryArray::const_reverse_iterator KDLockedSharedMemoryArray::rbegin() const - \overload - \since_f 2.2 -*/ - -/*! - \fn KDLockedSharedMemoryArray::reverse_iterator KDLockedSharedMemoryArray::rend() - Returns an \link KDLockedSharedMemoryArray::reverse_iterator reverse_iterator\endlink pointing to the first item of the array. - \since_f 2.2 -*/ - -/*! - \fn KDLockedSharedMemoryArray::const_reverse_iterator KDLockedSharedMemoryArray::rend() const - \overload - \since_f 2.2 -*/ - -/*! - \fn KDLockedSharedMemoryArray::size_type KDLockedSharedMemoryArray::size() const - Returns the size of this array. The size is calculated from the storage size of T and - the size of the shared memory segment. - \since_f 2.2 -*/ - -/*! - \fn T& KDLockedSharedMemoryArray::operator[]( difference_type n ) - Array access operator. Returns a reference to the item at index position \a n. -*/ - -/*! - \fn const T& KDLockedSharedMemoryArray::operator[]( difference_type n ) const - \overload -*/ - -/*! - \fn T& KDLockedSharedMemoryArray::front() - Returns a reference to the first item in the array. This is the same as operator[](0). -*/ - -/*! - \fn const T& KDLockedSharedMemoryArray::front() const - \overload -*/ - -/*! - \fn T& KDLockedSharedMemoryArray::back() - Returns a reference to the last item in the array. This is the same as operator[](size()-1). - \since_f 2.2 -*/ - -/*! - \fn const T& KDLockedSharedMemoryArray::back() const - \overload - \since_f 2.2 -*/ - - -#ifdef eKDTOOLSCORE_UNITTESTS - -#include - -#include -#include - -namespace -{ - struct TestStruct - { - TestStruct( uint nn = 0 ) - : n( nn ), - f( 0.0 ), - c( '\0' ), - b( false ) - { - } - uint n; - double f; - char c; - bool b; - }; - - bool operator==( const TestStruct& lhs, const TestStruct& rhs ) - { - return lhs.n == rhs.n && lhs.f == rhs.f && lhs.c == rhs.c && lhs.b == rhs.b; - } - - class TestThread : public QThread - { - public: - TestThread( const QString& key ) - : mem( key ) - { - mem.attach(); - } - - void run() - { - while( true ) - { - msleep( 100 ); - kdtools::KDLockedSharedMemoryPointer< TestStruct > p( &mem ); - if( !p->b ) - continue; - - p->n = 5; - p->f = 3.14; - p->c = 'A'; - p->b = false; - return; - } - } - - QSharedMemory mem; - }; - - bool isConst( TestStruct* ) - { - return false; - } - - bool isConst( const TestStruct* ) - { - return true; - } -} - - -KDAB_UNITTEST_SIMPLE( KDLockedSharedMemoryPointer, "kdcoretools" ) { - - const QString key = QUuid::createUuid(); - QSharedMemory mem( key ); - const bool created = mem.create( sizeof( TestStruct ) ); - assertTrue( created ); - if ( !created ) - return; // don't execute tests if shm coulnd't be created - - // On Windows, shared mem is only available in increments of page - // size (4k), so don't fail if the segment is larger: - const unsigned long mem_size = mem.size(); - assertGreaterOrEqual( mem_size, sizeof( TestStruct ) ); - - { - kdtools::KDLockedSharedMemoryPointer< TestStruct > p( &mem ); - assertTrue( p ); - *p = TestStruct(); - assertEqual( p->n, 0u ); - assertEqual( p->f, 0.0 ); - assertEqual( p->c, '\0' ); - assertFalse( p->b ); - } - - { - TestThread thread( key ); - assertEqual( thread.mem.key().toStdString(), key.toStdString() ); - assertEqual( static_cast< unsigned long >( thread.mem.size() ), mem_size ); - thread.start(); - - assertTrue( thread.isRunning() ); - thread.wait( 2000 ); - assertTrue( thread.isRunning() ); - - { - kdtools::KDLockedSharedMemoryPointer< TestStruct > p( &mem ); - p->b = true; - } - - thread.wait( 2000 ); - assertFalse( thread.isRunning() ); - } - - { - kdtools::KDLockedSharedMemoryPointer< TestStruct > p( &mem ); - assertEqual( p->n, 5u ); - assertEqual( p->f, 3.14 ); - assertEqual( p->c, 'A' ); - assertFalse( p->b ); - } - - { - kdtools::KDLockedSharedMemoryPointer< TestStruct > p( mem ); - assertEqual( mem.data(), p.get() ); - assertEqual( p.get(), p.operator->() ); - assertEqual( p.get(), &(*p) ); - assertEqual( p.get(), p.data() ); - assertFalse( isConst( p.get() ) ); - } - - { - const kdtools::KDLockedSharedMemoryPointer< TestStruct > p( &mem ); - assertEqual( mem.data(), p.get() ); - assertEqual( p.get(), p.operator->() ); - assertEqual( p.get(), &(*p) ); - assertEqual( p.get(), p.data() ); - assertTrue( isConst( p.get() ) ); - } - - { - QSharedMemory mem2( key + key ); - const bool created2 = mem2.create( 16 * sizeof( TestStruct ) ); - assertTrue( created2 ); - if ( !created2 ) - return; // don't execute tests if shm coulnd't be created - - kdtools::KDLockedSharedMemoryArray a( mem2 ); - assertTrue( a ); - assertEqual( a.get(), mem2.data() ); - assertEqual( &a[0], a.get() ); - - a[1] = a[0]; - assertTrue( a[0] == a[1] ); - - TestStruct ts; - ts.n = 5; - ts.f = 3.14; - a[0] = ts; - assertFalse( a[0] == a[1] ); - assertEqual( a.front().n, ts.n ); - assertEqual( a[0].f, ts.f ); - a[0].n = 10; - assertEqual( a.front().n, 10u ); - ts = a[0]; - assertEqual( ts.n, 10u ); - - std::vector< TestStruct > v; - for( uint i = 0; i < a.size(); ++i ) - v.push_back( TestStruct( i ) ); - - std::copy( v.begin(), v.end(), a.begin() ); - for( uint i = 0; i < a.size(); ++i ) - assertEqual( a[ i ].n, i ); - assertEqual( a.front().n, 0u ); - assertEqual( a.back().n, a.size() - 1 ); - - std::copy( v.begin(), v.end(), a.rbegin() ); - for( uint i = 0; i < a.size(); ++i ) - assertEqual( a[ i ].n, a.size() - 1 - i ); - assertEqual( a.front().n, a.size() - 1 ); - assertEqual( a.back().n, 0u ); - } - -} -#endif // KDTOOLSCORE_UNITTESTS -#endif // QT_NO_SHAREDMEMORY -#endif // QT_VERSION >= 0x040400 || defined( DOXYGEN_RUN ) diff --git a/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.h b/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.h deleted file mode 100644 index 19fdaa082..000000000 --- a/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB. - * SPDX-License-Identifier: LGPL-2.0-only - * - * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. - */ -#ifndef __KDTOOLS__CORE__KDLOCKEDSHAREDMEMORYPOINTER_H__ -#define __KDTOOLS__CORE__KDLOCKEDSHAREDMEMORYPOINTER_H__ - -#include - -#if QT_VERSION >= 0x040400 || defined( DOXYGEN_RUN ) -#ifndef QT_NO_SHAREDMEMORY - -#include "kdsharedmemorylocker.h" -#include - -#include - -#ifndef DOXYGEN_RUN -namespace kdtools { -#endif - -class KDLockedSharedMemoryPointerBase { -protected: - explicit KDLockedSharedMemoryPointerBase( QSharedMemory * mem ); - explicit KDLockedSharedMemoryPointerBase( QSharedMemory & mem ); - ~KDLockedSharedMemoryPointerBase(); - - // PENDING(marc) do we really want const propagation here? I - // usually declare all my RAII objects const... - void * get(); - const void * get() const; - - KDAB_IMPLEMENT_SAFE_BOOL_OPERATOR( get() ) - - size_t byteSize() const; - -private: - KDSharedMemoryLocker locker; - QSharedMemory * const mem; -}; - -template< typename T> -class MAKEINCLUDES_EXPORT KDLockedSharedMemoryPointer : KDLockedSharedMemoryPointerBase { - KDAB_DISABLE_COPY( KDLockedSharedMemoryPointer ); -public: - explicit KDLockedSharedMemoryPointer( QSharedMemory * m ) - : KDLockedSharedMemoryPointerBase( m ) {} - explicit KDLockedSharedMemoryPointer( QSharedMemory & m ) - : KDLockedSharedMemoryPointerBase( m ) {} - - T * get() { return static_cast( KDLockedSharedMemoryPointerBase::get() ); } - const T * get() const { return static_cast( KDLockedSharedMemoryPointerBase::get() ); } - - T * data() { return static_cast( get() ); } - const T * data() const { return static_cast( get() ); } - - T & operator*() { assert( get() ); return *get(); } - const T & operator*() const { assert( get() ); return *get(); } - - T * operator->() { return get(); } - const T * operator->() const { return get(); } - - KDAB_USING_SAFE_BOOL_OPERATOR( KDLockedSharedMemoryPointerBase ) -}; - -template -class MAKEINCLUDES_EXPORT KDLockedSharedMemoryArray : KDLockedSharedMemoryPointerBase { - KDAB_DISABLE_COPY( KDLockedSharedMemoryArray ); -public: - explicit KDLockedSharedMemoryArray( QSharedMemory * m ) - : KDLockedSharedMemoryPointerBase( m ) {} - explicit KDLockedSharedMemoryArray( QSharedMemory & m ) - : KDLockedSharedMemoryPointerBase( m ) {} - - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef T* iterator; - typedef const T* const_iterator; - typedef std::reverse_iterator< const_iterator > const_reverse_iterator; - typedef std::reverse_iterator< iterator > reverse_iterator; - - iterator begin() { return get(); } - const_iterator begin() const { return get(); } - - iterator end() { return begin() + size(); } - const_iterator end() const { return begin() + size(); } - - reverse_iterator rbegin() { return reverse_iterator( end() ); } - const_reverse_iterator rbegin() const { return reverse_iterator( end() ); } - - reverse_iterator rend() { return reverse_iterator( begin() ); } - const_reverse_iterator rend() const { return const_reverse_iterator( begin() ); } - - size_type size() const { return byteSize() / sizeof( T ); } - - T * get() { return static_cast( KDLockedSharedMemoryPointerBase::get() ); } - const T * get() const { return static_cast( KDLockedSharedMemoryPointerBase::get() ); } - - T & operator[]( difference_type n ) { assert( get() ); return *(get()+n); } - const T & operator[]( difference_type n ) const { assert( get() ); return *(get()+n); } - - T & front() { assert( get() ); return *get(); } - const T & front() const { assert( get() ); return *get(); } - - T & back() { assert( get() ); return *( get() + size() - 1 ); } - const T & back() const { assert( get() ); return *( get() + size() - 1 ); } - - KDAB_USING_SAFE_BOOL_OPERATOR( KDLockedSharedMemoryPointerBase ) -}; - -#ifndef DOXYGEN_RUN -} -#endif - -#endif /* QT_NO_SHAREDMEMORY */ - -#endif /* QT_VERSION >= 0x040400 || defined( DOXYGEN_RUN ) */ - -#endif /* __KDTOOLS__CORE__KDLOCKEDSHAREDMEMORYPOINTER_H__ */ diff --git a/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.cpp b/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.cpp deleted file mode 100644 index 3af326193..000000000 --- a/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB. - * SPDX-License-Identifier: LGPL-2.0-only - * - * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. - */ -#include "kdsharedmemorylocker.h" - -#if QT_VERSION >= 0x040400 || defined( DOXYGEN_RUN ) - -#include - -using namespace kdtools; - -/*! - \class KDSharedMemoryLocker - \ingroup raii core - \brief Exception-safe and convenient wrapper around QSharedMemory::lock() -*/ - -/** - * Constructor. Locks the shared memory segment \a mem. - * If another process has locking the segment, this constructor blocks - * until the lock is released. The memory segments needs to be properly created or attached. - */ -KDSharedMemoryLocker::KDSharedMemoryLocker( QSharedMemory* mem ) - : mem( mem ) -{ - mem->lock(); -} - -/** - * Destructor. Unlocks the shared memory segment associated with this - * KDSharedMemoryLocker. - */ -KDSharedMemoryLocker::~KDSharedMemoryLocker() -{ - mem->unlock(); -} - -#ifdef KDAB_EVAL -#include KDAB_EVAL -static const EvalDialogChecker evalChecker( "KD Tools", false ); -#endif - -#endif diff --git a/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.h b/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.h deleted file mode 100644 index 64b5c267f..000000000 --- a/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB. - * SPDX-License-Identifier: LGPL-2.0-only - * - * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. - */ -#ifndef __KDTOOLS__CORE__KDSHAREDMEMORYLOCKER_H -#define __KDTOOLS__CORE__KDSHAREDMEMORYLOCKER_H - -#include "kdtoolsglobal.h" - -#if QT_VERSION < 0x040400 && !defined( DOXYGEN_RUN ) -#ifdef Q_CC_GNU -#warning "Can't use KDTools KDSharedMemoryLocker with Qt versions prior to 4.4" -#endif -#else - -class QSharedMemory; - -#ifndef DOXYGEN_RUN -namespace kdtools -{ -#endif - -class KDTOOLSCORE_EXPORT KDSharedMemoryLocker -{ - Q_DISABLE_COPY( KDSharedMemoryLocker ) -public: - KDSharedMemoryLocker( QSharedMemory* mem ); - ~KDSharedMemoryLocker(); - -private: - QSharedMemory* const mem; -}; - -#ifndef DOXYGEN_RUN -} -#endif - -#endif - -#endif diff --git a/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.cpp b/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.cpp deleted file mode 100644 index 52eb60d37..000000000 --- a/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.cpp +++ /dev/null @@ -1,1256 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB. - * SPDX-License-Identifier: LGPL-2.0-only - * - * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. - */ -#include "kdsingleapplicationguard.h" - -#if QT_VERSION >= 0x040400 || defined(DOXYGEN_RUN) -#ifndef QT_NO_SHAREDMEMORY - -#include "kdsharedmemorylocker.h" -#include "kdlockedsharedmemorypointer.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifndef Q_WS_WIN -#include -#include -#endif - -#ifdef Q_WS_WIN -#include -#ifndef _SSIZE_T_DEFINED -typedef signed int ssize_t; -#endif -#endif - -using namespace kdtools; - -#ifndef KDSINGLEAPPLICATIONGUARD_TIMEOUT_SECONDS -#define KDSINGLEAPPLICATIONGUARD_TIMEOUT_SECONDS 10 -#endif - -#ifndef KDSINGLEAPPLICATIONGUARD_NUMBER_OF_PROCESSES -#define KDSINGLEAPPLICATIONGUARD_NUMBER_OF_PROCESSES 10 -#endif - -#ifndef KDSINGLEAPPLICATIONGUARD_MAX_COMMAND_LINE -#define KDSINGLEAPPLICATIONGUARD_MAX_COMMAND_LINE 32768 -#endif - -static unsigned int KDSINGLEAPPLICATIONGUARD_SHM_VERSION = 0; - -Q_GLOBAL_STATIC_WITH_ARGS( int, registerInstanceType, - (qRegisterMetaType()) ) - -/*! - \class KDSingleApplicationGuard::Instance - \relates KDSingleApplicationGuard - \ingroup core - \brief Information about instances a KDSingleApplicationGuard knows about - - Instance represents instances of applications under - KDSingleApplicationGuard protection, and allows access to their - pid() and the arguments() they were started with. -*/ - -class KDSingleApplicationGuard::Instance::Private : public QSharedData { - friend class ::KDSingleApplicationGuard::Instance; -public: - Private( const QStringList & args, bool truncated, qint64 pid ) - : pid( pid ), arguments( args ), truncated( truncated ) {} - -private: - qint64 pid; - QStringList arguments; - bool truncated; -}; - -struct ProcessInfo; - -/*! - \internal - */ -class KDSingleApplicationGuard::Private -{ - friend class ::KDSingleApplicationGuard; - friend class ::KDSingleApplicationGuard::Instance; - friend struct ::ProcessInfo; - KDSingleApplicationGuard * const q; -public: - Private( Policy policy, KDSingleApplicationGuard* qq ); - ~Private(); - - void create( const QStringList& arguments ); - - bool checkOperational( const char * function, const char * act ) const; - bool checkOperationalPrimary( const char * function, const char * act ) const; - - struct segmentheader - { - size_t size : 16; - }; - - static void sharedmem_free( char* ); - static char* sharedmem_malloc( size_t size ); - -private: - void shutdownInstance(); - void poll(); - -private: - static KDSingleApplicationGuard* primaryInstance; - -private: - QBasicTimer timer; - QSharedMemory mem; - int id; - Policy policy; - bool operational; - bool exitRequested; -}; - -/*! - \internal -*/ -KDSingleApplicationGuard::Instance::Instance( const QStringList & args, bool truncated, qint64 p ) - : d( new Private( args, truncated, p ) ) -{ - d->ref.ref(); - (void)registerInstanceType(); -} - -/*! - Default constructor. Constructs in Instance that is \link isNull() - null\endlink. - - \sa isNull() -*/ -KDSingleApplicationGuard::Instance::Instance() : d( 0 ) {} - -/*! - Copy constructor. -*/ -KDSingleApplicationGuard::Instance::Instance( const Instance & other ) - : d( other.d ) -{ - if ( d ) - d->ref.ref(); -} - -/*! - Destructor. -*/ -KDSingleApplicationGuard::Instance::~Instance() -{ - if ( d && !d->ref.deref() ) - delete d; -} - -/*! - \fn KDSingleApplicationGuard::Instance::swap( Instance & other ) - - Swaps the contents of this and \a other. - - This function never throws exceptions. -*/ - -/*! - \fn KDSingleApplicationGuard::Instance::operator=( Instance other ) - - Assigns the contents of \a other to this. - - This function is strongly exception-safe. -*/ - -/*! - \fn std::swap( KDSingleApplicationGuard::Instance & lhs, KDSingleApplicationGuard::Instance & rhs ) - \relates KDSingleApplicationGuard::Instance - - Specialisation of std::swap() for - KDSingleApplicationGuard::Instance. Calls swap(). -*/ - -/*! - \fn qSwap( KDSingleApplicationGuard::Instance & lhs, KDSingleApplicationGuard::Instance & rhs ) - \relates KDSingleApplicationGuard::Instance - - Specialisation of qSwap() for - KDSingleApplicationGuard::Instance. Calls swap(). -*/ - -/*! - \fn KDSingleApplicationGuard::Instance::isNull() const - - Returns whether this instance is null. -*/ - -/*! - Returns whether this instance is valid. A valid instance is neither - null, nor does it have a negative PID. -*/ -bool KDSingleApplicationGuard::Instance::isValid() const -{ - return d && d->pid >= 0 ; -} - -/*! - Returns whether the #arguments are complete (\c false) or not (\c - true), e.g. because they have been truncated due to limited storage - space. - - \sa arguments() -*/ -bool KDSingleApplicationGuard::Instance::areArgumentsTruncated() const -{ - return d && d->truncated; -} - -/*! - Returns the arguments that this instance was started with. - - \sa areArgumentsTruncated() -*/ -const QStringList & KDSingleApplicationGuard::Instance::arguments() const -{ - if ( d ) - return d->arguments; - static const QStringList empty; - return empty; -} - -/*! - Returns the process-id (PID) of this instance. -*/ -qint64 KDSingleApplicationGuard::Instance::pid() const -{ - if ( d ) - return d->pid; - else - return -1; -} - -/*! - \class KDSingleApplicationGuard KDSingleApplicationGuard - \ingroup core - \brief A guard to protect an application from having several instances. - - KDSingleApplicationGuard can be used to make sure only one instance of an - application is running at the same time. - - \note As KDSingleApplicationGuard currently uses QSharedMemory, Qt - 4.4 or later is required. - */ - -/*! - \fn void KDSingleApplicationGuard::instanceStarted(const KDSingleApplicationGuard::Instance & instance) - - This signal is emitted by the primary instance whenever another - instance \a instance started. - */ - -/*! - \fn void KDSingleApplicationGuard::instanceExited(const KDSingleApplicationGuard::Instance & instance) - - This signal is emitted by the primary instance whenever another - instance \a instance exited. - */ - -/*! - \fn void KDSingleApplicationGuard::raiseRequested() - - This signal is emitted when the current running application is requested - to raise its main window. -*/ - -/*! - \fn void KDSingleApplicationGuard::exitRequested() - - This signal is emitted when the current running application has been asked to exit - by calling kill on the instance. -*/ - -/*! - \fn void KDSingleApplicationGuard::becamePrimaryInstance() - - This signal is emitted when the current running application becomes - the new primary application. The old primary application has quit. - */ - -/*! - \fn void KDSingleApplicationGuard::becameSecondaryInstance() - - This signal is emmited when the primary instance became secondary instance. - This happens when the instance doesn't update its status for some (default 10) seconds. Another instance - got primary instance in that case. - */ - -/*! - \fn void KDSingleApplicationGuard::policyChanged( KDSingleApplicationGuard::Policy policy ) - - This signal is emitted when the #policy of the system changes. -*/ - -enum Command -{ - NoCommand = 0x00, - ExitedInstance = 0x01, - NewInstance = 0x02, - FreeInstance = 0x04, - ShutDownCommand = 0x08, - KillCommand = 0x10, - BecomePrimaryCommand = 0x20, - RaiseCommand = 0x40 -}; - -static const quint16 PrematureEndOfOptions = -1; -static const quint16 RegularEndOfOptions = -2; - -struct ProcessInfo -{ - static const size_t MarkerSize = sizeof(quint16); - - explicit ProcessInfo( Command c = FreeInstance, const QStringList& arguments = QStringList(), qint64 p = -1 ) - : pid( p ), - command( c ), - timestamp( 0 ), - commandline( 0 ) - { - setArguments( arguments ); - } - - void setArguments( const QStringList & arguments ); - QStringList arguments( bool * prematureEnd ) const; - - qint64 pid; - quint32 command; - quint32 timestamp; - char* commandline; -}; - -static inline bool operator==( const ProcessInfo & lhs, const ProcessInfo & rhs ) -{ - return lhs.command == rhs.command && - ( lhs.commandline == rhs.commandline || ( lhs.commandline != 0 && rhs.commandline != 0 && ::strcmp( lhs.commandline, rhs.commandline ) == 0 ) ); -} - -static inline bool operator!=( const ProcessInfo & lhs, const ProcessInfo & rhs ) -{ - return !operator==( lhs, rhs ); -} - -/*! - This struct contains information about the managed process system. - \internal - */ -struct InstanceRegister -{ - explicit InstanceRegister( KDSingleApplicationGuard::Policy policy = KDSingleApplicationGuard::NoPolicy ) - : policy( policy ), - maxInstances( KDSINGLEAPPLICATIONGUARD_NUMBER_OF_PROCESSES ), - version( 0 ) - { - std::fill_n( commandLines, KDSINGLEAPPLICATIONGUARD_MAX_COMMAND_LINE, 0 ); - ::memcpy( magicCookie, "kdsingleapp", 12 ); - } - - /*! - Returns whether this register was properly initialized by the first instance. - */ - bool isValid() const - { - return ::strcmp( magicCookie, "kdsingleapp" ) == 0; - } - - char magicCookie[ 12 ]; - unsigned int policy : 8; - quint32 maxInstances : 20; - unsigned int version : 4; - ProcessInfo info[ KDSINGLEAPPLICATIONGUARD_NUMBER_OF_PROCESSES ]; - - char commandLines[ KDSINGLEAPPLICATIONGUARD_MAX_COMMAND_LINE ]; - - Q_DISABLE_COPY( InstanceRegister ) -}; - -void ProcessInfo::setArguments( const QStringList & arguments ) -{ - if( commandline != 0 ) - KDSingleApplicationGuard::Private::sharedmem_free( commandline ); - - commandline = 0; - if( arguments.isEmpty() ) - return; - - size_t totalsize = MarkerSize; - for ( const QString& arg : arguments ) - { - const QByteArray utf8 = arg.toUtf8(); - totalsize += utf8.size() + MarkerSize; - } - InstanceRegister* const reg = reinterpret_cast( KDSingleApplicationGuard::Private::primaryInstance->d->mem.data() ); - this->commandline = KDSingleApplicationGuard::Private::sharedmem_malloc( totalsize ); - if( this->commandline == 0 ) - { - qWarning("KDSingleApplicationguard: out of memory when trying to save arguments.\n"); - return; - } - - char* const commandline = this->commandline + reinterpret_cast(reg->commandLines); - - int argpos = 0; - for ( const QString & arg : arguments ) - { - const QByteArray utf8 = arg.toUtf8(); - const int required = MarkerSize + utf8.size() + MarkerSize ; - const int available = KDSINGLEAPPLICATIONGUARD_MAX_COMMAND_LINE - argpos ; - if ( required > available || utf8.size() > std::numeric_limits::max() ) { - // write a premature-eoo marker, and quit - memcpy( commandline + argpos, &PrematureEndOfOptions, MarkerSize ); - argpos += MarkerSize; - qWarning( "KDSingleApplicationGuard: argument list is too long (bytes required: %d, used: %d, available: %d", - required, argpos - 2, available ); - return; - } else { - const quint16 len16 = utf8.size(); - // write the size of the data... - memcpy( commandline + argpos, &len16, MarkerSize ); - argpos += MarkerSize; - // then the data - memcpy( commandline + argpos, utf8.data(), len16 ); - argpos += len16; - } - } - const ssize_t available = KDSINGLEAPPLICATIONGUARD_MAX_COMMAND_LINE - argpos; - assert( available >= static_cast( MarkerSize ) ); - memcpy( commandline + argpos, &RegularEndOfOptions, MarkerSize ); - argpos += MarkerSize; -} - -QStringList ProcessInfo::arguments( bool * prematureEnd ) const -{ - QStringList result; - if( commandline == 0 ) - { - if( prematureEnd ) - *prematureEnd = true; - return result; - } - - InstanceRegister* const reg = reinterpret_cast( KDSingleApplicationGuard::Private::primaryInstance->d->mem.data() ); - const char* const commandline = this->commandline + reinterpret_cast(reg->commandLines); - - int argpos = 0; - while ( true ) { - const int available = KDSINGLEAPPLICATIONGUARD_MAX_COMMAND_LINE - argpos ; - assert( available >= 2 ); - - quint16 marker; - memcpy( &marker, commandline + argpos, MarkerSize ); - argpos += MarkerSize; - - if ( marker == PrematureEndOfOptions ) { - if ( prematureEnd ) *prematureEnd = true; - break; - } - if ( marker == RegularEndOfOptions ) { - if ( prematureEnd ) *prematureEnd = false; - break; - } - - const int requested = MarkerSize + marker + MarkerSize ; - if ( requested > available ) { - const long long int p = pid; - qWarning( "KDSingleApplicationGuard: inconsistency detected when parsing command-line argument for process %lld", p ); - if ( prematureEnd ) *prematureEnd = true; - break; - } - - result.push_back( QString::fromUtf8( commandline + argpos, marker ) ); - argpos += marker; - } - - return result; -} - -KDSingleApplicationGuard::Private::~Private() -{ - if( primaryInstance == q ) - primaryInstance = 0; -} - -bool KDSingleApplicationGuard::Private::checkOperational( const char * function, const char * act ) const -{ - assert( function ); - assert( act ); - if ( !operational ) - qWarning( "KDSingleApplicationGuard::%s: need to be operational to %s", function, act ); - return operational; -} - -bool KDSingleApplicationGuard::Private::checkOperationalPrimary( const char * function, const char * act ) const -{ - if ( !checkOperational( function, act ) ) - return false; - if ( id != 0 ) - qWarning( "KDSingleApplicationGuard::%s: need to be primary to %s", function, act ); - return id == 0; -} - -struct segmentheader -{ - size_t size : 16; -}; - -void KDSingleApplicationGuard::Private::sharedmem_free( char* pointer ) -{ - InstanceRegister* const reg = reinterpret_cast( KDSingleApplicationGuard::Private::primaryInstance->d->mem.data() ); - char* const heap = reg->commandLines; - char* const heap_ptr = heap + reinterpret_cast(pointer) - sizeof( segmentheader ); - const segmentheader* const header = reinterpret_cast< const segmentheader* >( heap_ptr ); - const size_t size = header->size; - - char* end = heap + KDSINGLEAPPLICATIONGUARD_MAX_COMMAND_LINE; - - std::copy( heap_ptr + size, end, heap_ptr ); - std::fill( end - size, end, 0 ); - - for( uint i = 0; i < reg->maxInstances; ++i ) - { - if( reg->info[ i ].commandline > pointer ) - reg->info[ i ].commandline -= size + sizeof( segmentheader ); - } -} - -char* KDSingleApplicationGuard::Private::sharedmem_malloc( size_t size ) -{ - InstanceRegister* const reg = reinterpret_cast( KDSingleApplicationGuard::Private::primaryInstance->d->mem.data() ); - char* heap = reg->commandLines; - - while( heap + sizeof( segmentheader ) + size < reg->commandLines + KDSINGLEAPPLICATIONGUARD_MAX_COMMAND_LINE ) - { - segmentheader* const header = reinterpret_cast< segmentheader* >( heap ); - if( header->size == 0 ) - { - header->size = size; - return heap + sizeof( segmentheader ) - reinterpret_cast(reg->commandLines); - } - heap += sizeof( header ) + header->size; - } - return 0; -} - -void KDSingleApplicationGuard::Private::shutdownInstance() -{ - KDLockedSharedMemoryPointer< InstanceRegister > instances( &q->d->mem ); - instances->info[ q->d->id ].command |= ExitedInstance; - - if( q->isPrimaryInstance() ) - { - // ohh... we need a new primary instance... - for ( int i = 1, end = instances->maxInstances ; i < end ; ++i ) - { - if( ( instances->info[ i ].command & ( FreeInstance | ExitedInstance | ShutDownCommand | KillCommand ) ) == 0 ) - { - instances->info[ i ].command |= BecomePrimaryCommand; - return; - } - } - // none found? then my species is dead :-( - } -} - -KDSingleApplicationGuard* KDSingleApplicationGuard::Private::primaryInstance = 0; - -/*! - Requests that the instance kills itself (by emitting exitRequested). - - If the instance has since exited, does nothing. - - \sa shutdown(), raise() -*/ -void KDSingleApplicationGuard::Instance::kill() -{ - KDLockedSharedMemoryPointer< InstanceRegister > instances( &KDSingleApplicationGuard::Private::primaryInstance->d->mem ); - for ( int i = 0, end = instances->maxInstances ; i < end ; ++i ) - { - if( instances->info[ i ].pid != d->pid ) - continue; - if( ( instances->info[ i ].command & ( FreeInstance | ExitedInstance ) ) == 0 ) - instances->info[ i ].command = KillCommand; - } -} - -/*! - Requests that the instance shuts itself down (by calling QCoreApplication::quit()). - - If the instance has since exited, does nothing. - - \sa kill(), raise() -*/ -void KDSingleApplicationGuard::Instance::shutdown() -{ - KDLockedSharedMemoryPointer< InstanceRegister > instances( &KDSingleApplicationGuard::Private::primaryInstance->d->mem ); - for ( int i = 0, end = instances->maxInstances ; i < end ; ++i ) - { - if( instances->info[ i ].pid != d->pid ) - continue; - if( ( instances->info[ i ].command & ( FreeInstance | ExitedInstance ) ) == 0 ) - instances->info[ i ].command = ShutDownCommand; - } -} - -/*! - - Requests that the instance raises its main window. - - The effects are implementation-defined: the KDSingleApplicationGuard - corresponding to the instance will emit its \link - KDSingleApplicationGuard::raiseRequested() raiseRequested()\endlink - signal. - - If the instance has since exited, does nothing. - - \sa kill(), shutdown() -*/ -void KDSingleApplicationGuard::Instance::raise() -{ - KDLockedSharedMemoryPointer< InstanceRegister > instances( &KDSingleApplicationGuard::Private::primaryInstance->d->mem ); - for ( int i = 0, end = instances->maxInstances ; i < end ; ++i ) - { - if( instances->info[ i ].pid != d->pid ) - continue; - if( ( instances->info[ i ].command & ( FreeInstance | ExitedInstance ) ) == 0 ) - instances->info[ i ].command = RaiseCommand; - } -} - - -#ifndef Q_WS_WIN -// static -void KDSingleApplicationGuard::SIGINT_handler( int sig ) -{ - if( sig == SIGINT && Private::primaryInstance != 0 ) - Private::primaryInstance->d->shutdownInstance(); - ::exit( 1 ); -} -#endif - -/*! - \enum KDSingleApplicationGuard::Policy - - Defines the policy that a KDSingleApplicationGuard can enforce: -*/ - -/*! - \var KDSingleApplicationGuard::NoPolicy - - instanceStarted() is emitted, and the new instance allowed to continue. -*/ - -/*! - \var KDSingleApplicationGuard::AutoKillOtherInstances - - instanceStarted() is emitted, and the new instance is killed (Instance::kill()). -*/ - -/*! - Creates a new KDSingleApplicationGuard with arguments - QCoreApplication::arguments() and policy AutoKillOtherInstances, - passing \a parent to the base class constructor, as usual. -*/ -KDSingleApplicationGuard::KDSingleApplicationGuard( QObject * parent ) - : QObject( parent ), d( new Private( AutoKillOtherInstances, this ) ) -{ - d->create( QCoreApplication::arguments() ); -} - -/*! - Creates a new KDSingleApplicationGuard with arguments - QCoreApplication::arguments() and policy \a policy, passing \a - parent to the base class constructor, as usual. -*/ -KDSingleApplicationGuard::KDSingleApplicationGuard( Policy policy, QObject * parent ) - : QObject( parent ), d( new Private( policy, this ) ) -{ - d->create( QCoreApplication::arguments() ); -} - -/*! - Creates a new KDSingleApplicationGuard with arguments \a arguments - and policy AutoKillOtherInstances, passing \a parent to the base - class constructor, as usual. -*/ -KDSingleApplicationGuard::KDSingleApplicationGuard( const QStringList & arguments, QObject * parent ) - : QObject( parent ), d( new Private( AutoKillOtherInstances, this ) ) -{ - d->create( arguments ); -} - -/*! - Creates a new KDSingleApplicationGuard with arguments \a arguments - and policy \a policy, passing \a parent to the base class - constructor, as usual. -*/ -KDSingleApplicationGuard::KDSingleApplicationGuard( const QStringList & arguments, Policy policy, QObject * parent ) - : QObject( parent ), d( new Private( policy, this ) ) -{ - d->create( arguments ); -} - -KDSingleApplicationGuard::Private::Private( Policy policy_, KDSingleApplicationGuard * qq ) - : q( qq ), - id( -1 ), - policy( policy_ ), - operational( false ), - exitRequested( false ) -{ -} - -void KDSingleApplicationGuard::Private::create( const QStringList & arguments ) -{ - if ( !QCoreApplication::instance() ) { - qWarning( "KDSingleApplicationGuard: you need to construct a Q(Core)Application before you can construct a KDSingleApplicationGuard" ); - return; - } - - const QString name = QCoreApplication::applicationName(); - if ( name.isEmpty() ) { - qWarning( "KDSingleApplicationGuard: QCoreApplication::applicationName must not be empty" ); - return; - } - - (void)registerInstanceType(); - if ( primaryInstance == 0 ) - primaryInstance = q; - - mem.setKey( name ); - - // if another instance crashed, the shared memory segment is still there on Unix - // the following lines trigger deletion in that case -#ifndef Q_WS_WIN - mem.attach(); - mem.detach(); -#endif - - const bool created = mem.create( sizeof( InstanceRegister ) ); - if( !created ) - { - QString errorMsg; - if( mem.error() != QSharedMemory::NoError && mem.error() != QSharedMemory::AlreadyExists ) - errorMsg += QString::fromLatin1( "QSharedMemomry::create() failed: %1" ).arg( mem.errorString() ); - - if( !mem.attach() ) - { - if( mem.error() != QSharedMemory::NoError ) - errorMsg += QString::fromLatin1( "QSharedMemomry::attach() failed: %1" ).arg( mem.errorString() ); - - qWarning( "KDSingleApplicationGuard: Could neither create nor attach to shared memory segment." ); - qWarning( "%s\n", errorMsg.toLocal8Bit().constData() ); - return; - } - - const int maxWaitMSecs = 1000 * 60; // stop waiting after 60 seconds - QElapsedTimer waitTimer; - waitTimer.start(); - - // lets wait till the other instance initialized the register - bool initialized = false; - while( !initialized && waitTimer.elapsed() < maxWaitMSecs ) - { - const KDLockedSharedMemoryPointer< InstanceRegister > instances( &mem ); - initialized = instances->isValid(); -#ifdef Q_WS_WIN - ::Sleep(20); -#else - usleep(20000); -#endif - } - - const KDLockedSharedMemoryPointer< InstanceRegister > instances( &mem ); - if ( instances->version != 0 ) { - qWarning( "KDSingleApplicationGuard: Detected version mismatch. " - "Highest supported version: %ud, actual version: %ud", - KDSINGLEAPPLICATIONGUARD_SHM_VERSION, instances->version ); - return; - } - - } - - - KDLockedSharedMemoryPointer< InstanceRegister > instances( &mem ); - - if( !created ) - { - assert( instances->isValid() ); - - // we're _not_ the first instance - // but the - bool killOurSelf = false; - - // find a new slot... - id = std::find( instances->info, instances->info + instances->maxInstances, ProcessInfo() ) - instances->info; - ProcessInfo& info = instances->info[ id ]; - info = ProcessInfo( NewInstance, arguments, QCoreApplication::applicationPid() ); - killOurSelf = instances->policy == AutoKillOtherInstances; - policy = static_cast( instances->policy ); - - // but the signal that we tried to start was sent to the primary application - if( killOurSelf ) - exitRequested = true; - } - else - { - // ok.... we are the first instance - new ( instances.get() ) InstanceRegister( policy ); // create a new list (in shared memory) - id = 0; // our id = 0 - // and we've no command - instances->info[ 0 ] = ProcessInfo( NoCommand, arguments, QCoreApplication::applicationPid() ); - } - -#ifndef Q_WS_WIN - ::signal( SIGINT, SIGINT_handler ); -#endif - - // now listen for commands - timer.start( 750, q ); - - operational = true; -} - -/*! - Destroys this SingleApplicationGuard. - If this instance has been the primary instance and no other instance is existing anymore, - the application is shut down completely. Otherwise the destructor selects another instance to - be the primary instances. - */ -KDSingleApplicationGuard::~KDSingleApplicationGuard() -{ - if( d->id == -1 ) - return; - - d->shutdownInstance(); -} - -/*! - \property KDSingleApplicationGuard::operational - - Contains whether this KDSingleApplicationGuard is operational. - - A non-operational KDSingleApplicationGuard cannot be used in any meaningful way. - - Reasons for a KDSingleApplicationGuard being non-operational include: - \li it was constructed before QApplication (or at least QCoreApplication) was constructed - \li it failed to create or attach to the shared memory segment that is used for communication - - Get this property's value using %isOperational(). -*/ -bool KDSingleApplicationGuard::isOperational() const -{ - return d->operational; -} - -/*! - \property KDSingleApplicationGuard::exitRequested - - Contains wheter this istance has been requested to exit. This will happen when this instance - was just started, but the policy is AutoKillOtherInstances or by explicitely calling kill on - this instance(). - - Get this property's value using %isExitRequested(). -*/ -bool KDSingleApplicationGuard::isExitRequested() const -{ - return d->exitRequested; -}; - -/*! - \property KDSingleApplicationGuard::primaryInstance - - Contains whether this instance is the primary instance. - - The primary instance is the first instance which was started or else the instance which - got selected by KDSingleApplicationGuard's destructor, when the primary instance was - shut down. - - Get this property's value using %isPrimaryInstance(), and monitor changes to it - using becamePrimaryInstance(). - */ -bool KDSingleApplicationGuard::isPrimaryInstance() const -{ - return d->id == 0; -} - -/*! - \property KDSingleApplicationGuard::policy - Specifies the policy KDSingleApplicationGuard is using when new instances are started. - This can only be set in the primary instance. - - Get this property's value using %policy(), set it using %setPolicy(), and monitor changes - to it using policyChanged(). - */ -KDSingleApplicationGuard::Policy KDSingleApplicationGuard::policy() const -{ - return d->policy; -} - -void KDSingleApplicationGuard::setPolicy( Policy policy ) -{ - if ( !d->checkOperationalPrimary( "setPolicy", "change the policy" ) ) - return; - - if( d->policy == policy ) - return; - - d->policy = policy; - emit policyChanged( policy ); - KDLockedSharedMemoryPointer< InstanceRegister > instances( &d->mem ); - instances->policy = policy; -} - -/*! - Returns a list of all currently running instances. - */ -QVector -KDSingleApplicationGuard::instances() const -{ - if ( !d->checkOperational( "instances", "report on other instances" ) ) - return QVector(); - - if ( Private::primaryInstance == 0 ) { - Private::primaryInstance = const_cast( this ); - } - - QVector result; - const KDLockedSharedMemoryPointer< InstanceRegister > instances( const_cast< QSharedMemory* >( &d->mem ) ); - for ( int i = 0, end = instances->maxInstances ; i < end ; ++i ) - { - const ProcessInfo& info = instances->info[ i ]; - if( ( info.command & ( FreeInstance | ExitedInstance ) ) == 0 ) - { - bool truncated; - const QStringList arguments = info.arguments( &truncated ); - result.push_back( Instance( arguments, truncated, info.pid ) ); - } - } - return result; -} - -/*! - Shuts down all other instances. This can only be called from the - the primary instance. - Shut down is done gracefully via QCoreApplication::quit(). - */ -void KDSingleApplicationGuard::shutdownOtherInstances() -{ - if ( !d->checkOperationalPrimary( "shutdownOtherInstances", "shut other instances down" ) ) - return; - - KDLockedSharedMemoryPointer< InstanceRegister > instances( &d->mem ); - for ( int i = 1, end = instances->maxInstances ; i < end ; ++i ) - { - if( ( instances->info[ i ].command & ( FreeInstance | ExitedInstance ) ) == 0 ) - instances->info[ i ].command = ShutDownCommand; - } -} - -/*! - Kills all other instances. This can only be called from the - the primary instance. - Killing is done via emitting exitRequested. It's up to the receiving - instance to react properly. - */ -void KDSingleApplicationGuard::killOtherInstances() -{ - if ( !d->checkOperationalPrimary( "killOtherInstances", "kill other instances" ) ) - return; - - KDLockedSharedMemoryPointer< InstanceRegister > instances( &d->mem ); - for ( int i = 1, end = instances->maxInstances ; i < end ; ++i ) - { - if( ( instances->info[ i ].command & ( FreeInstance | ExitedInstance ) ) == 0 ) - instances->info[ i ].command = KillCommand; - } -} - -bool KDSingleApplicationGuard::event( QEvent * event ) -{ - if ( event->type() == QEvent::Timer ) { - const QTimerEvent * const te = static_cast( event ); - if ( te->timerId() == d->timer.timerId() ) { - d->poll(); - return true; - } - } - return QObject::event( event ); -} - -void KDSingleApplicationGuard::Private::poll() { - - const quint32 now = QDateTime::currentDateTime().toTime_t(); - - if ( primaryInstance == 0 ) { - primaryInstance = q; - } - - if ( q->isPrimaryInstance() ) - { - // only the primary instance will get notified about new instances - QVector< Instance > exitedInstances; - QVector< Instance > startedInstances; - - { - KDLockedSharedMemoryPointer< InstanceRegister > instances( &mem ); - - if( instances->info[ id ].pid != QCoreApplication::applicationPid() ) - { - for ( int i = 1, end = instances->maxInstances ; i < end && id == 0 ; ++i ) - { - if( instances->info[ i ].pid == QCoreApplication::applicationPid() ) - id = i; - } - emit q->becameSecondaryInstance(); - return; - } - - instances->info[ id ].timestamp = now; - - for ( int i = 1, end = instances->maxInstances ; i < end ; ++i ) - { - ProcessInfo& info = instances->info[ i ]; - if( info.command & NewInstance ) - { - bool truncated; - const QStringList arguments = info.arguments( &truncated ); - startedInstances.push_back( Instance( arguments, truncated, info.pid ) ); - info.command &= ~NewInstance; // clear NewInstance flag - } - if( info.command & ExitedInstance ) - { - bool truncated; - const QStringList arguments = info.arguments( &truncated ); - exitedInstances.push_back( Instance( arguments, truncated, info.pid ) ); - info.command = FreeInstance; // set FreeInstance flag - } - } - } - - // one signal for every new instance - _after_ the memory segment was unlocked again - for( QVector< Instance >::const_iterator it = startedInstances.constBegin(); it != startedInstances.constEnd(); ++it ) - emit q->instanceStarted( *it ); - for( QVector< Instance >::const_iterator it = exitedInstances.constBegin(); it != exitedInstances.constEnd(); ++it ) - emit q->instanceExited( *it ); - } - else - { - // do we have a command? - bool killOurSelf = false; - bool shutDownOurSelf = false; - bool policyDidChange = false; - - { - KDLockedSharedMemoryPointer< InstanceRegister > instances( &mem ); - - const Policy oldPolicy = policy; - policy = static_cast( instances->policy ); - policyDidChange = policy != oldPolicy; - - // check for the primary instance health status - if( now - instances->info[ 0 ].timestamp > KDSINGLEAPPLICATIONGUARD_TIMEOUT_SECONDS ) - { - std::swap( instances->info[ 0 ], instances->info[ id ] ); - id = 0; - instances->info[ id ].timestamp = now; - emit q->becamePrimaryInstance(); - instances->info[ id ].command &= ~BecomePrimaryCommand; // afterwards, reset the flag - } - - if( instances->info[ id ].command & BecomePrimaryCommand ) - { - // we became primary! - instances->info[ 0 ] = instances->info[ id ]; - instances->info[ id ] = ProcessInfo(); // change our id to 0 and declare the old slot as free - id = 0; - instances->info[ id ].timestamp = now; - emit q->becamePrimaryInstance(); - } - - if( instances->info[ id ].command & RaiseCommand ) - { - // raise ourself! - emit q->raiseRequested(); - instances->info[ id ].command &= ~RaiseCommand; // afterwards, reset the flag - } - - - killOurSelf = instances->info[ id ].command & KillCommand; // check for kill command - shutDownOurSelf = instances->info[ id ].command & ShutDownCommand; // check for shut down command - instances->info[ id ].command &= ~( KillCommand | ShutDownCommand | BecomePrimaryCommand ); // reset both flags - if( killOurSelf ) - { - instances->info[ id ].command |= ExitedInstance; // upon kill, we have to set the ExitedInstance flag - id = -1; // becauso our d'tor won't be called anymore - } - } - - if( killOurSelf ) // kill our self takes precedence - { - exitRequested = true; - emit q->exitRequested(); - } - else if( shutDownOurSelf ) - qApp->quit(); - else if( policyDidChange ) - emit q->policyChanged( policy ); - } -} - -// #include "moc_kdsingleapplicationguard.cpp" - -#ifdef KDTOOLSCORE_UNITTESTS - -#include - -#include "kdautopointer.h" - -#include - -#include -#include -#include - -static void wait( int msec, QSignalSpy * spy=0, int expectedCount=INT_MAX ) -{ - QTime t; - t.start(); - while ( ( !spy || spy->count() < expectedCount ) && t.elapsed() < msec ) - { - qApp->processEvents( QEventLoop::WaitForMoreEvents, qMax( 10, msec - t.elapsed() ) ); - } -} - -static std::ostream& operator<<( std::ostream& stream, const QStringList& list ) -{ - stream << "QStringList("; - for( QStringList::const_iterator it = list.begin(); it != list.end(); ++it ) - { - stream << " " << it->toLocal8Bit().data(); - if( it + 1 != list.end() ) - stream << ","; - } - stream << " )"; - return stream; -} - -namespace { - class ApplicationNameSaver { - Q_DISABLE_COPY( ApplicationNameSaver ) - const QString oldname; - public: - explicit ApplicationNameSaver( const QString & name ) - : oldname( QCoreApplication::applicationName() ) - { - QCoreApplication::setApplicationName( name ); - } - ~ApplicationNameSaver() { - QCoreApplication::setApplicationName( oldname ); - } - }; -} - -KDAB_UNITTEST_SIMPLE( KDSingleApplicationGuard, "kdcoretools" ) { - - // set it to an unique name - const ApplicationNameSaver saver( QUuid::createUuid().toString() ); - - KDAutoPointer guard3; - KDAutoPointer spy3; - KDAutoPointer spy4; - - { - KDSingleApplicationGuard guard1; - assertEqual( guard1.policy(), KDSingleApplicationGuard::AutoKillOtherInstances ); - assertEqual( guard1.instances().count(), 1 ); - assertTrue( guard1.isPrimaryInstance() ); - - guard1.setPolicy( KDSingleApplicationGuard::NoPolicy ); - assertEqual( guard1.policy(), KDSingleApplicationGuard::NoPolicy ); - - QSignalSpy spy1( &guard1, SIGNAL(instanceStarted(KDSingleApplicationGuard::Instance)) ); - - KDSingleApplicationGuard guard2; - assertEqual( guard1.instances().count(), 2 ); - assertEqual( guard2.instances().count(), 2 ); - assertEqual( guard2.policy(), KDSingleApplicationGuard::NoPolicy ); - assertFalse( guard2.isPrimaryInstance() ); - - wait( 1000, &spy1, 1 ); - - assertEqual( spy1.count(), 1 ); - guard3.reset( new KDSingleApplicationGuard ); - spy3.reset( new QSignalSpy( guard3.get(), SIGNAL(becamePrimaryInstance()) ) ); - spy4.reset( new QSignalSpy( guard3.get(), SIGNAL(instanceExited(KDSingleApplicationGuard::Instance) ) ) ); - assertFalse( guard3->isPrimaryInstance() ); - } - - wait( 1000, spy3.get(), 1 ); - wait( 1000, spy4.get(), 1 ); - assertEqual( spy3->count(), 1 ); - assertEqual( guard3->instances().count(), 1 ); - assertTrue( guard3->isPrimaryInstance() ); - guard3.reset( new KDSingleApplicationGuard ); - - assertEqual( guard3->instances().first().arguments(), qApp->arguments() ); - - QSignalSpy spyStarted( guard3.get(), SIGNAL(instanceStarted(KDSingleApplicationGuard::Instance)) ); - QSignalSpy spyExited( guard3.get(), SIGNAL(instanceExited(KDSingleApplicationGuard::Instance)) ); - - { - KDSingleApplicationGuard guard1; - KDSingleApplicationGuard guard2; - - wait( 1000, &spyStarted, 2 ); - - assertEqual( spyStarted.count(), 2 ); - } - - wait( 1000, &spyExited, 2 ); - assertEqual( spyExited.count(), 2 ); - - spyStarted.clear(); - spyExited.clear(); - - { - // check arguments-too-long handling: - QStringList args; - for ( unsigned int i = 0, end = KDSINGLEAPPLICATIONGUARD_MAX_COMMAND_LINE/16 ; i != end ; ++i ) - args.push_back( QLatin1String( "0123456789ABCDEF" ) ); - KDSingleApplicationGuard guard3( args ); - - wait( 1000, &spyStarted, 1 ); - - const QVector instances = guard3.instances(); - assertEqual( instances.size(), 2 ); - - assertTrue( instances[1].areArgumentsTruncated() ); - } -} - -#endif // KDTOOLSCORE_UNITTESTS - -#endif // QT_NO_SHAREDMEMORY -#endif // QT_VERSION >= 0x040400 || defined(DOXYGEN_RUN) diff --git a/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.h b/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.h deleted file mode 100644 index f75825cef..000000000 --- a/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB. - * SPDX-License-Identifier: LGPL-2.0-only - * - * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. - */ -#ifndef KDTOOLSCORE_KDSINGLEAPPLICATIONGUARD_H -#define KDTOOLSCORE_KDSINGLEAPPLICATIONGUARD_H - -#include - -#ifndef QT_NO_SHAREDMEMORY - -#include -#include - -#include "pimpl_ptr.h" -#include "DllMacro.h" - -#include - -template class QVector; -class QCoreApplication; - -class DLLEXPORT KDSingleApplicationGuard : public QObject -{ - Q_OBJECT - Q_ENUMS( Policy ) - Q_PROPERTY( bool operational READ isOperational ) - Q_PROPERTY( bool exitRequested READ isExitRequested ) - Q_PROPERTY( bool primaryInstance READ isPrimaryInstance NOTIFY becamePrimaryInstance ) - Q_PROPERTY( Policy policy READ policy WRITE setPolicy NOTIFY policyChanged ) -public: - enum Policy - { - NoPolicy = 0, - AutoKillOtherInstances = 1 - }; - - explicit KDSingleApplicationGuard( QObject * parent=nullptr ); - explicit KDSingleApplicationGuard( Policy policy, QObject * parent=nullptr ); - explicit KDSingleApplicationGuard( const QStringList & arguments, QObject * parent=nullptr ); - explicit KDSingleApplicationGuard( const QStringList & arguments, Policy policy, QObject * parent=nullptr ); - ~KDSingleApplicationGuard() override; - - bool isOperational() const; - - bool isExitRequested() const; - - bool isPrimaryInstance() const; - - Policy policy() const; - void setPolicy( Policy policy ); - - class Instance; - - QVector instances() const; - -Q_SIGNALS: - void instanceStarted( const KDSingleApplicationGuard::Instance & instance ); - void instanceExited( const KDSingleApplicationGuard::Instance & instance ); - void exitRequested(); - void raiseRequested(); - void becamePrimaryInstance(); - void becameSecondaryInstance(); - void policyChanged( KDSingleApplicationGuard::Policy policy ); - -public Q_SLOTS: - void shutdownOtherInstances(); - void killOtherInstances(); - -protected: - /*! \reimp */ bool event( QEvent * event ) override; - -private: -#ifndef Q_WS_WIN - static void SIGINT_handler( int ); -#endif - -private: - friend struct ProcessInfo; - - class Private; - kdtools::pimpl_ptr< Private > d; -}; - -class DLLEXPORT KDSingleApplicationGuard::Instance { - friend class ::KDSingleApplicationGuard; - friend class ::KDSingleApplicationGuard::Private; - Instance( const QStringList &, bool, qint64 ); -public: - Instance(); - Instance( const Instance & other ); - ~Instance(); - - void swap( Instance & other ) { - std::swap( d, other.d ); - } - - Instance & operator=( Instance other ) { - swap( other ); - return *this; - } - - bool isNull() const { return !d; } - bool isValid() const; - - bool areArgumentsTruncated() const; - - const QStringList & arguments() const; - qint64 pid() const; - - void shutdown(); - void kill(); - void raise(); - -private: - class Private; - Private * d; -}; - -namespace std { - template <> - inline void swap( KDSingleApplicationGuard::Instance & lhs, - KDSingleApplicationGuard::Instance & rhs ) - { - lhs.swap( rhs ); - } -} // namespace std - -QT_BEGIN_NAMESPACE - -template <> -inline void qSwap( KDSingleApplicationGuard::Instance & lhs, - KDSingleApplicationGuard::Instance & rhs ) -{ - lhs.swap( rhs ); -} -Q_DECLARE_METATYPE( KDSingleApplicationGuard::Instance ) -Q_DECLARE_TYPEINFO( KDSingleApplicationGuard::Instance, Q_MOVABLE_TYPE ); - -QT_END_NAMESPACE - - -#endif // QT_NO_SHAREDMEMORY - -#endif /* KDTOOLSCORE_KDSINGLEAPPLICATIONGUARD_H */ diff --git a/3rdparty/kdsingleapplicationguard/kdtoolsglobal.cpp b/3rdparty/kdsingleapplicationguard/kdtoolsglobal.cpp deleted file mode 100644 index f886189c3..000000000 --- a/3rdparty/kdsingleapplicationguard/kdtoolsglobal.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB. - * SPDX-License-Identifier: LGPL-2.0-only - * - * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. - */ -#include "kdtoolsglobal.h" - -#include - -#include - -namespace { - struct Version { - unsigned char v[3]; - }; - - static inline bool operator<( const Version & lhs, const Version & rhs ) { - return std::lexicographical_compare( lhs.v, lhs.v + 3, rhs.v, rhs.v + 3 ); - } - static inline bool operator==( const Version & lhs, const Version & rhs ) { - return std::equal( lhs.v, lhs.v + 3, rhs.v ); - } - KDTOOLS_MAKE_RELATION_OPERATORS( Version, static inline ) -} - -static Version kdParseQtVersion( const char * const version ) { - if ( !version || qstrlen( version ) < 5 || version[1] != '.' || version[3] != '.' || ( version[5] != 0 && version[5] != '.' && version[5] != '-' ) ) - return Version(); // parse error - const Version result = { { static_cast< unsigned char >( version[0] - '0' ), - static_cast< unsigned char >( version[2] - '0' ), - static_cast< unsigned char >( version[4] - '0' ) } }; - return result; -} - -bool _kdCheckQtVersion_impl( unsigned int major, unsigned int minor, unsigned int patchlevel ) { - static const Version actual = kdParseQtVersion( qVersion() ); // do this only once each run... - const Version requested = { { static_cast< unsigned char >( major ), - static_cast< unsigned char >( minor ), - static_cast< unsigned char >( patchlevel ) } }; - return actual >= requested; -} diff --git a/3rdparty/kdsingleapplicationguard/kdtoolsglobal.h b/3rdparty/kdsingleapplicationguard/kdtoolsglobal.h deleted file mode 100644 index 5086ddd71..000000000 --- a/3rdparty/kdsingleapplicationguard/kdtoolsglobal.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB. - * SPDX-License-Identifier: LGPL-2.0-only - * - * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. - */ -#ifndef KDTOOLS_KDTOOLSGLOBAL_H -#define KDTOOLS_KDTOOLSGLOBAL_H - -#include - -#define KDAB_DISABLE_COPY( x ) private: x( const x & ); x & operator=( const x & ) - -#ifdef KDTOOLS_SHARED -# ifdef BUILD_SHARED_KDTOOLSCORE -# define KDTOOLSCORE_EXPORT Q_DECL_EXPORT -# else -# define KDTOOLSCORE_EXPORT Q_DECL_IMPORT -# endif -# ifdef BUILD_SHARED_KDTOOLSGUI -# define KDTOOLSGUI_EXPORT Q_DECL_EXPORT -# else -# define KDTOOLSGUI_EXPORT Q_DECL_IMPORT -# endif -# ifdef BUILD_SHARED_KDTOOLSXML -# define KDTOOLSXML_EXPORT Q_DECL_EXPORT -# else -# define KDTOOLSXML_EXPORT Q_DECL_IMPORT -# endif -# ifdef BUILD_SHARED_KDUPDATER -# define KDTOOLS_UPDATER_EXPORT Q_DECL_EXPORT -# else -# define KDTOOLS_UPDATER_EXPORT Q_DECL_IMPORT -# endif -#else // KDTOOLS_SHARED -# define KDTOOLSCORE_EXPORT -# define KDTOOLSGUI_EXPORT -# define KDTOOLSXML_EXPORT -# define KDTOOLS_UPDATER_EXPORT -#endif // KDTOOLS_SHARED - -#define MAKEINCLUDES_EXPORT - -#define DOXYGEN_PROPERTY( x ) -#ifdef DOXYGEN_RUN -# define KDAB_IMPLEMENT_SAFE_BOOL_OPERATOR( func ) operator unspecified_bool_type() const { return func; } -# define KDAB_USING_SAFE_BOOL_OPERATOR( Class ) operator unspecified_bool_type() const; -#else -# define KDAB_IMPLEMENT_SAFE_BOOL_OPERATOR( func ) \ - private: \ - struct __safe_bool_dummy__ { void nonnull() {} }; \ - public: \ - typedef void ( __safe_bool_dummy__::*unspecified_bool_type )(); \ - operator unspecified_bool_type() const { \ - return ( func ) ? &__safe_bool_dummy__::nonnull : 0 ; \ - } -#define KDAB_USING_SAFE_BOOL_OPERATOR( Class ) \ - using Class::operator Class::unspecified_bool_type; -#endif - -#define KDTOOLS_MAKE_RELATION_OPERATORS( Class, linkage ) \ - linkage bool operator>( const Class & lhs, const Class & rhs ) { \ - return operator<( rhs, lhs ); \ - } \ - linkage bool operator!=( const Class & lhs, const Class & rhs ) { \ - return !operator==( lhs, rhs ); \ - } \ - linkage bool operator<=( const Class & lhs, const Class & rhs ) { \ - return !operator>( lhs, rhs ); \ - } \ - linkage bool operator>=( const Class & lhs, const Class & rhs ) { \ - return !operator<( lhs, rhs ); \ - } - -template -inline T & __kdtools__dereference_for_methodcall( T & o ) { - return o; -} - -template -inline T & __kdtools__dereference_for_methodcall( T * o ) { - return *o; -} - -#define KDAB_SET_OBJECT_NAME( x ) __kdtools__dereference_for_methodcall( x ).setObjectName( QLatin1String( #x ) ) - -KDTOOLSCORE_EXPORT bool _kdCheckQtVersion_impl( unsigned int major, unsigned int minor=0, unsigned int patchlevel=0 ); -static inline bool kdCheckQtVersion( unsigned int major, unsigned int minor=0, unsigned int patchlevel=0 ) { - return (major<<16|minor<<8|patchlevel) <= static_cast(QT_VERSION) - || _kdCheckQtVersion_impl( major, minor, patchlevel ); -} - -#define KDTOOLS_DECLARE_PRIVATE_BASE( Class ) \ -protected: \ - class Private; \ - Private * d_func() { return _d; } \ - const Private * d_func() const { return _d; } \ - Class( Private * _d_, bool b ) : _d( _d_ ) { init(b); } \ -private: \ - void init(bool); \ -private: \ - Private * _d - -#define KDTOOLS_DECLARE_PRIVATE_DERIVED( Class, Base ) \ -protected: \ - class Private; \ - Private * d_func() { \ - return reinterpret_cast( Base::d_func() ); \ - } \ - const Private * d_func() const { \ - return reinterpret_cast( Base::d_func() ); \ - } \ - Class( Private * _d_, bool b ) \ - : Base( reinterpret_cast(_d_), b ) { init(b); } \ -private: \ - void init(bool) - - -#endif /* KDTOOLS_KDTOOLSGLOBAL_H */ - diff --git a/3rdparty/kdsingleapplicationguard/pimpl_ptr.cpp b/3rdparty/kdsingleapplicationguard/pimpl_ptr.cpp deleted file mode 100644 index f2b0a4dd9..000000000 --- a/3rdparty/kdsingleapplicationguard/pimpl_ptr.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB. - * SPDX-License-Identifier: LGPL-2.0-only - * - * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. - */ -#include "pimpl_ptr.h" - -/*! - \class pimpl_ptr: - \ingroup core smartptr - \brief Owning pointer for private implementations - \since_c 2.1 - - (The exception safety of this class has not been evaluated yet.) - - pimpl_ptr is a smart immutable pointer, which owns the contained object. Unlike other smart pointers, - it creates a standard constructed object when instanciated via the - \link pimpl_ptr() standard constructor\endlink. - Additionally, pimpl_ptr respects constness of the pointer object and returns \c const \c T* for - a const pimpl_ptr object. - - The content of a pimpl_ptr cannot be changed during it's lifetime. - - \section general-use General Use - - The general use case of pimpl_ptr is the "Pimpl Idiom", i.e. hiding the private implementation of a class - from the user's compiler which see \c MyClass as - - \code - class MyClass - { - public: - MyClass(); - ~MyClass(); - - // public class API - int value() const; - - private: - class Private; // defined later - kdtools::pimpl_ptr< Private > d; - }; - \endcode - - but not the private parts of it. These can only be seen (and accessed) by the code knowing \c MyClass::Private: - - \code - class MyClass::Private - { - public: - int value; - }; - - MyClass::MyClass() - { - // d was automatically filled with new Private - d->value = 42; - } - - MyClass::~MyClass() - { - // the content of d gets deleted automatically - } - - int MyClass::value() const - { - // access the private part: - // since MyClass::value() is const, the returned pointee is const, too - return d->value; - } - \endcode - -*/ - -/*! - \fn pimpl_ptr::pimpl_ptr() - - Default constructor. Constructs a pimpl_tr that contains (owns) a standard constructed - instance of \c T. - - \post \c *this owns a new object. -*/ - -/*! - \fn pimpl_ptr::pimpl_ptr( T * t ) - - Constructor. Constructs a pimpl_ptr that contains (owns) \a t. - - \post get() == obj -*/ - -/*! - \fn pimpl_ptr::~pimpl_ptr() - - Destructor. - - \post The object previously owned by \c *this has been deleted. -*/ - -/*! - \fn const T * pimpl_ptr::get() const - - \returns a const pointer to the contained (owned) object. - \overload -*/ - -/*! - \fn T * pimpl_ptr::get() - - \returns a pointer to the contained (owned) object. -*/ - -/*! - \fn const T & pimpl_ptr::operator*() const - - Dereference operator. Returns \link get() *get()\endlink. - \overload -*/ - -/*! - \fn T & pimpl_ptr::operator*() - - Dereference operator. Returns \link get() *get()\endlink. -*/ - -/*! - \fn const T * pimpl_ptr::operator->() const - - Member-by-pointer operator. Returns get(). - \overload -*/ - -/*! - \fn T * pimpl_ptr::operator->() - - Member-by-pointer operator. Returns get(). -*/ - -#ifdef KDTOOLSCORE_UNITTESTS - -#include - -#include -#include - -namespace -{ - struct ConstTester - { - bool isConst() - { - return false; - } - - bool isConst() const - { - return true; - } - }; -} - -KDAB_UNITTEST_SIMPLE( pimpl_ptr, "kdcoretools" ) { - - { - kdtools::pimpl_ptr< QObject > p; - assertNotNull( p.get() ); - assertNull( p->parent() ); - } - - - { - QPointer< QObject > o; - { - kdtools::pimpl_ptr< QObject > qobject( new QObject ); - o = qobject.get(); - assertEqual( o, qobject.operator->() ); - assertEqual( o, &(qobject.operator*()) ); - } - assertNull( o ); - } - - { - const kdtools::pimpl_ptr< QObject > qobject( new QObject ); - const QObject* o = qobject.get(); - assertEqual( o, qobject.operator->() ); - assertEqual( o, &(qobject.operator*()) ); - } - - { - kdtools::pimpl_ptr< QObject > o1; - assertTrue( o1 ); - kdtools::pimpl_ptr< QObject > o2( 0 ); - assertFalse( o2 ); - } - - { - const kdtools::pimpl_ptr< ConstTester > o1; - kdtools::pimpl_ptr< ConstTester > o2; - assertTrue( o1->isConst() ); - assertFalse( o2->isConst() ); - assertTrue( (*o1).isConst() ); - assertFalse( (*o2).isConst() ); - assertTrue( o1.get()->isConst() ); - assertFalse( o2.get()->isConst() ); - } -} - -#endif // KDTOOLSCORE_UNITTESTS diff --git a/3rdparty/kdsingleapplicationguard/pimpl_ptr.h b/3rdparty/kdsingleapplicationguard/pimpl_ptr.h deleted file mode 100644 index b8b4786ba..000000000 --- a/3rdparty/kdsingleapplicationguard/pimpl_ptr.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2001-2010 Klaralvdalens Datakonsult AB. - * SPDX-License-Identifier: LGPL-2.0-only - * - * The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. - */ -#ifndef KDTOOLSCORE_PIMPL_PTR_H -#define KDTOOLSCORE_PIMPL_PTR_H - -#include "kdtoolsglobal.h" - -#ifndef DOXYGEN_RUN -namespace kdtools { -#endif - - template - class pimpl_ptr { - KDAB_DISABLE_COPY( pimpl_ptr ); - T * d; - public: - pimpl_ptr() : d( new T ) {} - explicit pimpl_ptr( T * t ) : d( t ) {} - ~pimpl_ptr() { delete d; d = nullptr; } - - T * get() { return d; } - const T * get() const { return d; } - - T * operator->() { return get(); } - const T * operator->() const { return get(); } - - T & operator*() { return *get(); } - const T & operator*() const { return *get(); } - - KDAB_IMPLEMENT_SAFE_BOOL_OPERATOR( get() ) - }; - - // these are not implemented, so's we can catch their use at - // link-time. Leaving them undeclared would open up a comparison - // via operator unspecified-bool-type(). - template - void operator==( const pimpl_ptr &, const pimpl_ptr & ); - template - void operator!=( const pimpl_ptr &, const pimpl_ptr & ); - -#ifndef DOXYGEN_RUN -} // namespace kdtools -#endif - -#endif /* KDTOOLSCORE_PIMPL_PTR_H */ - diff --git a/3rdparty/waitingspinnerwidget.cpp b/3rdparty/waitingspinnerwidget.cpp deleted file mode 100644 index 98931a6ad..000000000 --- a/3rdparty/waitingspinnerwidget.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2012-2014 Alexander Turkin - * SPDX-FileCopyrightText: 2014 William Hallatt - * SPDX-FileCopyrightText: 2015 Jacob Dawid - * SPDX-License-Identifier: MIT - */ - -/* Original Work Copyright (c) 2012-2014 Alexander Turkin - Modified 2014 by William Hallatt - Modified 2015 by Jacob Dawid - -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. -*/ - -// Own includes -#include "waitingspinnerwidget.h" - -// Standard includes -#include -#include - -// Qt includes -#include -#include - -WaitingSpinnerWidget::WaitingSpinnerWidget(QWidget *parent, - bool centerOnParent, - bool disableParentWhenSpinning) - : QWidget(parent), - _centerOnParent(centerOnParent), - _disableParentWhenSpinning(disableParentWhenSpinning) { - initialize(); -} - -WaitingSpinnerWidget::WaitingSpinnerWidget(Qt::WindowModality modality, - QWidget *parent, - bool centerOnParent, - bool disableParentWhenSpinning) - : QWidget(parent, Qt::Dialog | Qt::FramelessWindowHint), - _centerOnParent(centerOnParent), - _disableParentWhenSpinning(disableParentWhenSpinning){ - initialize(); - - // We need to set the window modality AFTER we've hidden the - // widget for the first time since changing this property while - // the widget is visible has no effect. - setWindowModality(modality); - setAttribute(Qt::WA_TranslucentBackground); -} - -void WaitingSpinnerWidget::initialize() { - _color = Qt::black; - _roundness = 100.0; - _minimumTrailOpacity = 3.14159265358979323846; - _trailFadePercentage = 80.0; - _revolutionsPerSecond = 1.57079632679489661923; - _numberOfLines = 20; - _lineLength = 10; - _lineWidth = 2; - _innerRadius = 10; - _currentCounter = 0; - _isSpinning = false; - - _timer = new QTimer(this); - connect(_timer, SIGNAL(timeout()), this, SLOT(rotate())); - updateSize(); - updateTimer(); - hide(); -} - -void WaitingSpinnerWidget::paintEvent(QPaintEvent *) { - updatePosition(); - QPainter painter(this); - painter.fillRect(this->rect(), Qt::transparent); - painter.setRenderHint(QPainter::Antialiasing, true); - - if (_currentCounter >= _numberOfLines) { - _currentCounter = 0; - } - - painter.setPen(Qt::NoPen); - for (int i = 0; i < _numberOfLines; ++i) { - painter.save(); - painter.translate(_innerRadius + _lineLength, - _innerRadius + _lineLength); - qreal rotateAngle = - static_cast(360 * i) / static_cast(_numberOfLines); - painter.rotate(rotateAngle); - painter.translate(_innerRadius, 0); - int distance = - lineCountDistanceFromPrimary(i, _currentCounter, _numberOfLines); - QColor color = - currentLineColor(distance, _numberOfLines, _trailFadePercentage, - _minimumTrailOpacity, _color); - painter.setBrush(color); - // TODO improve the way rounded rect is painted - painter.drawRoundedRect( - QRect(0, -_lineWidth / 2, _lineLength, _lineWidth), _roundness, - _roundness, Qt::RelativeSize); - painter.restore(); - } -} - -void WaitingSpinnerWidget::start() { - updatePosition(); - _isSpinning = true; - show(); - - if(parentWidget() && _disableParentWhenSpinning) { - parentWidget()->setEnabled(false); - } - - if (!_timer->isActive()) { - _timer->start(); - _currentCounter = 0; - } -} - -void WaitingSpinnerWidget::stop() { - _isSpinning = false; - hide(); - - if(parentWidget() && _disableParentWhenSpinning) { - parentWidget()->setEnabled(true); - } - - if (_timer->isActive()) { - _timer->stop(); - _currentCounter = 0; - } -} - -void WaitingSpinnerWidget::setNumberOfLines(int lines) { - _numberOfLines = lines; - _currentCounter = 0; - updateTimer(); -} - -void WaitingSpinnerWidget::setLineLength(int length) { - _lineLength = length; - updateSize(); -} - -void WaitingSpinnerWidget::setLineWidth(int width) { - _lineWidth = width; - updateSize(); -} - -void WaitingSpinnerWidget::setInnerRadius(int radius) { - _innerRadius = radius; - updateSize(); -} - -QColor WaitingSpinnerWidget::color() { - return _color; -} - -qreal WaitingSpinnerWidget::roundness() { - return _roundness; -} - -qreal WaitingSpinnerWidget::minimumTrailOpacity() { - return _minimumTrailOpacity; -} - -qreal WaitingSpinnerWidget::trailFadePercentage() { - return _trailFadePercentage; -} - -qreal WaitingSpinnerWidget::revolutionsPersSecond() { - return _revolutionsPerSecond; -} - -int WaitingSpinnerWidget::numberOfLines() { - return _numberOfLines; -} - -int WaitingSpinnerWidget::lineLength() { - return _lineLength; -} - -int WaitingSpinnerWidget::lineWidth() { - return _lineWidth; -} - -int WaitingSpinnerWidget::innerRadius() { - return _innerRadius; -} - -bool WaitingSpinnerWidget::isSpinning() const { - return _isSpinning; -} - -void WaitingSpinnerWidget::setRoundness(qreal roundness) { - _roundness = std::max(0.0, std::min(100.0, roundness)); -} - -void WaitingSpinnerWidget::setColor(QColor color) { - _color = color; -} - -void WaitingSpinnerWidget::setRevolutionsPerSecond(qreal revolutionsPerSecond) { - _revolutionsPerSecond = revolutionsPerSecond; - updateTimer(); -} - -void WaitingSpinnerWidget::setTrailFadePercentage(qreal trail) { - _trailFadePercentage = trail; -} - -void WaitingSpinnerWidget::setMinimumTrailOpacity(qreal minimumTrailOpacity) { - _minimumTrailOpacity = minimumTrailOpacity; -} - -void WaitingSpinnerWidget::rotate() { - ++_currentCounter; - if (_currentCounter >= _numberOfLines) { - _currentCounter = 0; - } - update(); -} - -void WaitingSpinnerWidget::updateSize() { - int size = (_innerRadius + _lineLength) * 2; - setFixedSize(size, size); -} - -void WaitingSpinnerWidget::updateTimer() { - _timer->setInterval(1000 / (_numberOfLines * _revolutionsPerSecond)); -} - -void WaitingSpinnerWidget::updatePosition() { - if (parentWidget() && _centerOnParent) { - move(parentWidget()->width() / 2 - width() / 2, - parentWidget()->height() / 2 - height() / 2); - } -} - -int WaitingSpinnerWidget::lineCountDistanceFromPrimary(int current, int primary, - int totalNrOfLines) { - int distance = primary - current; - if (distance < 0) { - distance += totalNrOfLines; - } - return distance; -} - -QColor WaitingSpinnerWidget::currentLineColor(int countDistance, int totalNrOfLines, - qreal trailFadePerc, qreal minOpacity, - QColor color) { - if (countDistance == 0) { - return color; - } - const qreal minAlphaF = minOpacity / 100.0; - int distanceThreshold = - static_cast(ceil((totalNrOfLines - 1) * trailFadePerc / 100.0)); - if (countDistance > distanceThreshold) { - color.setAlphaF(minAlphaF); - } else { - qreal alphaDiff = color.alphaF() - minAlphaF; - qreal gradient = alphaDiff / static_cast(distanceThreshold + 1); - qreal resultAlpha = color.alphaF() - gradient * countDistance; - - // If alpha is out of bounds, clip it. - resultAlpha = std::min(1.0, std::max(0.0, resultAlpha)); - color.setAlphaF(resultAlpha); - } - return color; -} diff --git a/3rdparty/waitingspinnerwidget.h b/3rdparty/waitingspinnerwidget.h deleted file mode 100644 index d171e9beb..000000000 --- a/3rdparty/waitingspinnerwidget.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2012-2014 Alexander Turkin - * SPDX-FileCopyrightText: 2014 William Hallatt - * SPDX-FileCopyrightText: 2015 Jacob Dawid - * SPDX-License-Identifier: MIT - */ - -/* Original Work Copyright (c) 2012-2014 Alexander Turkin - Modified 2014 by William Hallatt - Modified 2015 by Jacob Dawid - -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 - -// Qt includes -#include -#include -#include - -class WaitingSpinnerWidget : public QWidget { - Q_OBJECT -public: - /*! Constructor for "standard" widget behaviour - use this - * constructor if you wish to, e.g. embed your widget in another. */ - WaitingSpinnerWidget(QWidget *parent = nullptr, - bool centerOnParent = true, - bool disableParentWhenSpinning = true); - - /*! Constructor - use this constructor to automatically create a modal - * ("blocking") spinner on top of the calling widget/window. If a valid - * parent widget is provided, "centreOnParent" will ensure that - * QtWaitingSpinner automatically centres itself on it, if not, - * "centreOnParent" is ignored. */ - WaitingSpinnerWidget(Qt::WindowModality modality, - QWidget *parent = nullptr, - bool centerOnParent = true, - bool disableParentWhenSpinning = true); - -public slots: - void start(); - void stop(); - -public: - void setColor(QColor color); - void setRoundness(qreal roundness); - void setMinimumTrailOpacity(qreal minimumTrailOpacity); - void setTrailFadePercentage(qreal trail); - void setRevolutionsPerSecond(qreal revolutionsPerSecond); - void setNumberOfLines(int lines); - void setLineLength(int length); - void setLineWidth(int width); - void setInnerRadius(int radius); - void setText(QString text); - - QColor color(); - qreal roundness(); - qreal minimumTrailOpacity(); - qreal trailFadePercentage(); - qreal revolutionsPersSecond(); - int numberOfLines(); - int lineLength(); - int lineWidth(); - int innerRadius(); - - bool isSpinning() const; - -private slots: - void rotate(); - -protected: - void paintEvent(QPaintEvent *paintEvent) override; - -private: - static int lineCountDistanceFromPrimary(int current, int primary, - int totalNrOfLines); - static QColor currentLineColor(int distance, int totalNrOfLines, - qreal trailFadePerc, qreal minOpacity, - QColor color); - - void initialize(); - void updateSize(); - void updateTimer(); - void updatePosition(); - -private: - QColor _color; - qreal _roundness; // 0..100 - qreal _minimumTrailOpacity; - qreal _trailFadePercentage; - qreal _revolutionsPerSecond; - int _numberOfLines; - int _lineLength; - int _lineWidth; - int _innerRadius; - -private: - WaitingSpinnerWidget(const WaitingSpinnerWidget&); - WaitingSpinnerWidget& operator=(const WaitingSpinnerWidget&); - - QTimer *_timer; - bool _centerOnParent; - bool _disableParentWhenSpinning; - int _currentCounter; - bool _isSpinning; -}; diff --git a/CHANGES-3.3 b/CHANGES-3.3 new file mode 100644 index 000000000..9debfc8d8 --- /dev/null +++ b/CHANGES-3.3 @@ -0,0 +1,55 @@ + + +This is the changelog for Calamares. For each release, the major changes and +contributors are listed. Note that Calamares does not have a historical +changelog -- this log starts with version 3.3.0. See CHANGES-3.2 for +the history of the 3.2 series (2018-05 - 2021-12). + +# 3.3.0 (unreleased) # + +This release contains contributions from (alphabetically by first name): + - Anubhav Choudhary + - Evan James + - Vitor Lopes + +This is a "minor" version change, but the size of the changes is very +large. Configuration files from previous versions of Calamares will +**certainly** need to be re-validated. Take heed of the many changes +in the *Modules* heading, below. + +## Project ## + - The C++ code in the project is now formatted with clang-format 12 or 13, + with the coding-style as found in `.clang-format`; there are minor + differences from the tool, compared to the clang-format 9 usually applied + to Calamares 3.2. + - The CMake code in the project is now formatted with gersemi 0.7.5. + +## Core ## + - CMake 3.16, Qt 5.15 are now required; the newer CMake is to support + new features (also for KDE Frameworks), Qt is the current LTS version. + - KDE Framework "DBusAddons" is now required, and is used to "activate" + Calamares; the KDAB Single Application Guard is no longer used. + KDSAG needed patching to chase Qt 5.15 deprecations, and the DBus + activation code is tried and tested in Frameworks (tier 1). + Running `calamares -d` no longer enforces a single-application + (it is for debugging purposes, after all). + - Python 3.6 or later is now required, to allow for F-strings in + Python code and allow other tidy-ups in the Python modules. + Boost::Python now requires 1.67 or later (for CMake support). + - The log file now **always** contains a debug-log, and the `-D` flag + primarily controls what is printed to stdout. By default, stdout + only gets errors; use `-D6` to match stdout with the file. Use `-D8` + to get a verbose log file **and** verbose stdout. + +## Modules ## + - *bootloader* now supports more options when building the kernel + command-line. (Thanks Evan) + - *displaymanager* no longer supports the discontinued *kdm* display manager. + - *grubcfg* changed the key *keepDistributor* to *keep_distributor*. + Please update configurations. + - *partition* requires KPMCore 21.12 (e.g. KPMCore 4.2 API, or later). + - *partition* can now skip installing the bootloader in more scenarios. + #1632 (Thanks Anubhav) + diff --git a/CMakeLists.txt b/CMakeLists.txt index d006faaf0..817e7e0c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,10 +25,13 @@ # CMake once. These affect the ABI offered by Calamares. # - PYTHON (enable Python Job modules) # - QML (enable QML UI View modules) -# - PYTHONQT # TODO:3.3: remove +# The WITH_* options affect the ABI of Calamares: you must +# build (C++) modules for Calamares with the same WITH_* +# settings, or they may not load at all. # BUILD_ : choose additional things to build # - TESTING (standard CMake option) # - SCHEMA_TESTING (requires Python, see ci/configvalidator.py) +# - KF5Crash (uses KCrash, rather than Calamares internal, for crash reporting) # DEBUG_ : special developer flags for debugging # # Example usage: @@ -38,35 +41,39 @@ # One special target is "show-version", which can be built # to obtain the version number from here. -# TODO:3.3: Require CMake 3.12 -cmake_minimum_required( VERSION 3.3 FATAL_ERROR ) -project( CALAMARES - VERSION 3.2.59 - LANGUAGES C CXX -) +cmake_minimum_required(VERSION 3.16 FATAL_ERROR) -set( CALAMARES_VERSION_RC 0 ) # Set to 0 during release cycle, 1 during development -if( CALAMARES_VERSION_RC EQUAL 1 AND CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR ) - message( FATAL_ERROR "Do not build development versions in the source-directory." ) +set(CALAMARES_VERSION 3.3.0) +set(CALAMARES_RELEASE_MODE OFF) # Set to ON during a release + +if(CMAKE_SCRIPT_MODE_FILE) + include(${CMAKE_CURRENT_LIST_DIR}/CMakeModules/ExtendedVersion.cmake) + set(CMAKE_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}) + extend_version( ${CALAMARES_VERSION} OFF _vshort _vlong ) + message("${_vlong}") + return() +endif() + +project(CALAMARES VERSION ${CALAMARES_VERSION} LANGUAGES C CXX HOMEPAGE_URL "https://calamares.io/") + +if(NOT CALAMARES_RELEASE_MODE AND CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) + message(FATAL_ERROR "Do not build development versions in the source-directory.") endif() ### OPTIONS # -option( INSTALL_CONFIG "Install configuration files" OFF ) -option( INSTALL_POLKIT "Install Polkit configuration" ON ) -option( INSTALL_COMPLETION "Install shell completions" OFF ) -# Options for the calamares executable -option( WITH_KF5Crash "Enable crash reporting with KCrash." ON ) # TODO:3.3: WITH->BUILD (this isn't an ABI thing) -option( WITH_KF5DBus "Use DBus service for unique-application." OFF ) # TODO:3.3: WITH->BUILD +option(INSTALL_CONFIG "Install configuration files" OFF) +option(INSTALL_POLKIT "Install Polkit configuration" ON) +option(INSTALL_COMPLETION "Install shell completions" OFF) # When adding WITH_* that affects the ABI offered by libcalamares, # also update libcalamares/CalamaresConfig.h.in -option( WITH_PYTHON "Enable Python modules API (requires Boost.Python)." ON ) -option( WITH_PYTHONQT "Enable Python view modules API (deprecated, requires PythonQt)." OFF ) # TODO:3.3: remove -option( WITH_QML "Enable QML UI options." ON ) +option(WITH_PYTHON "Enable Python modules API (requires Boost.Python)." ON) +option(WITH_QML "Enable QML UI options." ON) # -# Additional parts to build -option( BUILD_SCHEMA_TESTING "Enable schema-validation-tests" ON ) - +# Additional parts to build that do not affect ABI +option(BUILD_SCHEMA_TESTING "Enable schema-validation-tests" ON) +# Options for the calamares executable +option(BUILD_KF5Crash "Enable crash reporting with KCrash." ON) # Possible debugging flags are: # - DEBUG_TIMEZONES draws latitude and longitude lines on the timezone @@ -77,7 +84,6 @@ option( BUILD_SCHEMA_TESTING "Enable schema-validation-tests" ON ) # - DEBUG_PARTITION_UNSAFE (see partition/CMakeLists.txt) # - DEBUG_PARTITION_BAIL_OUT (see partition/CMakeLists.txt) - ### USE_* # # By convention, when there are multiple modules that implement similar @@ -101,15 +107,14 @@ option( BUILD_SCHEMA_TESTING "Enable schema-validation-tests" ON ) # - *services* picks one of the two service-configuration modules, # for either systemd or openrc. This defaults to empty so that # **both** modules are available. -set( USE_services "" CACHE STRING "Select the services module to use" ) +set(USE_services "" CACHE STRING "Select the services module to use") ### Calamares application info # -set( CALAMARES_ORGANIZATION_NAME "Calamares" ) -set( CALAMARES_ORGANIZATION_DOMAIN "github.com/calamares" ) -set( CALAMARES_APPLICATION_NAME "Calamares" ) -set( CALAMARES_DESCRIPTION_SUMMARY - "The distribution-independent installer framework" ) +set(CALAMARES_ORGANIZATION_NAME "Calamares") +set(CALAMARES_ORGANIZATION_DOMAIN "github.com/calamares") +set(CALAMARES_APPLICATION_NAME "Calamares") +set(CALAMARES_DESCRIPTION_SUMMARY "The distribution-independent installer framework") ### Transifex (languages) info # @@ -135,40 +140,42 @@ set( CALAMARES_DESCRIPTION_SUMMARY # `txstats.py -e`. See also # # Total 74 languages -set( _tx_complete az az_AZ ca es fi_FI he hi hr ja lt pt_BR pt_PT - sq sv uk zh_TW ) -set( _tx_good as be ca@valencia cs_CZ da de fa fr fur it_IT ko ml - nl ru si sk tg tr_TR vi zh_CN ) +set( _tx_complete az az_AZ ca es fi_FI he hi hr ja ko lt pt_BR + pt_PT sq sv tr_TR uk zh_TW ) +set( _tx_good as be ca@valencia cs_CZ da de fa fr fur it_IT ml nl + ru si sk tg vi zh_CN ) set( _tx_ok ar ast bg bn el en_GB es_MX et eu gl hu id is mr nb oc pl ro sl sr sr@latin th ) set( _tx_incomplete eo es_PR gu ie ja-Hira kk kn lo lv mk ne_NP ta_IN te ur zh zh_HK ) +# Total 74 languages ### Required versions # # See DEPENDENCIES section below. -set( QT_VERSION 5.9.0 ) -set( YAMLCPP_VERSION 0.5.1 ) -set( ECM_VERSION 5.18 ) -set( PYTHONLIBS_VERSION 3.3 ) -set( BOOSTPYTHON_VERSION 1.55.0 ) - +set(QT_VERSION 5.15.0) +set(YAMLCPP_VERSION 0.5.1) +set(ECM_VERSION 5.18) +set(PYTHONLIBS_VERSION 3.6) +set(BOOSTPYTHON_VERSION 1.72.0) ### CMAKE SETUP # -set( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules" ) +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeModules") # Enable IN_LIST -if( POLICY CMP0057 ) - cmake_policy( SET CMP0057 NEW ) +if(POLICY CMP0057) + cmake_policy(SET CMP0057 NEW) endif() # Let ``AUTOMOC`` and ``AUTOUIC`` process ``GENERATED`` files. -if( POLICY CMP0071 ) - cmake_policy( SET CMP0071 NEW ) +if(POLICY CMP0071) + cmake_policy(SET CMP0071 NEW) endif() # Recognize more macros to trigger automoc if(NOT CMAKE_VERSION VERSION_LESS "3.10.0") - list(APPEND CMAKE_AUTOMOC_MACRO_NAMES + list( + APPEND + CMAKE_AUTOMOC_MACRO_NAMES "K_PLUGIN_FACTORY_WITH_JSON" "K_EXPORT_PLASMA_DATAENGINE_WITH_JSON" "K_EXPORT_PLASMA_RUNNER" @@ -176,40 +183,50 @@ if(NOT CMAKE_VERSION VERSION_LESS "3.10.0") endif() # CMake Modules -include( CMakePackageConfigHelpers ) -include( CTest ) -include( FeatureSummary ) +include(CMakePackageConfigHelpers) +include(CTest) +include(FeatureSummary) # Calamares Modules -include( CMakeColors ) +include(CMakeColors) ### C++ SETUP # -set( CMAKE_CXX_STANDARD 17 ) -set( CMAKE_CXX_STANDARD_REQUIRED ON ) -set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror=return-type" ) -set( CMAKE_CXX_FLAGS_DEBUG "-Og -g ${CMAKE_CXX_FLAGS_DEBUG}" ) -set( CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG" ) -set( CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" ) -set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g" ) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror=return-type") +set(CMAKE_CXX_FLAGS_DEBUG "-Og -g ${CMAKE_CXX_FLAGS_DEBUG}") +set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG") +set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") -set( CMAKE_C_STANDARD 99 ) -set( CMAKE_C_STANDARD_REQUIRED ON ) -set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall" ) -set( CMAKE_C_FLAGS_DEBUG "-Og -g" ) -set( CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG" ) -set( CMAKE_C_FLAGS_RELEASE "-O4 -DNDEBUG" ) -set( CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g" ) +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") +set(CMAKE_C_FLAGS_DEBUG "-Og -g") +set(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG") +set(CMAKE_C_FLAGS_RELEASE "-O4 -DNDEBUG") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g") -set( CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined -Wl,--fatal-warnings" ) +set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined -Wl,--fatal-warnings") -if( CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) - message( STATUS "Found Clang ${CMAKE_CXX_COMPILER_VERSION}, setting up Clang-specific compiler flags." ) +# If no build type is set, pick a reasonable one +if(NOT CMAKE_BUILD_TYPE) + if(CALAMARES_RELEASE_MODE) + set(CMAKE_BUILD_TYPE "RelWithDebInfo") + else() + set(CMAKE_BUILD_TYPE "Debug") + endif() +endif() + +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + message(STATUS "Found Clang ${CMAKE_CXX_COMPILER_VERSION}, setting up Clang-specific compiler flags.") # Clang warnings: doing *everything* is counter-productive, since it warns # about things which we can't fix (e.g. C++98 incompatibilities, but # Calamares is C++17). - foreach( CLANG_WARNINGS + foreach( + CLANG_WARNINGS -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic @@ -221,68 +238,69 @@ if( CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) -Wno-documentation-unknown-command -Wno-unknown-warning-option ) - string( APPEND CMAKE_CXX_FLAGS " ${CLANG_WARNINGS}" ) + string(APPEND CMAKE_CXX_FLAGS " ${CLANG_WARNINGS}") endforeach() # The dwarf-debugging flags are slightly different, too - string( APPEND CMAKE_CXX_FLAGS_DEBUG " -gdwarf" ) - string( APPEND CMAKE_C_FLAGS_DEBUG " -gdwarf" ) + string(APPEND CMAKE_CXX_FLAGS_DEBUG " -gdwarf") + string(APPEND CMAKE_C_FLAGS_DEBUG " -gdwarf") # Third-party code where we don't care so much about compiler warnings # (because it's uncomfortable to patch) get different flags; use # mark_thirdparty_code( [...] ) # to switch off warnings for those sources. - set( SUPPRESS_3RDPARTY_WARNINGS "-Wno-everything" ) + set(SUPPRESS_3RDPARTY_WARNINGS "-Wno-everything") - set( CMAKE_TOOLCHAIN_PREFIX "llvm-" ) + set(CMAKE_TOOLCHAIN_PREFIX "llvm-") # The path prefix is only relevant for CMake 3.16 and later, fixes #1286 - set( CMAKE_AUTOMOC_PATH_PREFIX OFF ) - set( CALAMARES_AUTOMOC_OPTIONS "-butils/moc-warnings.h" ) - set( CALAMARES_AUTOUIC_OPTIONS --include utils/moc-warnings.h ) + set(CMAKE_AUTOMOC_PATH_PREFIX OFF) + set(CALAMARES_AUTOMOC_OPTIONS "-butils/moc-warnings.h") + set(CALAMARES_AUTOUIC_OPTIONS --include utils/moc-warnings.h) else() - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Woverloaded-virtual" ) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Woverloaded-virtual") - set( SUPPRESS_3RDPARTY_WARNINGS "" ) + set(SUPPRESS_3RDPARTY_WARNINGS "") endif() # Use mark_thirdparty_code() to reduce warnings from the compiler # on code that we're not going to fix. Call this with a list of files. macro(mark_thirdparty_code) - set_source_files_properties( ${ARGV} - PROPERTIES - COMPILE_FLAGS "${SUPPRESS_3RDPARTY_WARNINGS}" - COMPILE_DEFINITIONS "THIRDPARTY" + set_source_files_properties( + ${ARGV} + PROPERTIES COMPILE_FLAGS "${SUPPRESS_3RDPARTY_WARNINGS}" COMPILE_DEFINITIONS "THIRDPARTY" ) endmacro() -if( CMAKE_COMPILER_IS_GNUCXX ) - if( CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9 OR - CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.9 ) - message( STATUS "Found GNU g++ ${CMAKE_CXX_COMPILER_VERSION}, enabling colorized error messages." ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=auto" ) +if(CMAKE_COMPILER_IS_GNUCXX) + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9 OR CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.9) + message(STATUS "Found GNU g++ ${CMAKE_CXX_COMPILER_VERSION}, enabling colorized error messages.") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=auto") endif() endif() +# API that was deprecated before Qt 5.15 causes a compile error +add_compile_definitions(QT_DISABLE_DEPRECATED_BEFORE=0x050f00) ### DEPENDENCIES # -find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Concurrent Core Gui LinguistTools Network Svg Widgets ) -if( WITH_QML ) - find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Quick QuickWidgets ) +find_package(Qt5 ${QT_VERSION} CONFIG REQUIRED Concurrent Core Gui LinguistTools Network Svg Widgets) +if(WITH_QML) + find_package(Qt5 ${QT_VERSION} CONFIG REQUIRED Quick QuickWidgets) endif() # Optional Qt parts -find_package( Qt5DBus CONFIG ) +find_package(Qt5DBus CONFIG) -find_package( YAMLCPP ${YAMLCPP_VERSION} REQUIRED ) -if( INSTALL_POLKIT ) - find_package( PolkitQt5-1 REQUIRED ) +find_package(YAMLCPP ${YAMLCPP_VERSION} REQUIRED) +if(INSTALL_POLKIT) + find_package(PolkitQt5-1 REQUIRED) else() # Find it anyway, for dependencies-reporting - find_package( PolkitQt5-1 ) + find_package(PolkitQt5-1) endif() set_package_properties( - PolkitQt5-1 PROPERTIES + PolkitQt5-1 + PROPERTIES DESCRIPTION "Qt5 support for Polkit" URL "https://cgit.kde.org/polkit-qt-1.git" PURPOSE "PolkitQt5-1 helps with installing Polkit configuration" @@ -293,115 +311,104 @@ set_package_properties( # find_package(ECM ${ECM_VERSION} REQUIRED NO_MODULE), # no need to mess with the module path after. find_package(ECM ${ECM_VERSION} NO_MODULE) -if( ECM_FOUND ) +if(ECM_FOUND) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH}) - if ( BUILD_TESTING ) + if(BUILD_TESTING) # ECM implies that we can build the tests, too - find_package( Qt5 COMPONENTS Test REQUIRED ) - include( ECMAddTests ) + find_package(Qt5 COMPONENTS Test REQUIRED) + include(ECMAddTests) endif() include(KDEInstallDirs) endif() -find_package( KF5 QUIET COMPONENTS CoreAddons Crash DBusAddons ) +find_package(KF5 QUIET COMPONENTS CoreAddons Crash DBusAddons) set_package_properties( - KF5::CoreAddons PROPERTIES + KF5::CoreAddons + PROPERTIES TYPE REQUIRED DESCRIPTION "Classes built on QtCore for About Data" URL "https://api.kde.org/frameworks/kcoreaddons/" PURPOSE "About Calamares" ) -if( NOT KF5Crash_FOUND ) - if( WITH_KF5Crash ) - message(WARNING "WITH_KF5Crash is set, but KF5::Crash is not available.") +set_package_properties( + KF5::DBusAddons + PROPERTIES + TYPE REQUIRED + DESCRIPTION "Classes for DBus activation" + URL "https://api.kde.org/frameworks/dbusaddons/" + PURPOSE "Unique instance of Calamares" +) +if(NOT KF5Crash_FOUND) + if(BUILD_KF5Crash) + message(WARNING "BUILD_KF5Crash is set, but KF5::Crash is not available.") endif() - set( WITH_KF5Crash OFF ) -endif() -if( NOT KF5DBusAddons_FOUND ) - if( WITH_KF5DBus ) - message(WARNING "WITH_KF5DBus is set, but KF5::DBusAddons is not available.") - endif() - set( WITH_KF5DBus OFF ) + set(BUILD_KF5Crash OFF) endif() -# TODO:3.3: Use FindPython3 instead -find_package( PythonInterp ${PYTHONLIBS_VERSION} ) +find_package(Python ${PYTHONLIBS_VERSION} COMPONENTS Interpreter Development) set_package_properties( - PythonInterp PROPERTIES - DESCRIPTION "Python 3 interpreter." + Python + PROPERTIES + DESCRIPTION "Python3 interpreter." URL "https://python.org" - PURPOSE "Python 3 interpreter for certain tests." + PURPOSE "Python3 interpreter for certain tests." ) -set( _schema_explanation "" ) -if ( PYTHONINTERP_FOUND ) - if ( BUILD_SCHEMA_TESTING ) +set(_schema_explanation "") +if(Python_Interpreter_FOUND) + if(BUILD_SCHEMA_TESTING) # The configuration validator script has some dependencies, # and if they are not installed, don't run. If errors out # with exit(1) on missing dependencies. - if ( CALAMARES_CONFIGVALIDATOR_CHECKED ) - set( _validator_deps ${CALAMARES_CONFIGVALIDATOR_RESULT} ) + if(CALAMARES_CONFIGVALIDATOR_CHECKED) + set(_validator_deps ${CALAMARES_CONFIGVALIDATOR_RESULT}) else() - exec_program( ${PYTHON_EXECUTABLE} ARGS "${CMAKE_SOURCE_DIR}/ci/configvalidator.py" -x RETURN_VALUE _validator_deps ) - set( CALAMARES_CONFIGVALIDATOR_CHECKED TRUE CACHE INTERNAL "Dependencies for configvalidator checked" ) - set( CALAMARES_CONFIGVALIDATOR_RESULT ${_validator_deps} CACHE INTERNAL "Result of configvalidator dependency check" ) + exec_program( + ${Python_EXECUTABLE} + ARGS + "${CMAKE_SOURCE_DIR}/ci/configvalidator.py" + -x + RETURN_VALUE + _validator_deps + ) + set(CALAMARES_CONFIGVALIDATOR_CHECKED TRUE CACHE INTERNAL "Dependencies for configvalidator checked") + set(CALAMARES_CONFIGVALIDATOR_RESULT ${_validator_deps} + CACHE INTERNAL "Result of configvalidator dependency check" + ) endif() # It should never succeed, but only returns 1 when the imports fail - if ( _validator_deps EQUAL 1 ) - set( _schema_explanation " Missing dependencies for configvalidator.py." ) - set( BUILD_SCHEMA_TESTING OFF ) + if(_validator_deps EQUAL 1) + set(_schema_explanation " Missing dependencies for configvalidator.py.") + set(BUILD_SCHEMA_TESTING OFF) endif() endif() else() # Can't run schema tests without Python3. - set( _schema_explanation " Missing Python3." ) - set( BUILD_SCHEMA_TESTING OFF ) + set(_schema_explanation " Missing Python3.") + set(BUILD_SCHEMA_TESTING OFF) endif() -add_feature_info( yaml-schema BUILD_SCHEMA_TESTING "Validate YAML (config files) with schema.${_schema_explanation}" ) +add_feature_info(yaml-schema BUILD_SCHEMA_TESTING "Validate YAML (config files) with schema.${_schema_explanation}") -find_package( PythonLibs ${PYTHONLIBS_VERSION} ) -set_package_properties( - PythonLibs PROPERTIES - DESCRIPTION "C interface libraries for the Python 3 interpreter." - URL "https://python.org" - PURPOSE "Python 3 is used for Python job modules." -) - -if ( PYTHONLIBS_FOUND ) - # TODO:3.3: Require Boost + CMake; sort out Boost::Python - # Since Boost provides CMake config files (starting with Boost 1.70. - # or so) the mess that is the Calamares find code picks the wrong - # bits. Suppress those CMake config files, as suggested by @jmrcpn - set(Boost_NO_BOOST_CMAKE ON) - include( BoostPython3 ) - find_boost_python3( ${BOOSTPYTHON_VERSION} ${PYTHONLIBS_VERSION_STRING} CALAMARES_BOOST_PYTHON3_FOUND ) - set_package_properties( - Boost PROPERTIES - PURPOSE "Boost.Python is used for Python job modules." - ) - # TODO:3.3: Remove PythonQt support - find_package( PythonQt ) - set_package_properties( PythonQt PROPERTIES - DESCRIPTION "A Python embedding solution for Qt applications." - URL "http://pythonqt.sourceforge.net" - PURPOSE "PythonQt is used for Python view modules." - ) +if(Python_Development_FOUND) + find_package(boost_python) + if(NOT TARGET Boost::python) + find_package(Boost ${BOOSTPYTHON_VERSION} COMPONENTS python) + set_package_properties(Boost PROPERTIES PURPOSE "Boost.Python is used for Python job modules.") + else() + message(STATUS "Found boost_python with target Boost::python") + set(Boost_FOUND ON) + endif() endif() -if( NOT PYTHONLIBS_FOUND OR NOT CALAMARES_BOOST_PYTHON3_FOUND ) +if(NOT Python_Development_FOUND OR NOT Boost_FOUND) message(STATUS "Disabling Boost::Python modules") - set( WITH_PYTHON OFF ) -endif() -if( NOT PYTHONLIBS_FOUND OR NOT PYTHONQT_FOUND ) - message(STATUS "Disabling PythonQt modules") - set( WITH_PYTHONQT OFF ) + set(WITH_PYTHON OFF) endif() # Now we know the state of the ABI-options, copy them into "Calamares_" # prefixed variables, to match how the variables would-be-named # when building out-of-tree. set(Calamares_WITH_PYTHON ${WITH_PYTHON}) -set(Calamares_WITH_PYTHONQT ${WITH_PYTHONQT}) set(Calamares_WITH_QML ${WITH_QML}) ### Transifex Translation status @@ -411,39 +418,39 @@ set(Calamares_WITH_QML ${WITH_QML}) # for some obvious error. The actual work of compiling translations # is done in the lang/ directory. # -if( Qt5_VERSION VERSION_GREATER 5.12.1 ) +if(Qt5_VERSION VERSION_GREATER 5.12.1) # At least Qt 5.12.2 seems to support Esperanto in QLocale - if( "eo" IN_LIST _tx_incomplete ) + if("eo" IN_LIST _tx_incomplete) message(STATUS "Esperanto support since Qt 5.12.2, enabling Esperanto locale") - list( REMOVE_ITEM _tx_incomplete "eo" ) - list( APPEND _tx_ok "eo" ) + list(REMOVE_ITEM _tx_incomplete "eo") + list(APPEND _tx_ok "eo") endif() endif() -set( curr_tx ${_tx_complete} ${_tx_good} ${_tx_ok} ${_tx_incomplete} ) -set( tx_errors OFF ) -if ( curr_tx ) +set(curr_tx ${_tx_complete} ${_tx_good} ${_tx_ok} ${_tx_incomplete}) +set(tx_errors OFF) +if(curr_tx) # New in list - foreach( l ${curr_tx} ) - set( p_l "lang/calamares_${l}.ts" ) - if( NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${p_l} ) + foreach(l ${curr_tx}) + set(p_l "lang/calamares_${l}.ts") + if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${p_l}) message(WARNING "Language ${l} has no .ts file yet.") - set( tx_errors ON ) + set(tx_errors ON) endif() endforeach() - unset( p_l ) - unset( l ) + unset(p_l) + unset(l) endif() -unset( curr_tx ) -if( tx_errors ) - message( FATAL_ERROR "Translation warnings, see above." ) +unset(curr_tx) +if(tx_errors) + message(FATAL_ERROR "Translation warnings, see above.") endif() -set( CALAMARES_TRANSLATION_LANGUAGES en ${_tx_complete} ${_tx_good} ${_tx_ok} ) -list( SORT CALAMARES_TRANSLATION_LANGUAGES ) +set(CALAMARES_TRANSLATION_LANGUAGES en ${_tx_complete} ${_tx_good} ${_tx_ok}) +list(SORT CALAMARES_TRANSLATION_LANGUAGES) -add_subdirectory( lang ) # i18n tools +add_subdirectory(lang) # i18n tools ### Example Distro # @@ -462,22 +469,22 @@ add_subdirectory( lang ) # i18n tools # # make example-distro # -find_program( mksquashfs_PROGRAM mksquashfs ) -if( mksquashfs_PROGRAM ) - set( mksquashfs_FOUND ON ) - set( src_fs ${CMAKE_SOURCE_DIR}/data/example-root/ ) - set( dst_fs ${CMAKE_BINARY_DIR}/example.sqfs ) - if( EXISTS ${src_fs} ) +find_program(mksquashfs_PROGRAM mksquashfs) +if(mksquashfs_PROGRAM) + set(mksquashfs_FOUND ON) + set(src_fs ${CMAKE_SOURCE_DIR}/data/example-root/) + set(dst_fs ${CMAKE_BINARY_DIR}/example.sqfs) + if(EXISTS ${src_fs}) # based on the build host. If /lib64 exists, assume it is needed. # Collect directories needed for a minimal binary distro, # Note that the last path component is added to the root, so # if you add /usr/sbin here, it will be put into /sbin_1. # Add such paths to /etc/profile under ${src_fs}. - set( candidate_fs /sbin /bin /lib /lib64 ) - set( host_fs "" ) - foreach( c_fs ${candidate_fs} ) - if( EXISTS ${c_fs} ) - list( APPEND host_fs ${c_fs} ) + set(candidate_fs /sbin /bin /lib /lib64) + set(host_fs "") + foreach(c_fs ${candidate_fs}) + if(EXISTS ${c_fs}) + list(APPEND host_fs ${c_fs}) endif() endforeach() add_custom_command( @@ -488,105 +495,89 @@ if( mksquashfs_PROGRAM ) add_custom_target(example-distro DEPENDS ${dst_fs}) endif() else() - set( mksquashfs_FOUND OFF ) + set(mksquashfs_FOUND OFF) endif() # Doesn't list mksquashfs as an optional dep, though, because it # hasn't been sent through the find_package() scheme. # # "http://tldp.org/HOWTO/SquashFS-HOWTO/creatingandusing.html" -add_feature_info( ExampleDistro ${mksquashfs_FOUND} "Create example-distro target.") - +add_feature_info(ExampleDistro ${mksquashfs_FOUND} "Create example-distro target.") ### CALAMARES PROPER # -set( CALAMARES_VERSION ${CALAMARES_VERSION_MAJOR}.${CALAMARES_VERSION_MINOR}.${CALAMARES_VERSION_PATCH} ) +set(CALAMARES_VERSION ${CALAMARES_VERSION_MAJOR}.${CALAMARES_VERSION_MINOR}.${CALAMARES_VERSION_PATCH}) # In rare cases we have hotfix-releases with a tweak -if( CALAMARES_VERSION_TWEAK ) - set( CALAMARES_VERSION "${CALAMARES_VERSION}.${CALAMARES_VERSION_TWEAK}" ) +if(CALAMARES_VERSION_TWEAK) + set(CALAMARES_VERSION "${CALAMARES_VERSION}.${CALAMARES_VERSION_TWEAK}") endif() -set( CALAMARES_VERSION_SHORT "${CALAMARES_VERSION}" ) +set(CALAMARES_VERSION_SHORT "${CALAMARES_VERSION}") # Additional info for non-release builds. The "extended" version information # with date and git information (commit, dirty status) is used only # by CalamaresVersionX.h, which is included by consumers that need a full # version number with all that information; normal consumers can include # CalamaresVersion.h with more stable numbers. -if( NOT BUILD_RELEASE AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git/" ) - include( ExtendedVersion ) +if(NOT BUILD_RELEASE AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git/") + include(ExtendedVersion) extend_version( "${CALAMARES_VERSION}" OFF CALAMARES_VERSION_SHORT CALAMARES_VERSION ) endif() -# Special target for not-RC (e.g. might-be-release) builds. -# This is used by the release script to get the version. -if ( CALAMARES_VERSION_RC EQUAL 0 ) - add_custom_target(show-version - ${CMAKE_COMMAND} -E echo CALAMARES_VERSION=${CALAMARES_VERSION_SHORT} - USES_TERMINAL - ) +# Special define for RC (e.g. not-a-release) builds. +# This is consumed via the CalamaresConfig.h header. +if(NOT CALAMARES_RELEASE_MODE) + set(CALAMARES_VERSION_RC 1) endif() # enforce using constBegin, constEnd for const-iterators -add_definitions( - -DQT_STRICT_ITERATORS - -DQT_SHARED - -DQT_SHAREDPOINTER_TRACK_POINTERS -) +add_definitions(-DQT_STRICT_ITERATORS -DQT_SHARED -DQT_SHAREDPOINTER_TRACK_POINTERS) # set paths -set( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) -set( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) -set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") # Better default installation paths: GNUInstallDirs defines # CMAKE_INSTALL_FULL_SYSCONFDIR to be CMAKE_INSTALL_PREFIX/etc by default # but we really want /etc -if( NOT DEFINED CMAKE_INSTALL_SYSCONFDIR ) - set( CMAKE_INSTALL_SYSCONFDIR "/etc" ) +if(NOT DEFINED CMAKE_INSTALL_SYSCONFDIR) + set(CMAKE_INSTALL_SYSCONFDIR "/etc") endif() # make predefined install dirs available everywhere -include( GNUInstallDirs ) +include(GNUInstallDirs) # This is used by CalamaresAddLibrary; once Calamares is installed, # the CalamaresConfig.cmake module sets this variable to the IMPORTED # libraries for Calamares. -set( Calamares_LIBRARIES calamares ) +set(Calamares_LIBRARIES calamares) -add_subdirectory( src ) +add_subdirectory(src) add_feature_info(Python ${WITH_PYTHON} "Python job modules") -add_feature_info(PythonQt ${WITH_PYTHONQT} "Python view modules") +add_feature_info(Qml ${WITH_QML} "QML UI support") add_feature_info(Config ${INSTALL_CONFIG} "Install Calamares configuration") -add_feature_info(KCrash ${WITH_KF5Crash} "Crash dumps via KCrash") -add_feature_info(KDBusAddons ${WITH_KF5DBus} "Unique-application via DBus") +add_feature_info(Polkit ${INSTALL_POLKIT} "Install Polkit files") +add_feature_info(KCrash ${BUILD_KF5Crash} "Crash dumps via KCrash") ### CMake infrastructure installation # # -set( CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/Calamares" CACHE PATH "Installation directory for CMake files" ) -set( CMAKE_INSTALL_FULL_CMAKEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}" ) +set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/Calamares" CACHE PATH "Installation directory for CMake files") +set(CMAKE_INSTALL_FULL_CMAKEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}") -export( PACKAGE Calamares ) +export(PACKAGE Calamares) configure_package_config_file( "CalamaresConfig.cmake.in" "${PROJECT_BINARY_DIR}/CalamaresConfig.cmake" INSTALL_DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" - PATH_VARS - CMAKE_INSTALL_INCLUDEDIR - CMAKE_INSTALL_LIBDIR - CMAKE_INSTALL_DATADIR + PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR CMAKE_INSTALL_DATADIR ) write_basic_package_version_file( ${PROJECT_BINARY_DIR}/CalamaresConfigVersion.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ) -install( - EXPORT Calamares - DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" - FILE "CalamaresTargets.cmake" - NAMESPACE Calamares:: -) +install(EXPORT Calamares DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" FILE "CalamaresTargets.cmake" NAMESPACE Calamares::) # Install the cmake files install( @@ -603,69 +594,48 @@ install( "CMakeModules/CalamaresCheckModuleSelection.cmake" "CMakeModules/CMakeColors.cmake" "CMakeModules/FindYAMLCPP.cmake" - DESTINATION - "${CMAKE_INSTALL_CMAKEDIR}" + DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" ) ### Miscellaneous installs # # -if( INSTALL_CONFIG ) - install( - FILES settings.conf - DESTINATION share/calamares - ) +if(INSTALL_CONFIG) + install(FILES settings.conf DESTINATION share/calamares) endif() -if( INSTALL_POLKIT ) - install( - FILES com.github.calamares.calamares.policy - DESTINATION "${POLKITQT-1_POLICY_FILES_INSTALL_DIR}" - ) +if(INSTALL_POLKIT) + install(FILES com.github.calamares.calamares.policy DESTINATION "${POLKITQT-1_POLICY_FILES_INSTALL_DIR}") endif() -if ( INSTALL_COMPLETION ) - if( NOT CMAKE_INSTALL_BASHCOMPLETIONDIR ) - set( CMAKE_INSTALL_BASHCOMPLETIONDIR "${CMAKE_INSTALL_DATADIR}/bash-completion/completions" ) +if(INSTALL_COMPLETION) + if(NOT CMAKE_INSTALL_BASHCOMPLETIONDIR) + set(CMAKE_INSTALL_BASHCOMPLETIONDIR "${CMAKE_INSTALL_DATADIR}/bash-completion/completions") endif() - install( FILES ${CMAKE_SOURCE_DIR}/data/completion/bash/calamares DESTINATION "${CMAKE_INSTALL_BASHCOMPLETIONDIR}" ) + install(FILES ${CMAKE_SOURCE_DIR}/data/completion/bash/calamares DESTINATION "${CMAKE_INSTALL_BASHCOMPLETIONDIR}") endif() -install( - FILES calamares.desktop - DESTINATION ${CMAKE_INSTALL_DATADIR}/applications -) +install(FILES calamares.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) -install( - FILES man/calamares.8 - DESTINATION ${CMAKE_INSTALL_MANDIR}/man8/ -) +install(FILES man/calamares.8 DESTINATION ${CMAKE_INSTALL_MANDIR}/man8/) # uninstall target configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" - IMMEDIATE @ONLY + IMMEDIATE + @ONLY ) -add_custom_target( uninstall - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake -) +add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) ### CMAKE SUMMARY REPORT # -get_directory_property( SKIPPED_MODULES - DIRECTORY src/modules - DEFINITION LIST_SKIPPED_MODULES -) +get_directory_property(SKIPPED_MODULES DIRECTORY src/modules DEFINITION LIST_SKIPPED_MODULES) calamares_explain_skipped_modules( ${SKIPPED_MODULES} ) -feature_summary( - WHAT DISABLED_FEATURES - DESCRIPTION "The following features have been disabled:" - QUIET_ON_EMPTY -) +feature_summary(WHAT DISABLED_FEATURES DESCRIPTION "The following features have been disabled:" QUIET_ON_EMPTY) feature_summary( WHAT OPTIONAL_PACKAGES_NOT_FOUND DESCRIPTION "The following OPTIONAL packages were not found:" @@ -682,11 +652,11 @@ feature_summary( # # Note: most distro's will do distro-specific packaging rather than # using CPack, and this duplicates information in the AppStream, too. -# TODO:3.3 With newer CMake, move HOMEPAGE_URL to the project()call set(CPACK_PACKAGE_VENDOR calamares) set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A Linux system installer") -set(CPACK_PACKAGE_DESCRIPTION "Calamares is a Linux system installer, intended for Linux distributions to use on their ISOs and other bootable media to install the distribution to the end-user's computer. Calamares can also be used as an OEM configuration tool. It is modular, extensible and highly-configurable for Linux distributions from all five major Linux families.") -set(CPACK_PACKAGE_HOMEPAGE_URL "https://calamares.io") +set(CPACK_PACKAGE_DESCRIPTION + "Calamares is a Linux system installer, intended for Linux distributions to use on their ISOs and other bootable media to install the distribution to the end-user's computer. Calamares can also be used as an OEM configuration tool. It is modular, extensible and highly-configurable for Linux distributions from all five major Linux families." +) set(CPACK_PACKAGE_ICON "data/images/squid.png") include(CPack) diff --git a/CMakeModules/BoostPython3.cmake b/CMakeModules/BoostPython3.cmake deleted file mode 100644 index bd1d24e0e..000000000 --- a/CMakeModules/BoostPython3.cmake +++ /dev/null @@ -1,97 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2014 Aurélien Gâteau -# SPDX-FileCopyrightText: 2017 Adriaan de Groot -# SPDX-FileCopyrightText: 2019 Kevin Kofler -# SPDX-License-Identifier: BSD-2-Clause -# -### -# -# Handles the mess that Boost::Python is before CMake 3.16 and -# Boost 1.70 or so. -# -### -# -# On Ubuntu 14.04, the libboost-python1.54-dev package comes with one library -# for each Python version: -# libboost_python-py27.so -# libboost_python-py33.so -# libboost_python-py34.so -# -# Boost upstream however installs Boost.Python3 libboost_python3.so, which is -# what FindBoost.cmake is looking for. It looks for a library named -# "libboost_${component}.so". -# -# On Gentoo instead, the >=dev-libs/boost-1.54 package provides boost library -# with a name like: -# libboost_python-2.7.so -# libboost_python-3.3.so -# libboost_python-3.4.so -# depending on what python's targets you selected during install -# -# On Fedora >= 30 instead, the boost-python3-devel provides boost library with a -# name like: -# libboost_python37.so -# depending on what python's targets you selected during install -# -# find_boost_python3() tries to find the package with different component -# names. By default it tries "python3", "python-py$suffix" and -# "python-$dotsuffix", where suffix is based on the `python_version` argument. -# One can supply a custom component name by setting the -# `CALAMARES_BOOST_PYTHON3_COMPONENT` variable at CMake time. -set( CALAMARES_BOOST_PYTHON3_COMPONENT python3 CACHE STRING - "Name of the Boost.Python component. If Boost.Python is installed as - libboost_python-foo.so then this variable should be set to 'python-foo'." -) - -include(FindPackageHandleStandardArgs) - -macro( _find_boost_python3_int boost_version componentname found_var ) - foreach( _fbp_name ${CALAMARES_BOOST_PYTHON3_COMPONENT} ${componentname} ) - find_package( Boost ${boost_version} QUIET COMPONENTS ${_fbp_name} ) - string( TOUPPER ${_fbp_name} _fbp_uc_name ) - if( Boost_${_fbp_uc_name}_FOUND ) - if( CMAKE_SYSTEM_NAME MATCHES "FreeBSD" ) - # No upcasing - set( ${found_var} ${_fbp_name} ) - else() - set( ${found_var} ${_fbp_uc_name} ) - endif() - break() - endif() - endforeach() -endmacro() - -macro( find_boost_python3 boost_version python_version found_var ) - set( ${found_var} OFF ) - set( _fbp_found OFF ) - - # turns "3.4.123abc" into "34" - string( REGEX REPLACE "([0-9]+)\\.([0-9]+)\\..*" "\\1\\2" _fbp_python_short_version ${python_version} ) - _find_boost_python3_int( ${boost_version} python-py${_fbp_python_short_version} _fbp_found ) - - if (NOT _fbp_found) - _find_boost_python3_int( ${boost_version} python${_fbp_python_short_version} _fbp_found ) - endif() - - if (NOT _fbp_found) - # The following loop changes the searched name for Gentoo based distributions - # turns "3.4.123abc" into "3.4" - string( REGEX REPLACE "([0-9]+)\\.([0-9]+)\\..*" "\\1.\\2" _fbp_python_short_version ${python_version} ) - _find_boost_python3_int( ${boost_version} python-${_fbp_python_short_version} _fbp_found ) - endif() - - set( ${found_var} ${_fbp_found} ) - - # This is superfluous, but allows proper reporting in the features list - if ( _fbp_found ) - find_package( Boost ${boost_version} COMPONENTS ${_fbp_found} ) - else() - find_package( Boost ${boost_version} COMPONENTS Python ) - endif() - set_package_properties( - Boost PROPERTIES - DESCRIPTION "A C++ library which enables seamless interoperability between C++ and Python 3." - URL "http://www.boost.org" - ) -endmacro() diff --git a/CMakeModules/CalamaresAddModuleSubdirectory.cmake b/CMakeModules/CalamaresAddModuleSubdirectory.cmake index 91524a09e..e0eed223e 100644 --- a/CMakeModules/CalamaresAddModuleSubdirectory.cmake +++ b/CMakeModules/CalamaresAddModuleSubdirectory.cmake @@ -121,7 +121,8 @@ function( _calamares_add_module_subdirectory_impl ) # _mod_testing boolean if the module should be added to the loadmodule tests file(STRINGS "${_mod_dir}/module.desc" MODULE_INTERFACE REGEX "^interface") if ( MODULE_INTERFACE MATCHES "pythonqt" ) - set( _mod_enabled ${Calamares_WITH_PYTHONQT} ) + message( FATAL_ERROR "PythonQt is no longer supported" ) + set( _mod_enabled OFF ) set( _mod_reason "No PythonQt support" ) set( _mod_testing OFF ) elseif ( MODULE_INTERFACE MATCHES "python" ) diff --git a/CMakeModules/CalamaresAddTest.cmake b/CMakeModules/CalamaresAddTest.cmake index cd757bb88..b40e92939 100644 --- a/CMakeModules/CalamaresAddTest.cmake +++ b/CMakeModules/CalamaresAddTest.cmake @@ -18,19 +18,17 @@ # SOURCES # ) -include( CMakeParseArguments ) -include( CalamaresAutomoc ) +include(CMakeParseArguments) +include(CalamaresAutomoc) -function( calamares_add_test ) - # parse arguments (name needs to be saved before passing ARGN into the macro) - set( NAME ${ARGV0} ) - set( options GUI ) - set( oneValueArgs NAME RESOURCES ) - set( multiValueArgs SOURCES LIBRARIES DEFINITIONS ) - cmake_parse_arguments( TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) - set( TEST_NAME ${NAME} ) +function(calamares_add_test name) + set(options GUI) + set(oneValueArgs RESOURCES) + set(multiValueArgs SOURCES LIBRARIES DEFINITIONS) + cmake_parse_arguments(TEST "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + set(TEST_NAME ${name}) - if( ECM_FOUND AND BUILD_TESTING ) + if(ECM_FOUND AND BUILD_TESTING) ecm_add_test( ${TEST_SOURCES} ${TEST_RESOURCES} TEST_NAME @@ -40,15 +38,18 @@ function( calamares_add_test ) ${TEST_LIBRARIES} Qt5::Core Qt5::Test - ) + ) calamares_automoc( ${TEST_NAME} ) # We specifically pass in the source directory of the test-being- # compiled, so that it can find test-files in that source dir. - target_compile_definitions( ${TEST_NAME} PRIVATE -DBUILD_AS_TEST="${CMAKE_CURRENT_SOURCE_DIR}" ${TEST_DEFINITIONS} ) - if( TEST_GUI ) - target_link_libraries( ${TEST_NAME} Calamares::calamaresui Qt5::Gui ) + target_compile_definitions( + ${TEST_NAME} + PRIVATE -DBUILD_AS_TEST="${CMAKE_CURRENT_SOURCE_DIR}" ${TEST_DEFINITIONS} + ) + if(TEST_GUI) + target_link_libraries(${TEST_NAME} Calamares::calamaresui Qt5::Gui) endif() - if( TEST_RESOURCES ) + if(TEST_RESOURCES) calamares_autorcc( ${TEST_NAME} ${TEST_RESOURCES} ) endif() endif() diff --git a/CMakeModules/FindPythonQt.cmake b/CMakeModules/FindPythonQt.cmake deleted file mode 100644 index 81208a86e..000000000 --- a/CMakeModules/FindPythonQt.cmake +++ /dev/null @@ -1,185 +0,0 @@ -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2016 Teo Mrnjavac -# SPDX-FileCopyrightText: 2017 Adriaan de Groot -# SPDX-License-Identifier: BSD-2-Clause -# -### -# -# Find PythonQt -# -# Sets PYTHONQT_FOUND, PYTHONQT_INCLUDE_DIR, PYTHONQT_LIBRARY, PYTHONQT_LIBRARIES -# -# Also sets PYTHONQT_INCLUDE_DIRS to add whatever directories -# that are needed for extensions. -# - -# Python is required -find_package(PythonLibs) -if(NOT PYTHONLIBS_FOUND) - message(FATAL_ERROR "error: Python is required to build PythonQt") -endif() - -# Cut X.Y[.Z] down to just X.Y -string(REGEX REPLACE - "^([0-9][0-9]*)\.([0-9][0-9]*)" - "\\1.\\2@" - _PYTHONLIBS_MAJMIN - ${PYTHONLIBS_VERSION_STRING} -) -string(REGEX REPLACE - "@.*" - "" - PYTHONLIBS_MAJMIN - ${_PYTHONLIBS_MAJMIN} -) - -if(NOT EXISTS "${PYTHONQT_INSTALL_DIR}") - find_path(PYTHONQT_INSTALL_DIR - NAMES - include/PythonQt/PythonQt.h - include/PythonQt5/PythonQt.h - DOC "Directory where PythonQt was installed.") -endif() - -# XXX Since PythonQt 3.0 is not yet cmakeified, depending -# on how PythonQt is built, headers will not always be -# installed in "include/PythonQt". That is why "src" -# is added as an option. See [1] for more details. -# [1] https://github.com/commontk/CTK/pull/538#issuecomment-86106367 -find_path(PYTHONQT_INCLUDE_DIR PythonQt.h - PATHS - "${PYTHONQT_INSTALL_DIR}/include/PythonQt" - "${PYTHONQT_INSTALL_DIR}/include/PythonQt5" - "${PYTHONQT_INSTALL_DIR}/src" - DOC "Path to the PythonQt include directory") -find_path(PYTHONQT_ALL_INCLUDE_DIR PythonQt_QtAll.h - PATHS - "${PYTHONQT_INCLUDE_DIR}" - "${PYTHONQT_INSTALL_DIR}" - PATH_SUFFIXES - "extensions/PythonQt_QtAll" - "src" - DOC "Path to the PythonQt 'all' header") - -if ( NOT PythonQt_FIND_QUIETLY ) - message( STATUS "Searching for PythonQt (PythonLibs ${PYTHONLIBS_MAJMIN}) .." ) - if ( PYTHONQT_INCLUDE_DIR ) - message( STATUS " .. found include ${PYTHONQT_INCLUDE_DIR}" ) - message( STATUS " .. found all include ${PYTHONQT_ALL_INCLUDE_DIR}" ) - endif() -endif() - -# Minimum v3.1 is needed -find_library(PYTHONQT_LIBRARY_RELEASE - NAMES - PythonQt-Qt5-Python${PYTHONLIBS_MAJMIN} - PythonQt-Qt5-Python3 - PythonQt - PATHS "${PYTHONQT_INSTALL_DIR}/lib" - DOC "The PythonQt library." -) -find_library(PYTHONQT_LIBRARY_DEBUG - NAMES - PythonQt-Qt5-Python${PYTHONLIBS_MAJMIN}JMIN${CTK_CMAKE_DEBUG_POSTFIX} - PythonQt-Qt5-Python${PYTHONLIBS_MAJMIN}${CMAKE_DEBUG_POSTFIX} - PythonQt-Qt5-Python${PYTHONLIBS_MAJMIN} - PythonQt-Qt5-Python3${CTK_CMAKE_DEBUG_POSTFIX} - PythonQt-Qt5-Python3${CMAKE_DEBUG_POSTFIX} - PythonQt-Qt5-Python3 - PythonQt${CTK_CMAKE_DEBUG_POSTFIX} - PythonQt${CMAKE_DEBUG_POSTFIX} - PythonQt - PATHS "${PYTHONQT_INSTALL_DIR}/lib" - DOC "The PythonQt library (debug build)." -) -find_library(PYTHONQT_QTALL_LIBRARY_RELEASE - NAMES - PythonQt_QtAll-Qt5-Python${PYTHONLIBS_MAJMIN} - PythonQt_QtAll-Qt5-Python3 - PythonQt_QtAll - PATHS "${PYTHONQT_INSTALL_DIR}/lib" - DOC "Full Qt bindings for the PythonQt library." -) -find_library(PYTHONQT_QTALL_LIBRARY_DEBUG - NAMES - PythonQt_QtAll-Qt5-Python${PYTHONLIBS_MAJMIN}${CTK_CMAKE_DEBUG_POSTFIX} - PythonQt_QtAll-Qt5-Python${PYTHONLIBS_MAJMIN}${CMAKE_DEBUG_POSTFIX} - PythonQt_QtAll-Qt5-Python${PYTHONLIBS_MAJMIN} - PythonQt_QtAll-Qt5-Python3${CTK_CMAKE_DEBUG_POSTFIX} - PythonQt_QtAll-Qt5-Python3${CMAKE_DEBUG_POSTFIX} - PythonQt_QtAll-Qt5-Python3 - PythonQt_QtAll${CTK_CMAKE_DEBUG_POSTFIX} - PythonQt_QtAll${CMAKE_DEBUG_POSTFIX} - PythonQt_QtAll - PATHS "${PYTHONQT_INSTALL_DIR}/lib" - DOC "Full Qt bindings for the PythonQt library (debug build)." -) - -set(PYTHONQT_LIBRARY) -if(PYTHONQT_LIBRARY_RELEASE) - list(APPEND PYTHONQT_LIBRARY optimized ${PYTHONQT_LIBRARY_RELEASE}) -endif() -if(PYTHONQT_LIBRARY_DEBUG) - list(APPEND PYTHONQT_LIBRARY debug ${PYTHONQT_LIBRARY_DEBUG}) -endif() - -set(PYTHONQT_QTALL_LIBRARY) -if(PYTHONQT_QTALL_LIBRARY_RELEASE) - list(APPEND PYTHONQT_QTALL_LIBRARY optimized ${PYTHONQT_QTALL_LIBRARY_RELEASE}) -endif() -if(PYTHONQT_QTALL_LIBRARY_DEBUG) - list(APPEND PYTHONQT_QTALL_LIBRARY debug ${PYTHONQT_QTALL_LIBRARY_DEBUG}) -endif() - -if ( NOT PythonQt_FIND_QUIETLY ) - if ( PYTHONQT_LIBRARY ) - message( STATUS " .. found library ${PYTHONQT_LIBRARY}" ) - endif() - if ( PYTHONQT_QTALL_LIBRARY ) - message( STATUS " .. found qtall ${PYTHONQT_QTALL_LIBRARY}" ) - endif() -endif() - - -mark_as_advanced(PYTHONQT_INSTALL_DIR) -mark_as_advanced(PYTHONQT_INCLUDE_DIR) -mark_as_advanced(PYTHONQT_LIBRARY_RELEASE) -mark_as_advanced(PYTHONQT_LIBRARY_DEBUG) -mark_as_advanced(PYTHONQT_QTALL_LIBRARY_RELEASE) -mark_as_advanced(PYTHONQT_QTALL_LIBRARY_DEBUG) - -# On linux, also find libutil -if(UNIX AND NOT APPLE) - find_library(PYTHONQT_LIBUTIL util) - mark_as_advanced(PYTHONQT_LIBUTIL) -endif() - -# All upper case _FOUND variable is maintained for backwards compatibility. -set(PYTHONQT_FOUND 0) -set(PythonQt_FOUND 0) - -if(PYTHONQT_INCLUDE_DIR AND PYTHONQT_LIBRARY AND PYTHONQT_QTALL_LIBRARY) - # Currently CMake'ified PythonQt only supports building against a python Release build. - # This applies independently of CTK build type (Release, Debug, ...) - add_definitions(-DPYTHONQT_USE_RELEASE_PYTHON_FALLBACK) - set(PYTHONQT_FOUND 1) - set(PythonQt_FOUND ${PYTHONQT_FOUND}) - set(PYTHONQT_LIBRARIES ${PYTHONQT_LIBRARY} ${PYTHONQT_LIBUTIL} ${PYTHONQT_QTALL_LIBRARY}) - set(PYTHONQT_INCLUDE_DIRS ${PYTHONQT_INCLUDE_DIR}) - if(PYTHONQT_ALL_INCLUDE_DIR) - list(APPEND PYTHONQT_INCLUDE_DIRS ${PYTHONQT_ALL_INCLUDE_DIR}) - endif() -elseif(NOT PythonQt_FIND_QUIETLY) - set(_missing "") - if (NOT PYTHONQT_INCLUDE_DIR) - list(APPEND _missing "includes") - endif() - if (NOT PYTHONQT_LIBRARY) - list(APPEND _missing "library") - endif() - if (NOT PYTHONQT_QTALL_LIBRARY) - list(APPEND _missing "qtall") - endif() - message(STATUS "PythonQt not found, missing components ${_missing}") -endif() diff --git a/CMakeModules/KPMcoreHelper.cmake b/CMakeModules/KPMcoreHelper.cmake index 6aacfc95c..05dff18dd 100644 --- a/CMakeModules/KPMcoreHelper.cmake +++ b/CMakeModules/KPMcoreHelper.cmake @@ -10,7 +10,7 @@ if ( NOT KPMcore_searched_for ) set( KPMcore_searched_for TRUE ) - find_package( KPMcore 3.3 ) + find_package( KPMcore 21.12.0 ) set_package_properties( KPMcore PROPERTIES URL "https://invent.kde.org/kde/kpmcore" @@ -21,18 +21,6 @@ if ( NOT KPMcore_searched_for ) if( KPMcore_FOUND ) set( KPMcore_API_DEFINITIONS "" ) - if( KPMcore_VERSION VERSION_GREATER "3.3.70" AND KPMcore_VERSION VERSION_LESS "4.0" ) - message( FATAL_ERROR "KPMCore beta versions ${KPMcore_VERSION} not supported" ) - endif() - if ( KPMcore_VERSION VERSION_GREATER "3.3.0") - list( APPEND KPMcore_API_DEFINITIONS WITH_KPMCORE331API) # kpmcore > 3.3.0 with deprecations - endif() - if ( KPMcore_VERSION VERSION_GREATER_EQUAL "4.0") - list( APPEND KPMcore_API_DEFINITIONS WITH_KPMCORE4API) # kpmcore 4 with new API - endif() - if( KPMcore_VERSION VERSION_GREATER_EQUAL "4.2" ) - list( APPEND KPMcore_API_DEFINITIONS WITH_KPMCORE42API) # kpmcore 4.2 with new API - endif() else() set( KPMcore_API_DEFINITIONS WITHOUT_KPMcore ) endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0be408ba0..0eaf4d00f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -77,16 +77,15 @@ instructions are on the wiki. ### Dependencies Main: -* Compiler with C++17 support: GCC >= 7 or Clang >= 5 -* CMake >= 3.3 -* Qt >= 5.9 +* Compiler with C++17 support +* CMake >= 3.16 +* Qt >= 5.15 * yaml-cpp >= 0.5.1 -* Python >= 3.3 (required for some modules) -* Boost.Python >= 1.55.0 (required for some modules) +* Python >= 3.6 (required for some modules) +* Boost.Python >= 1.67.0 (required for some modules) * KDE extra-cmake-modules >= 5.18 (recommended; required for some modules; required for some tests) * KDE Frameworks KCoreAddons (>= 5.58 recommended) -* PythonQt (optional, deprecated) Individual modules may have their own requirements; these are listed in CMake output. diff --git a/CalamaresConfig.cmake.in b/CalamaresConfig.cmake.in index 4fb9621ca..7b7f5aff9 100644 --- a/CalamaresConfig.cmake.in +++ b/CalamaresConfig.cmake.in @@ -87,5 +87,4 @@ include(CalamaresAddPlugin) # This list should match the one in libcalamares/CalamaresConfig.h, # which is the C++-language side of the same configuration. set(Calamares_WITH_PYTHON @WITH_PYTHON@) -set(Calamares_WITH_PYTHONQT @WITH_PYTHONQT@) set(Calamares_WITH_QML @WITH_QML@) diff --git a/LICENSES/LGPL-2.0-only.txt b/LICENSES/LGPL-2.0-only.txt deleted file mode 100644 index df942b1ff..000000000 --- a/LICENSES/LGPL-2.0-only.txt +++ /dev/null @@ -1,488 +0,0 @@ - - The KD Tools Library is Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. - - You may use, distribute and copy the KD Tools Library under the terms of - GNU Library General Public License version 2, which is displayed below. - -------------------------------------------------------------------------- - GNU LIBRARY GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1991 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the library GPL. It is - numbered 2 because it goes with version 2 of the ordinary GPL.] - - 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 Library General Public License, applies to some -specially designated Free Software Foundation software, and to any -other libraries whose authors decide to use it. You can use it for -your libraries, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if -you distribute copies of the 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 a program 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. - - Our method of protecting your rights has two steps: (1) copyright -the library, and (2) offer you this license which gives you legal -permission to copy, distribute and/or modify the library. - - Also, for each distributor's protection, we want to make certain -that everyone understands that there is no warranty for this free -library. If the library is modified by someone else and passed on, we -want its recipients to know that what they have is not the original -version, so that any problems introduced by others will not reflect on -the original authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that companies distributing free -software will individually obtain patent licenses, thus in effect -transforming the program into proprietary software. To prevent this, -we have made it clear that any patent must be licensed for everyone's -free use or not licensed at all. - - Most GNU software, including some libraries, is covered by the ordinary -GNU General Public License, which was designed for utility programs. This -license, the GNU Library General Public License, applies to certain -designated libraries. This license is quite different from the ordinary -one; be sure to read it in full, and don't assume that anything in it is -the same as in the ordinary license. - - The reason we have a separate public license for some libraries is that -they blur the distinction we usually make between modifying or adding to a -program and simply using it. Linking a program with a library, without -changing the library, is in some sense simply using the library, and is -analogous to running a utility program or application program. However, in -a textual and legal sense, the linked executable is a combined work, a -derivative of the original library, and the ordinary General Public License -treats it as such. - - Because of this blurred distinction, using the ordinary General -Public License for libraries did not effectively promote software -sharing, because most developers did not use the libraries. We -concluded that weaker conditions might promote sharing better. - - However, unrestricted linking of non-free programs would deprive the -users of those programs of all benefit from the free status of the -libraries themselves. This Library General Public License is intended to -permit developers of non-free programs to use free libraries, while -preserving your freedom as a user of such programs to change the free -libraries that are incorporated in them. (We have not seen how to achieve -this as regards changes in header files, but we have achieved it as regards -changes in the actual functions of the Library.) The hope is that this -will lead to faster development of free libraries. - - 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, while the latter only -works together with the library. - - Note that it is possible for a library to be covered by the ordinary -General Public License rather than by this special one. - - GNU LIBRARY GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library which -contains a notice placed by the copyright holder or other authorized -party saying it may be distributed under the terms of this Library -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 compile 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) 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. - - c) 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. - - d) 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 source code distributed need not include anything that is normally -distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - 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 to -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 Library 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 Library General Public - License as published by the Free Software Foundation; either - version 2 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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/ci/abicheck.sh b/ci/abicheck.sh new file mode 100755 index 000000000..6bf8f9b54 --- /dev/null +++ b/ci/abicheck.sh @@ -0,0 +1,73 @@ +#! /bin/sh +# +# SPDX-FileCopyrightText: 2021 Adriaan de Groot +# SPDX-License-Identifier: BSD-2-Clause +# +# Compares the ABI of the current working tree with the ABI +# from a base-version. Uses libabigail for the actual comparison. +# +# To use the tool, just run the script. It will build Calamares at +# least once, maybe twice (if it needs the base-version ABI information +# and hasn't cached it). + +# The base version can be a tag or git-hash; it will be checked-out +# in a worktree. +# +# Note that the hash here now is the very start of 3.3, when ABI +# compatibility was not expected yet at **all**. +BASE_VERSION=419be4df25bc6fcc1958cb6e44afc1b9e64fce71 + +### Build a tree and cache the ABI info into ci/ +# +# +do_build() { + LABEL=$1 + SOURCE_DIR=$2 + + BUILD_DIR=build-abi-$LABEL + rm -rf $BUILD_DIR + mkdir $BUILD_DIR + + if ( cd $BUILD_DIR && cmake $SOURCE_DIR -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-Og -g -gdwarf" -DCMAKE_C_FLAGS="-Og -g -gdwarf" && make -j12 ) > /dev/null 2>&1 + then + ls -1 $BUILD_DIR/libcalamares*.so.* + # Copy the un-versioned files; .so is a symlink to the just-built one + for lib in $BUILD_DIR/libcalamares*.so + do + cp $lib ci/`basename $lib`.$LABEL + done + else + echo "! failed to build $LABEL" + exit 1 + fi +} + +### Build current tree and get ABI info +# +# +do_build current `pwd -P` + +### Build ABI base version +# +# We cache this to save on some build time, if we are chasing a +# single branch from an unchanging base version. +# +if test -f ci/libcalamares.so.$BASE_VERSION +then + # The ABI version is cached, so we're good + : +else + git worktree remove --force tree-abi-$BASE_VERSION + git worktree add tree-abi-$BASE_VERSION $BASE_VERSION > /dev/null 2>&1 || { echo "! could not create worktree for $BASE_VERSION" ; exit 1 ; } + do_build $BASE_VERSION $( cd tree-abi-$BASE_VERSION && pwd -P ) +fi + +### Compare & Report +# +# abidiff compares the Application Binary Interfaces (ABI) of two +# shared libraries in ELF format. It emits a meaningful report describing +# the differences between the two ABIs. +# +# -l prints only the leaf changes, leaving out explanations of why. +# +abidiff -l ci/libcalamares.so.$BASE_VERSION ci/libcalamares.so.current diff --git a/ci/txstats.py b/ci/txstats.py index 69a34f89e..696a4b828 100755 --- a/ci/txstats.py +++ b/ci/txstats.py @@ -97,10 +97,12 @@ class EditingOutputter(object): lines = f.readlines() mark = None + mark_text = None for l in lines: # Note that we didn't strip the lines, so need the \n here if l.startswith("# Total ") and l.endswith(" languages\n"): mark = lines.index(l) + mark_text = l break if mark is None: raise TXError("No CMakeLists.txt lines for TX stats found") @@ -108,18 +110,17 @@ class EditingOutputter(object): nextmark = mark + 1 for l in lines[mark+1:]: - if l.startswith("set( _tx_"): - nextmark += 1 - continue - if l.startswith(" "): - nextmark += 1 - continue - break - if nextmark > mark + 12 or nextmark > len(lines) - 4: + nextmark += 1 + if l.startswith(mark_text): + break + if nextmark > mark + 100 or nextmark > len(lines) - 4: # Try to catch runaway nextmarks: we know there should # be four set-lines, which are unlikely to be 3 lines each; # similarly the CMakeLists.txt is supposed to end with # some boilerplate. + # + # However, gersemi will reformat to one-language-per-line, + # so we can get really long sections, that's why we use 100 as a limit. raise TXError("Could not find end of TX settings in CMakeLists.txt") self.post_lines = lines[nextmark:] @@ -185,7 +186,8 @@ def get_tx_stats(languages, outputter, verbose): ) all_langs = [] - outputter.print("# Total %d languages" % len(languages)) + mark_text = "# Total %d languages" % len(languages) + outputter.print(mark_text) for lang_name in languages: stats = languages[lang_name]["translated"]["percentage"] # Make the by-definition-incomplete languages have a percentage @@ -202,6 +204,7 @@ def get_tx_stats(languages, outputter, verbose): output_langs(all_langs, outputter, "good", lambda s : 1.0 > s >= 0.75) output_langs(all_langs, outputter, "ok", lambda s : 0.75 > s >= 0.05) output_langs(all_langs, outputter, "incomplete", lambda s : 0.05 > s) + outputter.print(mark_text) # Audit the languages that are in TX, mapped to git for lang_name in languages: diff --git a/lang/CMakeLists.txt b/lang/CMakeLists.txt index 72aae9588..7494692c6 100644 --- a/lang/CMakeLists.txt +++ b/lang/CMakeLists.txt @@ -13,15 +13,15 @@ # - defines an OBJECT LIBRARY calamares-i18n for linking the compiled # translations into an executable. -include( CalamaresAddTranslations ) +include(CalamaresAddTranslations) find_package(Qt5 COMPONENTS Xml) -if( Qt5Xml_FOUND ) +if(Qt5Xml_FOUND) add_executable(txload txload.cpp) target_link_libraries(txload Qt5::Xml) endif() -install_calamares_gettext_translations( python +install_calamares_gettext_translations(python SOURCE_DIR ${CMAKE_SOURCE_DIR}/lang/python FILENAME python.mo RENAME calamares-python.mo @@ -30,25 +30,25 @@ install_calamares_gettext_translations( python ### TRANSLATIONS # # -set( TS_FILES "" ) -set( calamares_i18n_qrc_content "" ) +set(TS_FILES "") +set(calamares_i18n_qrc_content "") # calamares and qt language files -foreach( lang ${CALAMARES_TRANSLATION_LANGUAGES} ) - foreach( tlsource "calamares_${lang}" "tz_${lang}" "kb_${lang}" ) - if( EXISTS "${CMAKE_SOURCE_DIR}/lang/${tlsource}.ts" ) - string( APPEND calamares_i18n_qrc_content "${tlsource}.qm\n" ) - list( APPEND TS_FILES "${CMAKE_SOURCE_DIR}/lang/${tlsource}.ts" ) +foreach(lang ${CALAMARES_TRANSLATION_LANGUAGES}) + foreach(tlsource "calamares_${lang}" "tz_${lang}" "kb_${lang}") + if(EXISTS "${CMAKE_SOURCE_DIR}/lang/${tlsource}.ts") + string(APPEND calamares_i18n_qrc_content "${tlsource}.qm\n") + list(APPEND TS_FILES "${CMAKE_SOURCE_DIR}/lang/${tlsource}.ts") endif() endforeach() endforeach() -set( trans_file calamares_i18n ) -set( trans_infile ${CMAKE_CURRENT_BINARY_DIR}/${trans_file}.qrc ) -set( trans_outfile ${CMAKE_CURRENT_BINARY_DIR}/calamares-i18n.cxx ) -set( CALAMARES_TRANSLATIONS_SOURCE ${trans_outfile} ) +set(trans_file calamares_i18n) +set(trans_infile ${CMAKE_CURRENT_BINARY_DIR}/${trans_file}.qrc) +set(trans_outfile ${CMAKE_CURRENT_BINARY_DIR}/calamares-i18n.cxx) +set(CALAMARES_TRANSLATIONS_SOURCE ${trans_outfile}) -configure_file( ${CMAKE_SOURCE_DIR}/lang/calamares_i18n.qrc.in ${trans_infile} @ONLY ) +configure_file(${CMAKE_SOURCE_DIR}/lang/calamares_i18n.qrc.in ${trans_infile} @ONLY) qt5_add_translation(QM_FILES ${TS_FILES}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5ce5349fb..b1a536f91 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,26 +3,26 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -include( CalamaresAddBrandingSubdirectory ) -include( CalamaresAddLibrary ) -include( CalamaresAddModuleSubdirectory ) -include( CalamaresAddPlugin ) -include( CalamaresAddTest ) -include( CalamaresAddTranslations ) +include(CalamaresAddBrandingSubdirectory) +include(CalamaresAddLibrary) +include(CalamaresAddModuleSubdirectory) +include(CalamaresAddPlugin) +include(CalamaresAddTest) +include(CalamaresAddTranslations) # library -add_subdirectory( libcalamares ) +add_subdirectory(libcalamares) -add_subdirectory( libcalamaresui ) +add_subdirectory(libcalamaresui) # all things qml -add_subdirectory( qml/calamares ) +add_subdirectory(qml/calamares) # application -add_subdirectory( calamares ) +add_subdirectory(calamares) # plugins -add_subdirectory( modules ) +add_subdirectory(modules) # branding components -add_subdirectory( branding ) +add_subdirectory(branding) diff --git a/src/branding/README.md b/src/branding/README.md index 234b2a9b1..318e2b6d9 100644 --- a/src/branding/README.md +++ b/src/branding/README.md @@ -204,3 +204,22 @@ Adding the subdirectory can be done as follows: to `.qm` files before being installed. The CMake macro's do this automatically. For manual packaging, use `lrelease` to compile the files. + +## Global Storage keys + +The following keys from the `branding.desc` file are copied into +Global Storage under a *branding* parent key: + "productName", + "version", + "shortVersion", + "versionedName", + "shortVersionedName", + "shortProductName", + "bootloaderEntryName", + "productUrl", + "supportUrl", + "knownIssuesUrl", + "releaseNotesUrl", + "donateUrl" + + diff --git a/src/calamares/CMakeLists.txt b/src/calamares/CMakeLists.txt index d06a53d83..b132f186a 100644 --- a/src/calamares/CMakeLists.txt +++ b/src/calamares/CMakeLists.txt @@ -4,29 +4,16 @@ # SPDX-License-Identifier: BSD-2-Clause # -set( calamaresSources +set(calamaresSources main.cpp CalamaresApplication.cpp CalamaresWindow.cpp - DebugWindow.cpp VariantModel.cpp - progresstree/ProgressTreeDelegate.cpp progresstree/ProgressTreeView.cpp ) -if( NOT WITH_KF5DBus ) - set( kdsagSources - ${CMAKE_SOURCE_DIR}/3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.cpp - ${CMAKE_SOURCE_DIR}/3rdparty/kdsingleapplicationguard/kdsharedmemorylocker.cpp - ${CMAKE_SOURCE_DIR}/3rdparty/kdsingleapplicationguard/kdtoolsglobal.cpp - ${CMAKE_SOURCE_DIR}/3rdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp - ) - mark_thirdparty_code( ${kdsagSources} ) - list( APPEND calamaresSources ${kdsagSources} ) -endif() - include_directories( ${CMAKE_SOURCE_DIR}/src/libcalamares ${CMAKE_SOURCE_DIR}/src/libcalamaresui @@ -42,45 +29,30 @@ include_directories( # The calamares-i18n.cxx file -- full path in CALAMARES_TRANSLATIONS_SOURCE -- # is created as a target in the lang/ directory. This is compiled to a # library (it's just the result of a QRC compile). -add_executable( calamares_bin ${calamaresSources} calamares.qrc ) -target_include_directories( calamares_bin PRIVATE ${CMAKE_SOURCE_DIR} ) -set_target_properties(calamares_bin - PROPERTIES - ENABLE_EXPORTS TRUE - RUNTIME_OUTPUT_NAME calamares -) +add_executable(calamares_bin ${calamaresSources} calamares.qrc) +target_include_directories(calamares_bin PRIVATE ${CMAKE_SOURCE_DIR}) +set_target_properties(calamares_bin PROPERTIES ENABLE_EXPORTS TRUE RUNTIME_OUTPUT_NAME calamares) calamares_automoc( calamares_bin ) calamares_autouic( calamares_bin ) calamares_autorcc( calamares_bin ) -if( kdsagSources ) - set_source_files_properties( ${kdsagSources} PROPERTIES AUTOMOC OFF ) +if(kdsagSources) + set_source_files_properties(${kdsagSources} PROPERTIES AUTOMOC OFF) endif() -target_link_libraries( calamares_bin - PRIVATE - calamares - calamaresui - calamares-i18n - Qt5::Core - Qt5::Widgets - KF5::CoreAddons +target_link_libraries( + calamares_bin + PRIVATE calamares calamaresui calamares-i18n Qt5::Core Qt5::Widgets KF5::CoreAddons KF5::DBusAddons ) -if( WITH_KF5Crash ) - target_link_libraries( calamares_bin PRIVATE KF5::Crash ) - target_compile_definitions( calamares_bin PRIVATE WITH_KF5Crash ) -endif() -if( WITH_KF5DBus ) - target_link_libraries( calamares_bin PRIVATE KF5::DBusAddons ) - target_compile_definitions( calamares_bin PRIVATE WITH_KF5DBus ) +if(BUILD_KF5Crash) + target_link_libraries(calamares_bin PRIVATE KF5::Crash) + target_compile_definitions(calamares_bin PRIVATE BUILD_KF5Crash) endif() -install( TARGETS calamares_bin - BUNDLE DESTINATION . - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} -) +install(TARGETS calamares_bin BUNDLE DESTINATION . RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) -install( FILES ${CMAKE_SOURCE_DIR}/data/images/squid.svg +install( + FILES ${CMAKE_SOURCE_DIR}/data/images/squid.svg RENAME calamares.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps ) @@ -88,11 +60,11 @@ install( FILES ${CMAKE_SOURCE_DIR}/data/images/squid.svg ### TESTS # # -if( BUILD_TESTING ) +if(BUILD_TESTING) # Don't install, these are just for enable_testing - add_executable( loadmodule testmain.cpp ) - target_link_libraries( loadmodule PRIVATE Qt5::Core Qt5::Widgets calamares calamaresui ) + add_executable(loadmodule testmain.cpp) + target_link_libraries(loadmodule PRIVATE Qt5::Core Qt5::Widgets calamares calamaresui) - add_executable( test_conf test_conf.cpp ) - target_link_libraries( test_conf PUBLIC yamlcpp::yamlcpp Qt5::Core ) + add_executable(test_conf test_conf.cpp) + target_link_libraries(test_conf PUBLIC yamlcpp::yamlcpp Qt5::Core) endif() diff --git a/src/calamares/DebugWindow.cpp b/src/calamares/DebugWindow.cpp index 13e8ccfdd..feeab833e 100644 --- a/src/calamares/DebugWindow.cpp +++ b/src/calamares/DebugWindow.cpp @@ -27,13 +27,6 @@ #include "utils/Retranslator.h" #include "widgets/TranslationFix.h" -#ifdef WITH_PYTHONQT -#include "ViewManager.h" -#include "viewpages/PythonQtViewStep.h" - -#include -#endif - #include #include #include @@ -120,80 +113,10 @@ DebugWindow::DebugWindow() m_ui->moduleConfigView->setModel( m_module_model.get() ); -#ifdef WITH_PYTHONQT - QPushButton* pythonConsoleButton = new QPushButton; - pythonConsoleButton->setText( "Attach Python console" ); - m_ui->modulesVerticalLayout->insertWidget( 1, pythonConsoleButton ); - pythonConsoleButton->hide(); - - QObject::connect( - pythonConsoleButton, - &QPushButton::clicked, - this, - [ this, moduleConfigModel ] - { - QString moduleName = m_ui->modulesListView->currentIndex().data().toString(); - Module* module = ModuleManager::instance()->moduleInstance( moduleName ); - if ( module->interface() != Module::Interface::PythonQt || module->type() != Module::Type::View ) - return; - - for ( ViewStep* step : ViewManager::instance()->viewSteps() ) - { - if ( step->moduleInstanceKey() == module->instanceKey() ) - { - PythonQtViewStep* pqvs = qobject_cast< PythonQtViewStep* >( step ); - if ( pqvs ) - { - QWidget* consoleWindow = new QWidget; - - QWidget* console = pqvs->createScriptingConsole(); - console->setParent( consoleWindow ); - - QVBoxLayout* layout = new QVBoxLayout; - consoleWindow->setLayout( layout ); - layout->addWidget( console ); - - QHBoxLayout* bottomLayout = new QHBoxLayout; - layout->addLayout( bottomLayout ); - - QLabel* bottomLabel = new QLabel( consoleWindow ); - bottomLayout->addWidget( bottomLabel ); - QString line = QString( "Module: %1
" - "Python class: %2" ) - .arg( module->instanceKey() ) - .arg( console->property( "classname" ).toString() ); - bottomLabel->setText( line ); - - QPushButton* closeButton = new QPushButton( consoleWindow ); - closeButton->setText( "&Close" ); - QObject::connect( - closeButton, &QPushButton::clicked, [ consoleWindow ] { consoleWindow->close(); } ); - bottomLayout->addWidget( closeButton ); - bottomLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); - - consoleWindow->setParent( this ); - consoleWindow->setWindowFlags( Qt::Window ); - consoleWindow->setWindowTitle( "Calamares Python console" ); - consoleWindow->setAttribute( Qt::WA_DeleteOnClose, true ); - consoleWindow->showNormal(); - break; - } - } - } - } ); - -#endif - connect( m_ui->modulesListView->selectionModel(), &QItemSelectionModel::selectionChanged, this, - [ this -#ifdef WITH_PYTHONQT - , - pythonConsoleButton -#endif - ] - { + [this] { QString moduleName = m_ui->modulesListView->currentIndex().data().toString(); Module* module = ModuleManager::instance()->moduleInstance( ModuleSystem::InstanceKey::fromString( moduleName ) ); @@ -204,10 +127,6 @@ DebugWindow::DebugWindow() m_ui->moduleConfigView->expandAll(); m_ui->moduleTypeLabel->setText( module->typeString() ); m_ui->moduleInterfaceLabel->setText( module->interfaceString() ); -#ifdef WITH_PYTHONQT - pythonConsoleButton->setVisible( module->interface() == Module::Interface::PythonQt - && module->type() == Module::Type::View ); -#endif } } ); diff --git a/src/calamares/DebugWindow.ui b/src/calamares/DebugWindow.ui index 1b163d49d..44ecf04ab 100644 --- a/src/calamares/DebugWindow.ui +++ b/src/calamares/DebugWindow.ui @@ -5,7 +5,7 @@ SPDX-FileCopyrightText: 2015 Teo Mrnjavac <teo@kde.org> SPDX-License-Identifier: GPL-3.0-or-later Calamares::DebugWindow - + 0 diff --git a/src/calamares/calamares-sidebar.qml b/src/calamares/calamares-sidebar.qml index e52cc14b8..46d2bd561 100644 --- a/src/calamares/calamares-sidebar.qml +++ b/src/calamares/calamares-sidebar.qml @@ -46,12 +46,12 @@ Rectangle { Layout.fillWidth: true; height: 35; radius: 6; - color: Branding.styleString( index == ViewManager.currentStepIndex ? Branding.SidebarBackgroundSelected : Branding.SidebarBackground ); + color: Branding.styleString( index == ViewManager.currentStepIndex ? Branding.SidebarBackgroundCurrent : Branding.SidebarBackground ); Text { anchors.verticalCenter: parent.verticalCenter; anchors.horizontalCenter: parent.horizontalCenter; - color: Branding.styleString( index == ViewManager.currentStepIndex ? Branding.SidebarTextSelected : Branding.SidebarText ); + color: Branding.styleString( index == ViewManager.currentStepIndex ? Branding.SidebarTextCurrent : Branding.SidebarText ); text: display; } } diff --git a/src/calamares/main.cpp b/src/calamares/main.cpp index de709156f..fcc946485 100644 --- a/src/calamares/main.cpp +++ b/src/calamares/main.cpp @@ -16,15 +16,9 @@ #include "utils/Logger.h" #include "utils/Retranslator.h" -#ifndef WITH_KF5DBus -#include "3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.h" -#endif - #include -#ifdef WITH_KF5DBus #include -#endif -#ifdef WITH_KF5Crash +#ifdef BUILD_KF5Crash #include #endif @@ -123,37 +117,16 @@ main( int argc, char* argv[] ) KAboutData::setApplicationData( aboutData ); a.setApplicationDisplayName( QString() ); // To avoid putting an extra "Calamares/" into the log-file -#ifdef WITH_KF5Crash +#ifdef BUILD_KF5Crash KCrash::initialize(); // KCrash::setCrashHandler(); KCrash::setDrKonqiEnabled( true ); KCrash::setFlags( KCrash::SaferDialog | KCrash::AlwaysDirectly ); - // TODO: umount anything in /tmp/calamares-... as an emergency save function #endif bool is_debug = handle_args( a ); -#ifdef WITH_KF5DBus KDBusService service( is_debug ? KDBusService::Multiple : KDBusService::Unique ); -#else - KDSingleApplicationGuard guard( is_debug ? KDSingleApplicationGuard::NoPolicy - : KDSingleApplicationGuard::AutoKillOtherInstances ); - if ( !is_debug && !guard.isPrimaryInstance() ) - { - // Here we have not yet set-up the logger system, so qDebug() is ok - auto instancelist = guard.instances(); - qDebug() << "Calamares is already running, shutting down."; - if ( instancelist.count() > 0 ) - { - qDebug() << "Other running Calamares instances:"; - } - for ( const auto& i : instancelist ) - { - qDebug() << " " << i.isValid() << i.pid() << i.arguments(); - } - return 69; // EX_UNAVAILABLE on FreeBSD - } -#endif Calamares::Settings::init( is_debug ); if ( !Calamares::Settings::instance() || !Calamares::Settings::instance()->isValid() ) diff --git a/src/calamares/progresstree/ProgressTreeDelegate.cpp b/src/calamares/progresstree/ProgressTreeDelegate.cpp index 48b5b4328..2117a28ae 100644 --- a/src/calamares/progresstree/ProgressTreeDelegate.cpp +++ b/src/calamares/progresstree/ProgressTreeDelegate.cpp @@ -25,50 +25,8 @@ item_fontsize() return CalamaresUtils::defaultFontSize() + 4; } -QSize -ProgressTreeDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const -{ - if ( !index.isValid() ) - { - return option.rect.size(); - } - - QFont font = qApp->font(); - - font.setPointSize( item_fontsize() ); - QFontMetrics fm( font ); - int height = fm.height(); - - height += 2 * item_margin; - - return QSize( option.rect.width(), height ); -} - - -void -ProgressTreeDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const -{ - QStyleOptionViewItem opt = option; - - painter->save(); - - initStyleOption( &opt, index ); - opt.text.clear(); - - painter->setBrush( - QColor( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarBackground ) ) ); - painter->setPen( QColor( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarText ) ) ); - - paintViewStep( painter, opt, index ); - - painter->restore(); -} - - -void -ProgressTreeDelegate::paintViewStep( QPainter* painter, - const QStyleOptionViewItem& option, - const QModelIndex& index ) const +static void +paintViewStep( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) { QRect textRect = option.rect.adjusted( item_margin, item_margin, -item_margin, -item_margin ); QFont font = qApp->font(); @@ -78,9 +36,9 @@ ProgressTreeDelegate::paintViewStep( QPainter* painter, if ( index.row() == index.data( Calamares::ViewManager::ProgressTreeItemCurrentIndex ).toInt() ) { - painter->setPen( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarTextSelect ) ); + painter->setPen( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarTextCurrent ) ); QString textHighlight - = Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarTextHighlight ); + = Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarBackgroundCurrent ); if ( textHighlight.isEmpty() ) { painter->setBrush( CalamaresApplication::instance()->mainWindow()->palette().window() ); @@ -122,3 +80,42 @@ ProgressTreeDelegate::paintViewStep( QPainter* painter, } } while ( shrinkSteps <= maximumShrink ); } + +QSize +ProgressTreeDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const +{ + if ( !index.isValid() ) + { + return option.rect.size(); + } + + QFont font = qApp->font(); + + font.setPointSize( item_fontsize() ); + QFontMetrics fm( font ); + int height = fm.height(); + + height += 2 * item_margin; + + return QSize( option.rect.width(), height ); +} + + +void +ProgressTreeDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const +{ + QStyleOptionViewItem opt = option; + + painter->save(); + + initStyleOption( &opt, index ); + opt.text.clear(); + + painter->setBrush( + QColor( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarBackground ) ) ); + painter->setPen( QColor( Calamares::Branding::instance()->styleString( Calamares::Branding::SidebarText ) ) ); + + paintViewStep( painter, opt, index ); + + painter->restore(); +} diff --git a/src/calamares/progresstree/ProgressTreeDelegate.h b/src/calamares/progresstree/ProgressTreeDelegate.h index 55dcf7ac4..d5a5abcbc 100644 --- a/src/calamares/progresstree/ProgressTreeDelegate.h +++ b/src/calamares/progresstree/ProgressTreeDelegate.h @@ -26,9 +26,6 @@ public: protected: QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const override; void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const override; - -private: - void paintViewStep( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const; }; #endif // PROGRESSTREEDELEGATE_H diff --git a/src/calamares/progresstree/ProgressTreeView.h b/src/calamares/progresstree/ProgressTreeView.h index 5c416dfd6..00decb6c3 100644 --- a/src/calamares/progresstree/ProgressTreeView.h +++ b/src/calamares/progresstree/ProgressTreeView.h @@ -14,8 +14,11 @@ #include /** - * @brief The ProgressTreeView class is a modified QTreeView which displays the + * @brief Displays progress through the list of (visible) steps + * + * The ProgressTreeView class is a modified QListView which displays the * available view steps and the user's progress through them. + * Since Calamares doesn't support "sub steps", it isn't really a tree. */ class ProgressTreeView : public QListView { diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index 95081bb5e..181ec2b30 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -10,20 +10,16 @@ # (non-GUI) jobs. # -add_definitions( -DDLLEXPORT_PRO ) -include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ) +add_definitions(-DDLLEXPORT_PRO) +include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) -configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/CalamaresConfig.h.in - ${CMAKE_CURRENT_BINARY_DIR}/CalamaresConfig.h ) -configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/CalamaresVersion.h.in - ${CMAKE_CURRENT_BINARY_DIR}/CalamaresVersion.h ) -configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/CalamaresVersionX.h.in - ${CMAKE_CURRENT_BINARY_DIR}/CalamaresVersionX.h ) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CalamaresConfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/CalamaresConfig.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CalamaresVersion.h.in ${CMAKE_CURRENT_BINARY_DIR}/CalamaresVersion.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CalamaresVersionX.h.in ${CMAKE_CURRENT_BINARY_DIR}/CalamaresVersionX.h) -set( OPTIONAL_PRIVATE_LIBRARIES "" ) -set( OPTIONAL_PUBLIC_LIBRARIES "" ) - -set( libSources +add_library( + calamares + SHARED CalamaresAbout.cpp CppJob.cpp GlobalStorage.cpp @@ -32,13 +28,11 @@ set( libSources JobQueue.cpp ProcessJob.cpp Settings.cpp - # GeoIP services geoip/Interface.cpp geoip/GeoIPFixed.cpp geoip/GeoIPJSON.cpp geoip/Handler.cpp - # Locale-data service locale/Global.cpp locale/Lookup.cpp @@ -47,7 +41,6 @@ set( libSources locale/TranslatableString.cpp locale/Translation.cpp locale/TranslationsModel.cpp - # Modules modulesystem/Config.cpp modulesystem/Descriptor.cpp @@ -56,19 +49,15 @@ set( libSources modulesystem/Preset.cpp modulesystem/RequirementsChecker.cpp modulesystem/RequirementsModel.cpp - # Network service network/Manager.cpp - # Packages service packages/Globals.cpp - # Partition service partition/Global.cpp partition/Mount.cpp partition/PartitionSize.cpp partition/Sync.cpp - # Utility service utils/CalamaresUtilsSystem.cpp utils/CommandList.cpp @@ -80,248 +69,197 @@ set( libSources utils/Retranslator.cpp utils/Runner.cpp utils/String.cpp + utils/StringExpander.cpp utils/UMask.cpp utils/Variant.cpp utils/Yaml.cpp ) +set_target_properties( + calamares + PROPERTIES + VERSION ${CALAMARES_VERSION_SHORT} + SOVERSION ${CALAMARES_VERSION_SHORT} + INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_INSTALL_FULL_INCLUDEDIR}/libcalamares +) +target_link_libraries(calamares LINK_PUBLIC yamlcpp::yamlcpp Qt5::Core KF5::CoreAddons) + ### OPTIONAL Automount support (requires dbus) # # -if( Qt5DBus_FOUND) - list( APPEND libSources partition/AutoMount.cpp ) - list( APPEND OPTIONAL_PRIVATE_LIBRARIES Qt5::DBus ) +if(Qt5DBus_FOUND) + target_sources(calamares PRIVATE partition/AutoMount.cpp) + target_link_libraries(calamares PRIVATE Qt5::DBus) endif() ### OPTIONAL Python support # # -if( WITH_PYTHON ) - list( APPEND libSources - PythonHelper.cpp - PythonJob.cpp - PythonJobApi.cpp - ) - - include_directories(${PYTHON_INCLUDE_DIRS}) - link_directories(${PYTHON_LIBRARIES}) - - include_directories(${Boost_INCLUDE_DIRS}) - link_directories(${Boost_LIBRARY_DIRS}) - - list( APPEND OPTIONAL_PRIVATE_LIBRARIES - ${PYTHON_LIBRARIES} - ${Boost_LIBRARIES} - ) +if(WITH_PYTHON) + target_sources(calamares PRIVATE PythonHelper.cpp PythonJob.cpp PythonJobApi.cpp) + target_link_libraries(calamares PRIVATE Python::Python Boost::python) endif() ### OPTIONAL GeoIP XML support # # find_package(Qt5 COMPONENTS Xml) -if( Qt5Xml_FOUND ) - list( APPEND libSources geoip/GeoIPXML.cpp ) - list( APPEND OPTIONAL_PUBLIC_LIBRARIES Qt5::Network Qt5::Xml ) +if(Qt5Xml_FOUND) + target_sources(calamares PRIVATE geoip/GeoIPXML.cpp) + target_link_libraries(calamares PRIVATE Qt5::Network Qt5::Xml) endif() ### OPTIONAL KPMcore support # # -include( KPMcoreHelper ) +include(KPMcoreHelper) -if ( KPMcore_FOUND ) - find_package( Qt5 REQUIRED DBus ) # Needed for KPMCore - find_package( KF5 REQUIRED I18n WidgetsAddons ) # Needed for KPMCore +if(KPMcore_FOUND) + find_package(Qt5 REQUIRED DBus) # Needed for KPMCore + find_package(KF5 REQUIRED I18n WidgetsAddons) # Needed for KPMCore - foreach ( d ${KPMcore_API_DEFINITIONS} ) - add_definitions( -D${d} ) + foreach(d ${KPMcore_API_DEFINITIONS}) + add_definitions(-D${d}) endforeach() - include_directories( ${KPMCORE_INCLUDE_DIR} ) - list( APPEND libSources - partition/FileSystem.cpp - partition/KPMManager.cpp - partition/PartitionIterator.cpp - partition/PartitionQuery.cpp + include_directories(${KPMCORE_INCLUDE_DIR}) + target_sources( + calamares + PRIVATE + partition/FileSystem.cpp + partition/KPMManager.cpp + partition/PartitionIterator.cpp + partition/PartitionQuery.cpp ) - list( APPEND OPTIONAL_PRIVATE_LIBRARIES kpmcore ) + target_link_libraries(calamares PRIVATE kpmcore) endif() ### LIBRARY # # -add_library( calamares SHARED ${libSources} ) -set_target_properties( calamares - PROPERTIES - VERSION ${CALAMARES_VERSION_SHORT} - SOVERSION ${CALAMARES_VERSION_SHORT} - INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_INSTALL_FULL_INCLUDEDIR}/libcalamares -) calamares_automoc( calamares ) - -target_link_libraries( calamares - LINK_PRIVATE - ${OPTIONAL_PRIVATE_LIBRARIES} - LINK_PUBLIC - yamlcpp::yamlcpp - Qt5::Core - KF5::CoreAddons - ${OPTIONAL_PUBLIC_LIBRARIES} -) - add_library(Calamares::calamares ALIAS calamares) ### Installation # # -install( TARGETS calamares +install( + TARGETS calamares EXPORT Calamares - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME + DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY + DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE + DESTINATION ${CMAKE_INSTALL_LIBDIR} ) # Make symlink lib/calamares/libcalamares.so to lib/libcalamares.so.VERSION so # lib/calamares can be used as module path for the Python interpreter. -install( CODE " +install( + CODE + " file( MAKE_DIRECTORY \"\$ENV{DESTDIR}/${CMAKE_INSTALL_FULL_LIBDIR}/calamares\" ) execute_process( COMMAND \"${CMAKE_COMMAND}\" -E create_symlink ../libcalamares.so.${CALAMARES_VERSION_SHORT} libcalamares.so WORKING_DIRECTORY \"\$ENV{DESTDIR}/${CMAKE_INSTALL_FULL_LIBDIR}/calamares\" ) -") +" +) # Install header files -file( GLOB rootHeaders "*.h" ) +file(GLOB rootHeaders "*.h") install( - FILES - ${CMAKE_CURRENT_BINARY_DIR}/CalamaresConfig.h - ${CMAKE_CURRENT_BINARY_DIR}/CalamaresVersion.h - ${rootHeaders} + FILES ${CMAKE_CURRENT_BINARY_DIR}/CalamaresConfig.h ${CMAKE_CURRENT_BINARY_DIR}/CalamaresVersion.h ${rootHeaders} DESTINATION include/libcalamares ) # Install each subdir-worth of header files -foreach( subdir geoip locale modulesystem network partition utils ) - file( GLOB subdir_headers "${subdir}/*.h" ) - install( FILES ${subdir_headers} DESTINATION include/libcalamares/${subdir} ) +foreach(subdir geoip locale modulesystem network partition utils) + file(GLOB subdir_headers "${subdir}/*.h") + install(FILES ${subdir_headers} DESTINATION include/libcalamares/${subdir}) endforeach() - -### TESTING +### TRANSLATION TESTING # -# -calamares_add_test( - libcalamarestest - SOURCES - Tests.cpp -) +# This is a support function, used just once, to help out the localetest +function(calamares_qrc_translations basename) + set(NAME ${ARGV0}) + set(options "") + set(oneValueArgs SUBDIRECTORY OUTPUT_VARIABLE) + set(multiValueArgs LANGUAGES) + cmake_parse_arguments(_qrt "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) -calamares_add_test( - libcalamaresgeoiptest - SOURCES - geoip/GeoIPTests.cpp - ${geoip_src} -) - -function ( calamares_qrc_translations basename ) - set( NAME ${ARGV0} ) - set( options "" ) - set( oneValueArgs SUBDIRECTORY OUTPUT_VARIABLE ) - set( multiValueArgs LANGUAGES ) - cmake_parse_arguments( _qrt "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) - - if( NOT _qrt_OUTPUT_VARIABLE ) - set( _qrt_OUTPUT_VARIABLE "qrc_translations_${basename}" ) + if(NOT _qrt_OUTPUT_VARIABLE) + set(_qrt_OUTPUT_VARIABLE "qrc_translations_${basename}") endif() - set( translations_qrc_infile ${CMAKE_CURRENT_BINARY_DIR}/${basename}.qrc ) - set( translations_qrc_outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${basename}.cxx ) + set(translations_qrc_infile ${CMAKE_CURRENT_BINARY_DIR}/${basename}.qrc) + set(translations_qrc_outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${basename}.cxx) # Must use this variable name because of the @ substitution - set( calamares_i18n_qrc_content "" ) - set( calamares_i18n_ts_filelist "" ) - foreach( lang ${_qrt_LANGUAGES} ) - string( APPEND calamares_i18n_qrc_content "${basename}_${lang}.qm" ) - list( APPEND calamares_i18n_ts_filelist "${CMAKE_CURRENT_SOURCE_DIR}/${_qrt_SUBDIRECTORY}/${basename}_${lang}.ts" ) + set(calamares_i18n_qrc_content "") + set(calamares_i18n_ts_filelist "") + foreach(lang ${_qrt_LANGUAGES}) + string(APPEND calamares_i18n_qrc_content "${basename}_${lang}.qm") + list( + APPEND + calamares_i18n_ts_filelist + "${CMAKE_CURRENT_SOURCE_DIR}/${_qrt_SUBDIRECTORY}/${basename}_${lang}.ts" + ) endforeach() - configure_file( ${CMAKE_SOURCE_DIR}/lang/calamares_i18n.qrc.in ${translations_qrc_infile} @ONLY ) + configure_file(${CMAKE_SOURCE_DIR}/lang/calamares_i18n.qrc.in ${translations_qrc_infile} @ONLY) qt5_add_translation(QM_FILES ${calamares_i18n_ts_filelist}) # Run the resource compiler (rcc_options should already be set) add_custom_command( OUTPUT ${translations_qrc_outfile} COMMAND "${Qt5Core_RCC_EXECUTABLE}" - ARGS ${rcc_options} --format-version 1 -name ${basename} -o ${translations_qrc_outfile} ${translations_qrc_infile} + ARGS + ${rcc_options} + --format-version + 1 + -name + ${basename} + -o + ${translations_qrc_outfile} + ${translations_qrc_infile} MAIN_DEPENDENCY ${translations_qrc_infile} DEPENDS ${QM_FILES} ) - set( ${_qrt_OUTPUT_VARIABLE} ${translations_qrc_outfile} PARENT_SCOPE ) + set(${_qrt_OUTPUT_VARIABLE} ${translations_qrc_outfile} PARENT_SCOPE) endfunction() calamares_qrc_translations( localetest OUTPUT_VARIABLE localetest_qrc SUBDIRECTORY testdata LANGUAGES nl ) -calamares_add_test( - libcalamareslocaletest - SOURCES - locale/Tests.cpp - ${localetest_qrc} -) -calamares_add_test( - libcalamaresmodulesystemtest - SOURCES - modulesystem/Tests.cpp -) +### TESTING +# +# +calamares_add_test(libcalamarestest SOURCES Tests.cpp) -calamares_add_test( - libcalamaresnetworktest - SOURCES - network/Tests.cpp -) +calamares_add_test(libcalamaresgeoiptest SOURCES geoip/GeoIPTests.cpp ${geoip_src}) -calamares_add_test( - libcalamarespackagestest - SOURCES - packages/Tests.cpp -) +calamares_add_test(libcalamareslocaletest SOURCES locale/Tests.cpp ${localetest_qrc}) -calamares_add_test( - libcalamarespartitiontest - SOURCES - partition/Global.cpp - partition/Tests.cpp - LIBRARIES - ${OPTIONAL_PRIVATE_LIBRARIES} -) +calamares_add_test(libcalamaresmodulesystemtest SOURCES modulesystem/Tests.cpp) -if( KPMcore_FOUND ) - calamares_add_test( - libcalamarespartitionkpmtest - SOURCES - partition/KPMTests.cpp - LIBRARIES - ${OPTIONAL_PRIVATE_LIBRARIES} - ) +calamares_add_test(libcalamaresnetworktest SOURCES network/Tests.cpp) + +calamares_add_test(libcalamarespackagestest SOURCES packages/Tests.cpp) + +if(KPMcore_FOUND) + calamares_add_test(libcalamarespartitiontest SOURCES partition/Global.cpp partition/Tests.cpp LIBRARIES kpmcore) + calamares_add_test(libcalamarespartitionkpmtest SOURCES partition/KPMTests.cpp LIBRARIES kpmcore) endif() -calamares_add_test( - libcalamaresutilstest - SOURCES - utils/Tests.cpp - utils/Runner.cpp -) - -calamares_add_test( - libcalamaresutilspathstest - SOURCES - utils/TestPaths.cpp -) +calamares_add_test(libcalamaresutilstest SOURCES utils/Tests.cpp utils/Runner.cpp) +calamares_add_test(libcalamaresutilspathstest SOURCES utils/TestPaths.cpp) # This is not an actual test, it's a test / demo application # for experimenting with GeoIP. -add_executable( test_geoip geoip/test_geoip.cpp ${geoip_src} ) -target_link_libraries( test_geoip Calamares::calamares Qt5::Network yamlcpp::yamlcpp ) +add_executable(test_geoip geoip/test_geoip.cpp ${geoip_src}) +target_link_libraries(test_geoip Calamares::calamares Qt5::Network yamlcpp::yamlcpp) calamares_automoc( test_geoip ) -if ( Qt5DBus_FOUND ) - add_executable( test_automount partition/calautomount.cpp ) - target_link_libraries( test_automount Calamares::calamares Qt5::DBus ) +if(Qt5DBus_FOUND) + add_executable(test_automount partition/calautomount.cpp) + target_link_libraries(test_automount Calamares::calamares Qt5::DBus) endif() diff --git a/src/libcalamares/CalamaresConfig.h.in b/src/libcalamares/CalamaresConfig.h.in index 3d551b8e8..23d4ebfd0 100644 --- a/src/libcalamares/CalamaresConfig.h.in +++ b/src/libcalamares/CalamaresConfig.h.in @@ -25,7 +25,6 @@ * which is the CMake-time side of the same configuration. */ #cmakedefine WITH_PYTHON -#cmakedefine WITH_PYTHONQT #cmakedefine WITH_QML #endif // CALAMARESCONFIG_H diff --git a/src/libcalamares/PythonJobApi.cpp b/src/libcalamares/PythonJobApi.cpp index 3532d8f32..753e222d1 100644 --- a/src/libcalamares/PythonJobApi.cpp +++ b/src/libcalamares/PythonJobApi.cpp @@ -262,7 +262,7 @@ host_env_process_output( const boost::python::list& args, std::string obscure( const std::string& string ) { - return CalamaresUtils::obscure( QString::fromStdString( string ) ).toStdString(); + return Calamares::String::obscure( QString::fromStdString( string ) ).toStdString(); } static QStringList diff --git a/src/libcalamares/modulesystem/Descriptor.cpp b/src/libcalamares/modulesystem/Descriptor.cpp index 52275b2f0..14fee0371 100644 --- a/src/libcalamares/modulesystem/Descriptor.cpp +++ b/src/libcalamares/modulesystem/Descriptor.cpp @@ -40,7 +40,6 @@ interfaceNames() { QStringLiteral("process"), Interface::Process }, { QStringLiteral("qtplugin"), Interface::QtPlugin }, { QStringLiteral("python"), Interface::Python }, - { QStringLiteral("pythonqt"), Interface::PythonQt } }; // *INDENT-ON* // clang-format on @@ -107,7 +106,6 @@ Descriptor::fromDescriptorData( const QVariantMap& moduleDesc, const QString& de consumedKeys << "load"; break; case Interface::Python: - case Interface::PythonQt: d.m_script = CalamaresUtils::getString( moduleDesc, "script" ); if ( d.m_script.isEmpty() ) { diff --git a/src/libcalamares/modulesystem/Descriptor.h b/src/libcalamares/modulesystem/Descriptor.h index fb1a66309..5b3681336 100644 --- a/src/libcalamares/modulesystem/Descriptor.h +++ b/src/libcalamares/modulesystem/Descriptor.h @@ -42,7 +42,6 @@ enum class Interface QtPlugin, // Jobs or Views Python, // Jobs only Process, // Deprecated interface - PythonQt // Views only, available as enum even if PythonQt isn't used }; const NamedEnumTable< Interface >& interfaceNames(); @@ -114,7 +113,7 @@ public: */ QString script() const { - return ( m_interface == Interface::Python || m_interface == Interface::PythonQt ) ? m_script : QString(); + return m_interface == Interface::Python ? m_script : QString(); } private: diff --git a/src/libcalamares/modulesystem/RequirementsChecker.cpp b/src/libcalamares/modulesystem/RequirementsChecker.cpp index 3d3e16172..b5bd91b36 100644 --- a/src/libcalamares/modulesystem/RequirementsChecker.cpp +++ b/src/libcalamares/modulesystem/RequirementsChecker.cpp @@ -43,7 +43,7 @@ RequirementsChecker::run() { m_progressTimer = new QTimer( this ); connect( m_progressTimer, &QTimer::timeout, this, &RequirementsChecker::reportProgress ); - m_progressTimer->start( 1200 ); // msec + m_progressTimer->start( std::chrono::milliseconds( 1200 ) ); for ( const auto& module : m_modules ) { @@ -76,7 +76,7 @@ RequirementsChecker::finished() } m_model->describe(); - m_model->changeRequirementsList(); + m_model->reCheckList(); QTimer::singleShot( 0, this, &RequirementsChecker::done ); } } diff --git a/src/libcalamares/modulesystem/RequirementsModel.cpp b/src/libcalamares/modulesystem/RequirementsModel.cpp index 3a0c85ccd..b9a091014 100644 --- a/src/libcalamares/modulesystem/RequirementsModel.cpp +++ b/src/libcalamares/modulesystem/RequirementsModel.cpp @@ -16,17 +16,41 @@ namespace Calamares { void -RequirementsModel::addRequirementsList( const Calamares::RequirementsList& requirements ) +RequirementsModel::clear() { QMutexLocker l( &m_addLock ); beginResetModel(); - m_requirements.append( requirements ); - changeRequirementsList(); + m_requirements.clear(); endResetModel(); + reCheckList(); } void -RequirementsModel::changeRequirementsList() +RequirementsModel::addRequirementsList( const Calamares::RequirementsList& requirements ) +{ + QMutexLocker l( &m_addLock ); + + beginResetModel(); + for ( const auto& r : requirements ) + { + auto it = std::find_if( m_requirements.begin(), + m_requirements.end(), + [ &r ]( const Calamares::RequirementEntry& re ) { return r.name == re.name; } ); + if ( it != m_requirements.end() ) + { + *it = r; + } + else + { + m_requirements.append( r ); + } + } + endResetModel(); + reCheckList(); +} + +void +RequirementsModel::reCheckList() { auto isUnSatisfied = []( const Calamares::RequirementEntry& e ) { return !e.satisfied; }; auto isMandatoryAndUnSatisfied = []( const Calamares::RequirementEntry& e ) { return e.mandatory && !e.satisfied; }; @@ -34,8 +58,8 @@ RequirementsModel::changeRequirementsList() m_satisfiedRequirements = std::none_of( m_requirements.begin(), m_requirements.end(), isUnSatisfied ); m_satisfiedMandatory = std::none_of( m_requirements.begin(), m_requirements.end(), isMandatoryAndUnSatisfied ); - emit satisfiedRequirementsChanged( m_satisfiedRequirements ); - emit satisfiedMandatoryChanged( m_satisfiedMandatory ); + Q_EMIT satisfiedRequirementsChanged( m_satisfiedRequirements ); + Q_EMIT satisfiedMandatoryChanged( m_satisfiedMandatory ); } int @@ -98,7 +122,7 @@ void RequirementsModel::setProgressMessage( const QString& m ) { m_progressMessage = m; - emit progressMessageChanged( m_progressMessage ); + Q_EMIT progressMessageChanged( m_progressMessage ); } } // namespace Calamares diff --git a/src/libcalamares/modulesystem/RequirementsModel.h b/src/libcalamares/modulesystem/RequirementsModel.h index 5f3e13cbb..bd71ce81f 100644 --- a/src/libcalamares/modulesystem/RequirementsModel.h +++ b/src/libcalamares/modulesystem/RequirementsModel.h @@ -33,8 +33,6 @@ class RequirementsChecker; */ class DLLEXPORT RequirementsModel : public QAbstractListModel { - friend class RequirementsChecker; - Q_OBJECT Q_PROPERTY( bool satisfiedRequirements READ satisfiedRequirements NOTIFY satisfiedRequirementsChanged FINAL ) Q_PROPERTY( bool satisfiedMandatory READ satisfiedMandatory NOTIFY satisfiedMandatoryChanged FINAL ) @@ -45,11 +43,11 @@ public: enum Roles : short { - Name, + NegatedText = Qt::DisplayRole, + Details = Qt::ToolTipRole, + Name = Qt::UserRole, Satisfied, Mandatory, - Details, - NegatedText, HasDetails }; // No Q_ENUM because these are exposed through roleNames() @@ -69,6 +67,15 @@ public: ///@brief Debugging tool, describe the checking-state void describe() const; + ///@brief Update progress message (called by the checker) + void setProgressMessage( const QString& m ); + + ///@brief Append some requirements; resets the model + void addRequirementsList( const Calamares::RequirementsList& requirements ); + + ///@brief Check the whole list, emit signals satisfied...() + void reCheckList(); + signals: void satisfiedRequirementsChanged( bool value ); void satisfiedMandatoryChanged( bool value ); @@ -77,16 +84,10 @@ signals: protected: QHash< int, QByteArray > roleNames() const override; - ///@brief Append some requirements; resets the model - void addRequirementsList( const Calamares::RequirementsList& requirements ); - - ///@brief Update progress message (called by the checker) - void setProgressMessage( const QString& m ); + ///@brief Clears the requirements; resets the model + void clear(); private: - ///@brief Implementation for {set,add}RequirementsList - void changeRequirementsList(); - QString m_progressMessage; QMutex m_addLock; RequirementsList m_requirements; diff --git a/src/libcalamares/network/Manager.cpp b/src/libcalamares/network/Manager.cpp index 6cb270ecd..536474b2b 100644 --- a/src/libcalamares/network/Manager.cpp +++ b/src/libcalamares/network/Manager.cpp @@ -29,16 +29,11 @@ namespace Network void RequestOptions::applyToRequest( QNetworkRequest* request ) const { -#if QT_VERSION < QT_VERSION_CHECK( 5, 15, 0 ) - constexpr const auto RedirectPolicyAttribute = QNetworkRequest::FollowRedirectsAttribute; -#else - constexpr const auto RedirectPolicyAttribute = QNetworkRequest::RedirectPolicyAttribute; -#endif if ( m_flags & Flag::FollowRedirect ) { // Follows all redirects except unsafe ones (https to http). - request->setAttribute( RedirectPolicyAttribute, true ); + request->setAttribute( QNetworkRequest::RedirectPolicyAttribute, true ); } if ( m_flags & Flag::FakeUserAgent ) diff --git a/src/libcalamares/partition/Global.h b/src/libcalamares/partition/Global.h index 733e2f69c..b76c74c58 100644 --- a/src/libcalamares/partition/Global.h +++ b/src/libcalamares/partition/Global.h @@ -17,13 +17,10 @@ #define PARTITION_GLOBAL_H #include "DllMacro.h" +#include "FileSystem.h" #include "JobQueue.h" -#ifdef WITH_KPMCORE4API -#include "FileSystem.h" - #include -#endif namespace CalamaresUtils { @@ -78,7 +75,6 @@ isFilesystemUsedGS( const QString& filesystemType ) return isFilesystemUsedGS( Calamares::JobQueue::instanceGlobalStorage(), filesystemType ); } -#ifdef WITH_KPMCORE4API /** @brief Mark a particular filesystem type as used (or not) * * See useFilesystemGS(const QString&, bool); this method uses the filesystem type @@ -100,7 +96,6 @@ isFilesystemUsedGS( FileSystem::Type filesystem ) return isFilesystemUsedGS( untranslatedFS( filesystem ) ); } -#endif } // namespace Partition } // namespace CalamaresUtils diff --git a/src/libcalamares/partition/KPMHelper.h b/src/libcalamares/partition/KPMHelper.h index f6007b119..e61c31956 100644 --- a/src/libcalamares/partition/KPMHelper.h +++ b/src/libcalamares/partition/KPMHelper.h @@ -25,6 +25,8 @@ #pragma clang diagnostic ignored "-Wdocumentation" #pragma clang diagnostic ignored "-Wsuggest-destructor-override" #pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override" +// Because of __lastType +#pragma clang diagnostic ignored "-Wreserved-identifier" #endif #include diff --git a/src/libcalamares/partition/KPMManager.cpp b/src/libcalamares/partition/KPMManager.cpp index 8031030b1..7220b6151 100644 --- a/src/libcalamares/partition/KPMManager.cpp +++ b/src/libcalamares/partition/KPMManager.cpp @@ -14,10 +14,7 @@ #include #include -#if defined( WITH_KPMCORE4API ) #include -#endif - #include @@ -30,7 +27,6 @@ class InternalManager { public: InternalManager(); - ~InternalManager(); }; static bool s_kpm_loaded = false; @@ -69,22 +65,6 @@ InternalManager::InternalManager() } } -InternalManager::~InternalManager() -{ -#if defined( WITH_KPMCORE4API ) && !defined( WITH_KPMCORE42API ) - cDebug() << "Cleaning up KPMCore backend .."; - - // From KPMcore 4.0 until KPMcore 4.2 we needed to stop - // the helper by hand. KPMcore 4.2 ported to polkit directly, - // which doesn't need a helper. - auto backend_p = CoreBackendManager::self()->backend(); - if ( backend_p ) - { - ExternalCommand::stopHelper(); - } -#endif -} - std::shared_ptr< InternalManager > getInternal() { diff --git a/src/libcalamares/partition/KPMTests.cpp b/src/libcalamares/partition/KPMTests.cpp index 3834b7913..2f828f772 100644 --- a/src/libcalamares/partition/KPMTests.cpp +++ b/src/libcalamares/partition/KPMTests.cpp @@ -57,18 +57,10 @@ KPMTests::testFlagNames() QCOMPARE( PartitionTable::flagName( static_cast< PartitionTable::Flag >( 1 ) ), QStringLiteral( "boot" ) ); -#ifdef WITH_KPMCORE4API // KPMCore 4 unifies the flags and handles them internally QCOMPARE( PartitionTable::flagName( PartitionTable::Flag::Boot ), QStringLiteral( "boot" ) ); QVERIFY( names.contains( QStringLiteral( "boot" ) ) ); QVERIFY( !names.contains( QStringLiteral( "esp" ) ) ); -#else - // KPMCore 3 has separate flags - QCOMPARE( PartitionTable::flagName( PartitionTable::FlagBoot ), QStringLiteral( "boot" ) ); - QCOMPARE( PartitionTable::flagName( PartitionTable::FlagEsp ), QStringLiteral( "esp" ) ); - QVERIFY( names.contains( QStringLiteral( "boot" ) ) ); - QVERIFY( names.contains( QStringLiteral( "esp" ) ) ); -#endif } void diff --git a/src/libcalamares/partition/PartitionQuery.cpp b/src/libcalamares/partition/PartitionQuery.cpp index 0356f920c..4d54215f3 100644 --- a/src/libcalamares/partition/PartitionQuery.cpp +++ b/src/libcalamares/partition/PartitionQuery.cpp @@ -50,12 +50,7 @@ isPartitionFreeSpace( const Partition* partition ) bool isPartitionNew( const Partition* partition ) { -#if defined( WITH_KPMCORE4API ) - constexpr auto NewState = Partition::State::New; -#else - constexpr auto NewState = Partition::StateNew; -#endif - return partition->state() == NewState; + return partition->state() == Partition::State::New; } diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 2d6bdde83..7622b006d 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -230,7 +230,7 @@ System::createTargetParentDirs( const QString& filePath ) const } -QPair< qint64, qreal > +QPair< quint64, qreal > System::getTotalMemoryB() const { #ifdef Q_OS_LINUX diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.h b/src/libcalamares/utils/CalamaresUtilsSystem.h index f7f04079e..f4f5257c4 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.h +++ b/src/libcalamares/utils/CalamaresUtilsSystem.h @@ -337,7 +337,7 @@ public: * * @return size, guesstimate-factor */ - DLLEXPORT QPair< qint64, qreal > getTotalMemoryB() const; + DLLEXPORT QPair< quint64, qreal > getTotalMemoryB() const; /** * @brief getCpuDescription returns a string describing the CPU. diff --git a/src/libcalamares/utils/CommandList.cpp b/src/libcalamares/utils/CommandList.cpp index 4652dcc5a..7e1f42d22 100644 --- a/src/libcalamares/utils/CommandList.cpp +++ b/src/libcalamares/utils/CommandList.cpp @@ -16,6 +16,7 @@ // #include "utils/CalamaresUtils.h" #include "utils/CalamaresUtilsSystem.h" #include "utils/Logger.h" +#include "utils/StringExpander.h" #include "utils/Variant.h" #include @@ -67,6 +68,48 @@ get_variant_stringlist( const QVariantList& l ) return retl; } +static Calamares::String::DictionaryExpander +get_gs_expander( System::RunLocation location ) +{ + Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); + + Calamares::String::DictionaryExpander expander; + + // Figure out the replacement for ${ROOT} + if ( location == System::RunLocation::RunInTarget ) + { + expander.insert( QStringLiteral( "ROOT" ), QStringLiteral( "/" ) ); + } + else if ( gs && gs->contains( "rootMountPoint" ) ) + { + expander.insert( QStringLiteral( "ROOT" ), gs->value( "rootMountPoint" ).toString() ); + } + + // Replacement for ${USER} + if ( gs && gs->contains( "username" ) ) + { + expander.insert( QStringLiteral( "USER" ), gs->value( "username" ).toString() ); + } + + return expander; +} + +CommandLine +CommandLine::expand( KMacroExpanderBase& expander ) const +{ + QString c = first; + expander.expandMacrosShellQuote( c ); + return { c, second }; +} + +CalamaresUtils::CommandLine +CommandLine::expand() const +{ + auto expander = get_gs_expander( System::RunLocation::RunInHost ); + return expand( expander ); +} + + CommandList::CommandList( bool doChroot, std::chrono::seconds timeout ) : m_doChroot( doChroot ) , m_timeout( timeout ) @@ -90,7 +133,7 @@ CommandList::CommandList::CommandList( const QVariant& v, bool doChroot, std::ch } else if ( v.type() == QVariant::String ) { - append( v.toString() ); + append( { v.toString(), m_timeout } ); } else if ( v.type() == QVariant::Map ) { @@ -107,61 +150,28 @@ CommandList::CommandList::CommandList( const QVariant& v, bool doChroot, std::ch } } -CommandList::~CommandList() {} - -static inline bool -findInCommands( const CommandList& l, const QString& needle ) -{ - for ( CommandList::const_iterator i = l.cbegin(); i != l.cend(); ++i ) - if ( i->command().contains( needle ) ) - { - return true; - } - return false; -} - Calamares::JobResult CommandList::run() { - QLatin1String rootMagic( "@@ROOT@@" ); - QLatin1String userMagic( "@@USER@@" ); - System::RunLocation location = m_doChroot ? System::RunLocation::RunInTarget : System::RunLocation::RunInHost; - /* Figure out the replacement for @@ROOT@@ */ - QString root = QStringLiteral( "/" ); - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - - bool needsRootSubstitution = findInCommands( *this, rootMagic ); - if ( needsRootSubstitution && ( location == System::RunLocation::RunInHost ) ) + auto expander = get_gs_expander( location ); + auto expandedList = expand( expander ); + if ( expander.hasErrors() ) { - if ( !gs || !gs->contains( "rootMountPoint" ) ) - { - cError() << "No rootMountPoint defined."; - return Calamares::JobResult::error( - QCoreApplication::translate( "CommandList", "Could not run command." ), - QCoreApplication::translate( "CommandList", - "The command runs in the host environment and needs to know the root " - "path, but no rootMountPoint is defined." ) ); - } - root = gs->value( "rootMountPoint" ).toString(); - } - - bool needsUserSubstitution = findInCommands( *this, userMagic ); - if ( needsUserSubstitution && ( !gs || !gs->contains( "username" ) ) ) - { - cError() << "No username defined."; + const auto missing = expander.errorNames(); + cError() << "Missing variables:" << missing; return Calamares::JobResult::error( QCoreApplication::translate( "CommandList", "Could not run command." ), QCoreApplication::translate( "CommandList", - "The command needs to know the user's name, but no username is defined." ) ); + "The commands use variables that are not defined. " + "Missing variables are: %1." ) + .arg( missing.join( ',' ) ) ); } - QString user = gs->value( "username" ).toString(); // may be blank if unset - for ( CommandList::const_iterator i = cbegin(); i != cend(); ++i ) + for ( CommandList::const_iterator i = expandedList.cbegin(); i != expandedList.cend(); ++i ) { QString processed_cmd = i->command(); - processed_cmd.replace( rootMagic, root ).replace( userMagic, user ); bool suppress_result = false; if ( processed_cmd.startsWith( '-' ) ) { @@ -191,10 +201,24 @@ CommandList::run() return Calamares::JobResult::ok(); } -void -CommandList::append( const QString& s ) +CommandList +CommandList::expand( KMacroExpanderBase& expander ) const { - append( CommandLine( s, m_timeout ) ); + // Copy and expand the list, collecting missing variables (so don't call expand()) + CommandList expandedList( m_doChroot, m_timeout ); + std::transform( cbegin(), + cend(), + std::back_inserter( expandedList ), + [ &expander ]( const CommandLine& c ) { return c.expand( expander ); } ); + return expandedList; } +CommandList +CommandList::expand() const +{ + auto expander = get_gs_expander( System::RunLocation::RunInHost ); + return expand( expander ); +} + + } // namespace CalamaresUtils diff --git a/src/libcalamares/utils/CommandList.h b/src/libcalamares/utils/CommandList.h index 432020a96..586b04ed3 100644 --- a/src/libcalamares/utils/CommandList.h +++ b/src/libcalamares/utils/CommandList.h @@ -18,6 +18,8 @@ #include +class KMacroExpanderBase; + namespace CalamaresUtils { @@ -50,6 +52,20 @@ struct CommandLine : public QPair< QString, std::chrono::seconds > std::chrono::seconds timeout() const { return second; } bool isValid() const { return !first.isEmpty(); } + + /** @brief Returns a copy of this one command, with variables expanded + * + * The given macro-expander is used to expand the command-line. + * This will normally be a Calamares::String::DictionaryExpander + * instance, which handles the ROOT and USER variables. + */ + CommandLine expand( KMacroExpanderBase& expander ) const; + /** @brief As above, with a default macro-expander. + * + * The default macro-expander assumes RunInHost (e.g. ROOT will + * expand to the RootMountPoint set in Global Storage). + */ + CommandLine expand() const; }; /** @brief Abbreviation, used internally. */ @@ -69,7 +85,6 @@ public: /** @brief empty command-list with timeout to apply to entries. */ CommandList( bool doChroot = true, std::chrono::seconds timeout = std::chrono::seconds( 10 ) ); CommandList( const QVariant& v, bool doChroot = true, std::chrono::seconds timeout = std::chrono::seconds( 10 ) ); - ~CommandList(); bool doChroot() const { return m_doChroot; } @@ -81,10 +96,21 @@ public: using CommandList_t::const_iterator; using CommandList_t::count; using CommandList_t::isEmpty; + using CommandList_t::push_back; + using CommandList_t::value_type; -protected: - using CommandList_t::append; - void append( const QString& ); + /** @brief Return a copy of this command-list, with variables expanded + * + * Each command-line in the list is expanded with the given @p expander. + * @see CommandLine::expand() for details. + */ + CommandList expand( KMacroExpanderBase& expander ) const; + /** @brief As above, with a default macro-expander. + * + * Each command-line in the list is expanded with that default macro-expander. + * @see CommandLine::expand() for details. + */ + CommandList expand() const; private: bool m_doChroot; diff --git a/src/libcalamares/utils/Logger.cpp b/src/libcalamares/utils/Logger.cpp index adb082687..10f7cad8c 100644 --- a/src/libcalamares/utils/Logger.cpp +++ b/src/libcalamares/utils/Logger.cpp @@ -53,7 +53,14 @@ setupLogLevel( unsigned int level ) { level = LOGVERBOSE; } - s_threshold = level + 1; // Comparison is < in log() function + s_threshold = level + 1; // Comparison is < in logLevelEnabled() function +} + +unsigned int +logLevel() +{ + // Undo the +1 in setupLogLevel() + return s_threshold > 0 ? s_threshold - 1 : 0; } bool @@ -62,33 +69,40 @@ logLevelEnabled( unsigned int level ) return level < s_threshold; } -unsigned int -logLevel() +/** @brief Should we call the log_implementation() function with this level? + * + * The implementation logs everything for which logLevelEnabled() is + * true to the file **and** to stdout; it logs everything at debug-level + * or below to the file regardless. + */ +static inline bool +log_enabled( unsigned int level ) { - return s_threshold > 0 ? s_threshold - 1 : 0; + return level <= LOGDEBUG || logLevelEnabled( level ); } static void -log( const char* msg, unsigned int debugLevel, bool withTime = true ) +log_implementation( const char* msg, unsigned int debugLevel, const bool withTime ) { + QMutexLocker lock( &s_mutex ); + + const auto date = QDate::currentDate().toString( Qt::ISODate ); + const auto time = QTime::currentTime().toString(); + + // If we don't format the date as a Qt::ISODate then we get a crash when + // logging at exit as Qt tries to use QLocale to format, but QLocale is + // on its way out. + logfile << date.toUtf8().data() << " - " << time.toUtf8().data() << " [" << debugLevel << "]: " << msg << std::endl; + + logfile.flush(); + if ( logLevelEnabled( debugLevel ) ) { - QMutexLocker lock( &s_mutex ); - - // If we don't format the date as a Qt::ISODate then we get a crash when - // logging at exit as Qt tries to use QLocale to format, but QLocale is - // on its way out. - logfile << QDate::currentDate().toString( Qt::ISODate ).toUtf8().data() << " - " - << QTime::currentTime().toString().toUtf8().data() << " [" - << QString::number( debugLevel ).toUtf8().data() << "]: " << msg << std::endl; - - logfile.flush(); - if ( withTime ) { - std::cout << QTime::currentTime().toString().toUtf8().data() << " [" - << QString::number( debugLevel ).toUtf8().data() << "]: "; + std::cout << time.toUtf8().data() << " [" << debugLevel << "]: "; } + // The endl is desired, since it also flushes (like the logfile, above) std::cout << msg << std::endl; } } @@ -97,29 +111,30 @@ log( const char* msg, unsigned int debugLevel, bool withTime = true ) static void CalamaresLogHandler( QtMsgType type, const QMessageLogContext&, const QString& msg ) { - static QMutex s_mutex; - - QByteArray ba = msg.toUtf8(); - const char* message = ba.constData(); - - QMutexLocker locker( &s_mutex ); - + unsigned int level = LOGVERBOSE; switch ( type ) { case QtInfoMsg: - log( message, LOGVERBOSE ); + level = LOGVERBOSE; break; case QtDebugMsg: - log( message, LOGDEBUG ); + level = LOGDEBUG; break; case QtWarningMsg: - log( message, LOGWARNING ); + level = LOGWARNING; break; case QtCriticalMsg: case QtFatalMsg: - log( message, LOGERROR ); + level = LOGERROR; break; } + + if ( !log_enabled( level ) ) + { + return; + } + + log_implementation( msg.toUtf8().constData(), level, true ); } @@ -188,14 +203,14 @@ CDebug::CDebug( unsigned int debugLevel, const char* func ) CDebug::~CDebug() { - if ( logLevelEnabled( m_debugLevel ) ) + if ( log_enabled( m_debugLevel ) ) { if ( m_funcinfo ) { m_msg.prepend( s_Continuation ); // Prepending, so back-to-front m_msg.prepend( m_funcinfo ); } - log( m_msg.toUtf8().data(), m_debugLevel, m_funcinfo ); + log_implementation( m_msg.toUtf8().data(), m_debugLevel, bool( m_funcinfo ) ); } } diff --git a/src/libcalamares/utils/PluginFactory.h b/src/libcalamares/utils/PluginFactory.h index a3371dd72..8e841f5e7 100644 --- a/src/libcalamares/utils/PluginFactory.h +++ b/src/libcalamares/utils/PluginFactory.h @@ -4,10 +4,6 @@ * SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot * SPDX-License-Identifier: GPL-3.0-or-later * - * Based on KPluginFactory from KCoreAddons, KDE project - * SPDX-FileCopyrightText: 2007 Matthias Kretz - * SPDX-FileCopyrightText: 2007 Bernhard Loos - * * Calamares is Free Software: see the License-Identifier above. * * @@ -16,81 +12,100 @@ #ifndef UTILS_PLUGINFACTORY_H #define UTILS_PLUGINFACTORY_H -#include +#include #define CalamaresPluginFactory_iid "io.calamares.PluginFactory" /** @brief Plugin factory for Calamares * - * Try to re-use KPluginFactory as much as possible (since the - * old code for PluginFactory was a fork of an old version of - * exactly that). + * A Calamares plugin contains just one kind of plugin -- either + * a job, or a viewstep -- so the factory is straightforward. + * It gets a single CreateInstanceFunction and calls that; + * the function is set when registerPlugin() is called in a subclass. * - * The current createInstance() method passes more arguments - * to the job and viewstep constructors than we want; chasing - * that change means modifying each Calamares module. This class - * implements a version of createInstance() with fewer arguments - * and overloads registerPlugin() to use that. */ -class CalamaresPluginFactory : public KPluginFactory +class CalamaresPluginFactory : public QObject { Q_OBJECT public: - explicit CalamaresPluginFactory() - : KPluginFactory() - { - } + explicit CalamaresPluginFactory() {} ~CalamaresPluginFactory() override; - /** @brief Create an object from the factory. - * - * Ignores all the @p args since they are not used. Calls - * Calamares constructors for the Jobs and ViewSteps. - */ - template < class impl, class ParentType > - static QObject* createInstance( QWidget* parentWidget, QObject* parent, const QVariantList& args ) + typedef QObject* ( *CreateInstanceFunction )( QObject* ); + + template < class T > + T* create( QObject* parent = nullptr ) { - Q_UNUSED( parentWidget ) - Q_UNUSED( args ) - ParentType* p = nullptr; - if ( parent ) + auto* op = fn ? fn( parent ) : nullptr; + if ( !op ) { - p = qobject_cast< ParentType* >( parent ); - Q_ASSERT( p ); + return nullptr; } - return new impl( p ); + T* tp = qobject_cast< T* >( op ); + if ( !tp ) + { + delete op; + } + return tp; } - /** @brief register a plugin - * - * The Calamares version doesn't accept keywords, and uses - * the Calamares createInstance() version which ignores - * the QVariantList of arguments. - */ - template < class T > - void registerPlugin() - { - KPluginFactory::registerPlugin< T >( QString(), &createInstance< T, QObject > ); - } +protected: + CreateInstanceFunction fn = nullptr; }; /** @brief declare a Calamares Plugin Factory * - * This would be defined as K_PLUGIN_FACTORY_DECLARATION_WITH_BASEFACTORY, - * except that does not actually use the base factory class that is - * passed in. + * There should be one declaration -- generally alongside the + * class definition for the Job or ViewStep that the plugin is + * going to provide, in the header -- and one definition -- in + * the corresponding implementation. */ #define CALAMARES_PLUGIN_FACTORY_DECLARATION( name ) \ class name : public CalamaresPluginFactory \ { \ Q_OBJECT \ - Q_INTERFACES( KPluginFactory ) \ + Q_INTERFACES( CalamaresPluginFactory ) \ Q_PLUGIN_METADATA( IID CalamaresPluginFactory_iid ) \ public: \ explicit name(); \ ~name() override; \ + template < class T > \ + static QObject* createInstance( QObject* parent ) \ + { \ + return new T( parent ); \ + } \ + template < class T > \ + void registerPlugin() \ + { \ + fn = createInstance< T >; \ + } \ }; + +/** @brief Define a Calamares Plugin Factory + * + * This should be done exactly once, generally in the translation + * unit containing the definitions for the main class of the plugin, + * either the Job or the ViewStep definitions. + * + * The @p name must match the name used in the declaration, while + * @p pluginRegistrations should be a single call to `registerPlugin()` + * where `T` is the type (subclass of Job or ViewStep) defined by the + * plugin, eg. + * + * ``` + * CALAMARES_PLUGIN_FACTORY_DEFINITION( MyPlugin, registerPlugin() ) + * ``` + * + * Leaving out the `()` will lead to generally-weird compiler warnings. + */ #define CALAMARES_PLUGIN_FACTORY_DEFINITION( name, pluginRegistrations ) \ - K_PLUGIN_FACTORY_DEFINITION_WITH_BASEFACTORY( name, CalamaresPluginFactory, pluginRegistrations ) + name::name() \ + : CalamaresPluginFactory() \ + { \ + pluginRegistrations; \ + } \ + name::~name() {} + +Q_DECLARE_INTERFACE( CalamaresPluginFactory, CalamaresPluginFactory_iid ) #endif diff --git a/src/libcalamares/utils/String.cpp b/src/libcalamares/utils/String.cpp index c88c23693..f1708d5a3 100644 --- a/src/libcalamares/utils/String.cpp +++ b/src/libcalamares/utils/String.cpp @@ -19,7 +19,9 @@ #include -namespace CalamaresUtils +namespace Calamares +{ +namespace String { QString removeDiacritics( const QString& string ) @@ -124,7 +126,7 @@ obscure( const QString& string ) QString -truncateMultiLine( const QString& string, CalamaresUtils::LinesStartEnd lines, CalamaresUtils::CharCount chars ) +truncateMultiLine( const QString& string, LinesStartEnd lines, CharCount chars ) { const char NEWLINE = '\n'; const int maxLines = lines.atStart + lines.atEnd; @@ -246,4 +248,5 @@ removeTrailing( QString& string, QChar c ) string.remove( lastIndex, string.length() ); } -} // namespace CalamaresUtils +} // namespace String +} // namespace Calamares diff --git a/src/libcalamares/utils/String.h b/src/libcalamares/utils/String.h index 1adc2336a..30fca66d2 100644 --- a/src/libcalamares/utils/String.h +++ b/src/libcalamares/utils/String.h @@ -42,10 +42,15 @@ constexpr static const auto SplitKeepEmptyParts = #endif ; +namespace Calamares +{ /** - * @brief The CalamaresUtils namespace contains utility functions. + * @brief The Calamares::String namespace + * + * This namespace contains functions related to string-handling, + * string-expansion, etc. */ -namespace CalamaresUtils +namespace String { /** * @brief removeDiacritics replaces letters with diacritics and ligatures with @@ -113,6 +118,7 @@ DLLEXPORT void removeLeading( QString& string, QChar c ); */ DLLEXPORT void removeTrailing( QString& string, QChar c ); -} // namespace CalamaresUtils +} // namespace String +} // namespace Calamares #endif diff --git a/src/libcalamares/utils/StringExpander.cpp b/src/libcalamares/utils/StringExpander.cpp new file mode 100644 index 000000000..38093869d --- /dev/null +++ b/src/libcalamares/utils/StringExpander.cpp @@ -0,0 +1,89 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2022 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + * + */ + +#include "StringExpander.h" +#include "Logger.h" + +namespace Calamares +{ +namespace String +{ + +struct DictionaryExpander::Private +{ + QHash< QString, QString > dictionary; + QStringList missing; +}; + +DictionaryExpander::DictionaryExpander() + : KWordMacroExpander( '$' ) + , d( std::make_unique< Private >() ) +{ +} + +DictionaryExpander::DictionaryExpander( Calamares::String::DictionaryExpander&& other ) + : KWordMacroExpander( other.escapeChar() ) + , d( std::move( other.d ) ) +{ +} + + +DictionaryExpander::~DictionaryExpander() {} + + +void +DictionaryExpander::insert( const QString& key, const QString& value ) +{ + d->dictionary.insert( key, value ); +} + +void +DictionaryExpander::clearErrors() +{ + d->missing.clear(); +} + +bool +DictionaryExpander::hasErrors() const +{ + return !d->missing.isEmpty(); +} + +QStringList +DictionaryExpander::errorNames() const +{ + return d->missing; +} + +QString +DictionaryExpander::expand( QString s ) +{ + clearErrors(); + expandMacros( s ); + return s; +} + +bool +DictionaryExpander::expandMacro( const QString& str, QStringList& ret ) +{ + if ( d->dictionary.contains( str ) ) + { + ret << d->dictionary[ str ]; + return true; + } + else + { + d->missing << str; + return false; + } +} + +} // namespace String +} // namespace Calamares diff --git a/src/libcalamares/utils/StringExpander.h b/src/libcalamares/utils/StringExpander.h new file mode 100644 index 000000000..a7f2dab7e --- /dev/null +++ b/src/libcalamares/utils/StringExpander.h @@ -0,0 +1,67 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2022 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + * + */ + +#ifndef UTILS_STRINGEXPANDER_H +#define UTILS_STRINGEXPANDER_H + +#include "DllMacro.h" + +#include + +#include +#include + +namespace Calamares +{ +namespace String +{ + +/** @brief Expand variables in a string against a dictionary. + * + * This class provides a convenience API for building up a dictionary + * and using it to expand strings. Use the `expand()` method to + * do standard word-based expansion with `$` as macro-symbol. + * + * Unlike straight-up `KMacroExpander::expandMacros()`, this + * provides an API to find out which variables were missing + * from the dictionary during expansion. Use `hasErrors()` and + * `errorNames()` to find out which variables those were. + * + * Call `clearErrors()` to reset the stored errors. Calling + * `expand()` implicitly clears the errors before starting + * a new expansion, as well. + */ +class DictionaryExpander : public KWordMacroExpander +{ +public: + DictionaryExpander(); + DictionaryExpander( DictionaryExpander&& ); + virtual ~DictionaryExpander() override; + + void insert( const QString& key, const QString& value ); + + void clearErrors(); + bool hasErrors() const; + QStringList errorNames() const; + + QString expand( QString s ); + +protected: + virtual bool expandMacro( const QString& str, QStringList& ret ) override; + +private: + struct Private; + std::unique_ptr< Private > d; +}; + +} // namespace String +} // namespace Calamares + +#endif diff --git a/src/libcalamares/utils/Tests.cpp b/src/libcalamares/utils/Tests.cpp index 1105915ad..e94c104db 100644 --- a/src/libcalamares/utils/Tests.cpp +++ b/src/libcalamares/utils/Tests.cpp @@ -10,11 +10,13 @@ */ #include "CalamaresUtilsSystem.h" +#include "CommandList.h" #include "Entropy.h" #include "Logger.h" #include "RAII.h" #include "Runner.h" #include "String.h" +#include "StringExpander.h" #include "Traits.h" #include "UMask.h" #include "Variant.h" @@ -45,7 +47,10 @@ private Q_SLOTS: void testLoadSaveYaml(); // Just settings.conf void testLoadSaveYamlExtended(); // Do a find() in the src dir + /** @section Test running commands and command-expansion. */ void testCommands(); + void testCommandExpansion_data(); + void testCommandExpansion(); // See also shellprocess tests /** @section Test that all the UMask objects work correctly. */ void testUmask(); @@ -75,6 +80,10 @@ private Q_SLOTS: void testStringRemoveTrailing_data(); void testStringRemoveTrailing(); + /** @section Test String expansion. */ + void testStringMacroExpander_data(); + void testStringMacroExpander(); // The KF5::CoreAddons bits + /** @section Test Runner directory-manipulation. */ void testRunnerDirs(); void testCalculateWorkingDirectory(); @@ -94,6 +103,16 @@ LibCalamaresTests::~LibCalamaresTests() {} void LibCalamaresTests::initTestCase() { + Calamares::GlobalStorage* gs + = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; + + if ( !gs ) + { + cDebug() << "Creating new JobQueue"; + (void)new Calamares::JobQueue(); + gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; + } + QVERIFY( gs ); } void @@ -251,6 +270,34 @@ LibCalamaresTests::testCommands() QVERIFY( r.getOutput().contains( tfn.fileName() ) ); } +void +LibCalamaresTests::testCommandExpansion_data() +{ + QTest::addColumn< QString >( "command" ); + QTest::addColumn< QString >( "expected" ); + + QTest::newRow( "empty" ) << QString() << QString(); + QTest::newRow( "ls " ) << QStringLiteral( "ls" ) << QStringLiteral( "ls" ); + QTest::newRow( "user " ) << QStringLiteral( "chmod $USER" ) << QStringLiteral( "chmod alice" ); +} + +void +LibCalamaresTests::testCommandExpansion() +{ + Calamares::GlobalStorage* gs + = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; + QVERIFY( gs ); + gs->insert( QStringLiteral( "username" ), QStringLiteral( "alice" ) ); + + QFETCH( QString, command ); + QFETCH( QString, expected ); + CalamaresUtils::CommandLine c( command, std::chrono::seconds( 0 ) ); + CalamaresUtils::CommandLine e = c.expand(); + + QCOMPARE( c.command(), command ); + QCOMPARE( e.command(), expected ); +} + void LibCalamaresTests::testUmask() { @@ -554,7 +601,7 @@ LibCalamaresTests::testStringTruncation() { Logger::setupLogLevel( Logger::LOGDEBUG ); - using namespace CalamaresUtils; + using namespace Calamares::String; const QString longString( R"(--- --- src/libcalamares/utils/String.h @@ -635,7 +682,7 @@ LibCalamaresTests::testStringTruncationShorter() { Logger::setupLogLevel( Logger::LOGDEBUG ); - using namespace CalamaresUtils; + using namespace Calamares::String; const QString longString( R"(Some strange string artifacts appeared, leading to `{1?}` being displayed in various user-facing messages. These have been removed @@ -730,7 +777,7 @@ LibCalamaresTests::testStringTruncationDegenerate() { Logger::setupLogLevel( Logger::LOGDEBUG ); - using namespace CalamaresUtils; + using namespace Calamares::String; // This is quite long, 1 line only, with no newlines const QString longString( "The portscout new distfile checker has detected that one or more of your " @@ -783,7 +830,7 @@ LibCalamaresTests::testStringRemoveLeading() QFETCH( QString, result ); const QString initial = string; - CalamaresUtils::removeLeading( string, c ); + Calamares::String::removeLeading( string, c ); QCOMPARE( string, result ); } @@ -813,10 +860,64 @@ LibCalamaresTests::testStringRemoveTrailing() QFETCH( QString, result ); const QString initial = string; - CalamaresUtils::removeTrailing( string, c ); + Calamares::String::removeTrailing( string, c ); QCOMPARE( string, result ); } +void +LibCalamaresTests::testStringMacroExpander_data() +{ + QTest::addColumn< QString >( "source" ); + QTest::addColumn< QString >( "result" ); + QTest::addColumn< QStringList >( "errors" ); + + QTest::newRow( "empty " ) << QString() << QString() << QStringList {}; + QTest::newRow( "constant" ) << QStringLiteral( "bunnies!" ) << QStringLiteral( "bunnies!" ) << QStringList {}; + QTest::newRow( "escaped " ) << QStringLiteral( "$$bun" ) << QStringLiteral( "$bun" ) + << QStringList {}; // Double $$ is an escaped $ + QTest::newRow( "whole " ) << QStringLiteral( "${ROOT}" ) << QStringLiteral( "wortel" ) << QStringList {}; + QTest::newRow( "unbraced" ) << QStringLiteral( "$ROOT" ) << QStringLiteral( "wortel" ) + << QStringList {}; // Does not need {} + QTest::newRow( "bad-var1" ) << QStringLiteral( "${ROOF}" ) << QStringLiteral( "${ROOF}" ) + << QStringList { QStringLiteral( "ROOF" ) }; // Not replaced + QTest::newRow( "twice " ) << QStringLiteral( "${ROOT}x${ROOT}" ) << QStringLiteral( "wortelxwortel" ) + << QStringList {}; + QTest::newRow( "bad-var2" ) << QStringLiteral( "${ROOT}x${ROPE}" ) << QStringLiteral( "wortelx${ROPE}" ) + << QStringList { QStringLiteral( "ROPE" ) }; // Not replaced + // This is a borked string with a "nested" variable. The variable-name- + // scanner goes from ${ to the next } and tries to match that. + QTest::newRow( "confuse1" ) << QStringLiteral( "${RO${ROOT}" ) << QStringLiteral( "${ROwortel" ) + << QStringList { "RO${ROOT" }; + // This one doesn't have a { for the first name to match with + QTest::newRow( "confuse2" ) << QStringLiteral( "$RO${ROOT}" ) << QStringLiteral( "$ROwortel" ) + << QStringList { "RO" }; + // Here we see it just doesn't nest + QTest::newRow( "confuse3" ) << QStringLiteral( "${RO${ROOT}}" ) << QStringLiteral( "${ROwortel}" ) + << QStringList { "RO${ROOT" }; +} + +void +LibCalamaresTests::testStringMacroExpander() +{ + QHash< QString, QString > dict; + dict.insert( QStringLiteral( "ROOT" ), QStringLiteral( "wortel" ) ); + + Calamares::String::DictionaryExpander d; + d.insert( QStringLiteral( "ROOT" ), QStringLiteral( "wortel" ) ); + + QFETCH( QString, source ); + QFETCH( QString, result ); + QFETCH( QStringList, errors ); + + QString km_expanded = KMacroExpander::expandMacros( source, dict, '$' ); + QCOMPARE( km_expanded, result ); + + QString de_expanded = d.expand( source ); + QCOMPARE( de_expanded, result ); + QCOMPARE( d.errorNames(), errors ); + QCOMPARE( d.hasErrors(), !errors.isEmpty() ); +} + static QString dirname( const QTemporaryDir& d ) { diff --git a/src/libcalamares/utils/Units.h b/src/libcalamares/utils/Units.h index bb5bf4509..3b909dc02 100644 --- a/src/libcalamares/utils/Units.h +++ b/src/libcalamares/utils/Units.h @@ -17,6 +17,8 @@ namespace CalamaresUtils { +/// @brief Type for expressing units +using intunit_t = quint64; namespace Units { @@ -137,12 +139,19 @@ BytesToMiB( qint64 b ) return int( b / 1024 / 1024 ); } +// TODO: deprecate signed version constexpr int BytesToGiB( qint64 b ) { return int( b / 1024 / 1024 / 1024 ); } +constexpr intunit_t +BytesToGiB( intunit_t b ) +{ + return b / 1024 / 1024 / 1024; +} + constexpr qint64 alignBytesToBlockSize( qint64 bytes, qint64 blocksize ) { diff --git a/src/libcalamaresui/Branding.h b/src/libcalamaresui/Branding.h index 1654b4d56..556f2fcff 100644 --- a/src/libcalamaresui/Branding.h +++ b/src/libcalamaresui/Branding.h @@ -76,10 +76,8 @@ public: { SidebarBackground, SidebarText, - SidebarTextSelect, - SidebarTextSelected = SidebarTextSelect, // TODO:3.3:Remove SidebarTextSelect - SidebarTextHighlight, - SidebarBackgroundSelected = SidebarTextHighlight // TODO:3.3:Remove SidebarTextHighlight + SidebarTextCurrent, + SidebarBackgroundCurrent, }; Q_ENUM( StyleEntry ) diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index 48e4c4b4d..406bd3ce4 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -8,24 +8,21 @@ # view modules, view steps, widgets, and branding. # The UI libs use the non-UI library -include_directories( ${CMAKE_SOURCE_DIR}/src/libcalamares ${CMAKE_BINARY_DIR}/src/libcalamares ${CMAKE_SOURCE_DIR} ) +include_directories(${CMAKE_SOURCE_DIR}/src/libcalamares ${CMAKE_BINARY_DIR}/src/libcalamares ${CMAKE_SOURCE_DIR}) -set( calamaresui_SOURCES +set(calamaresui_SOURCES modulesystem/CppJobModule.cpp modulesystem/ModuleFactory.cpp modulesystem/ModuleManager.cpp modulesystem/ProcessJobModule.cpp modulesystem/ViewModule.cpp - utils/CalamaresUtilsGui.cpp utils/ImageRegistry.cpp utils/Paste.cpp - viewpages/BlankViewStep.cpp viewpages/ExecutionViewStep.cpp viewpages/Slideshow.cpp viewpages/ViewStep.cpp - widgets/ClickableLabel.cpp widgets/ErrorDialog.cpp widgets/FixedAspectRatioLabel.cpp @@ -33,42 +30,20 @@ set( calamaresui_SOURCES widgets/LogWidget.cpp widgets/TranslationFix.cpp widgets/WaitingWidget.cpp - ${CMAKE_SOURCE_DIR}/3rdparty/waitingspinnerwidget.cpp - + widgets/waitingspinnerwidget.cpp Branding.cpp ViewManager.cpp ) -# Don't warn about third-party sources -mark_thirdparty_code( - ${CMAKE_SOURCE_DIR}/3rdparty/waitingspinnerwidget.cpp -) - -if( WITH_PYTHON ) - list( APPEND calamaresui_SOURCES - modulesystem/PythonJobModule.cpp - ) +if(WITH_PYTHON) + list(APPEND calamaresui_SOURCES modulesystem/PythonJobModule.cpp) endif() -if( WITH_PYTHONQT ) - list( APPEND calamaresui_SOURCES - modulesystem/PythonQtViewModule.cpp - utils/PythonQtUtils.cpp - viewpages/PythonQtJob.cpp - viewpages/PythonQtViewStep.cpp - viewpages/PythonQtGlobalStorageWrapper.cpp - viewpages/PythonQtUtilsWrapper.cpp - ) +if(WITH_QML) + list(APPEND calamaresui_SOURCES utils/Qml.cpp viewpages/QmlViewStep.cpp) endif() -if( WITH_QML ) - list( APPEND calamaresui_SOURCES - utils/Qml.cpp - viewpages/QmlViewStep.cpp - ) -endif() - -calamares_add_library( calamaresui +calamares_add_library(calamaresui SOURCES ${calamaresui_SOURCES} EXPORT_MACRO UIDLLEXPORT_PRO LINK_LIBRARIES @@ -79,22 +54,17 @@ calamares_add_library( calamaresui utils/ErrorDialog/ErrorDialog.ui VERSION ${CALAMARES_VERSION_SHORT} ) -target_link_libraries( calamaresui PRIVATE yamlcpp::yamlcpp ) -if( KF5CoreAddons_FOUND AND KF5CoreAddons_VERSION VERSION_GREATER_EQUAL 5.58 ) - target_compile_definitions( calamaresui PRIVATE WITH_KOSRelease ) +target_link_libraries(calamaresui PRIVATE yamlcpp::yamlcpp) +if(KF5CoreAddons_FOUND AND KF5CoreAddons_VERSION VERSION_GREATER_EQUAL 5.58) + target_compile_definitions(calamaresui PRIVATE WITH_KOSRelease) + target_link_libraries(calamaresui PRIVATE KF5::CoreAddons) endif() -if( WITH_PYTHONQT ) - # *_DIRS because we also use extensions - target_include_directories( calamaresui PRIVATE ${PYTHON_INCLUDE_DIRS} ${PYTHONQT_INCLUDE_DIRS} ) - target_link_libraries( calamaresui PRIVATE ${PYTHON_LIBRARIES} ${PYTHONQT_LIBRARIES} ) -endif() -if( WITH_QML ) - target_link_libraries( calamaresui PUBLIC Qt5::QuickWidgets ) +if(WITH_QML) + target_link_libraries(calamaresui PUBLIC Qt5::QuickWidgets) endif() add_library(Calamares::calamaresui ALIAS calamaresui) - ### Installation # # @@ -103,24 +73,12 @@ add_library(Calamares::calamaresui ALIAS calamaresui) # where libcalamares and libcalamaresui live in different branches, # we're going to glom it all together in the installed headers location. -install( - FILES - Branding.h - ViewManager.h - DESTINATION include/libcalamares -) +install(FILES Branding.h ViewManager.h DESTINATION include/libcalamares) # Install each subdir-worth of header files -foreach( subdir modulesystem utils viewpages widgets ) - file( GLOB subdir_headers "${subdir}/*.h" ) - install( FILES ${subdir_headers} DESTINATION include/libcalamares/${subdir} ) +foreach(subdir modulesystem utils viewpages widgets) + file(GLOB subdir_headers "${subdir}/*.h") + install(FILES ${subdir_headers} DESTINATION include/libcalamares/${subdir}) endforeach() -calamares_add_test( - test_libcalamaresuipaste - SOURCES - utils/TestPaste.cpp - utils/Paste.cpp - LIBRARIES - calamaresui -) +calamares_add_test(test_libcalamaresuipaste SOURCES utils/TestPaste.cpp utils/Paste.cpp LIBRARIES calamaresui) diff --git a/src/libcalamaresui/modulesystem/ModuleFactory.cpp b/src/libcalamaresui/modulesystem/ModuleFactory.cpp index a7193d3f5..7f44a0052 100644 --- a/src/libcalamaresui/modulesystem/ModuleFactory.cpp +++ b/src/libcalamaresui/modulesystem/ModuleFactory.cpp @@ -24,10 +24,6 @@ #include "PythonJobModule.h" #endif -#ifdef WITH_PYTHONQT -#include "PythonQtViewModule.h" -#endif - #include #include #include @@ -59,14 +55,6 @@ moduleFromDescriptor( const Calamares::ModuleSystem::Descriptor& moduleDescripto { m.reset( new ViewModule() ); } - else if ( moduleDescriptor.interface() == Interface::PythonQt ) - { -#ifdef WITH_PYTHONQT - m.reset( new PythonQtViewModule() ); -#else - cError() << "PythonQt view modules are not supported in this version of Calamares."; -#endif - } else { cError() << "Bad interface" diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index 1e397b340..1233b1115 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -349,7 +349,18 @@ ModuleManager::checkRequirements() connect( rq, &RequirementsChecker::done, this, - [ = ]() { this->requirementsComplete( m_requirementsModel->satisfiedMandatory() ); } ); + [ = ]() + { + if ( m_requirementsModel->satisfiedMandatory() ) + { + /* we're done */ this->requirementsComplete( true ); + } + else + { + this->requirementsComplete( false ); + QTimer::singleShot( std::chrono::seconds( 5 ), this, &ModuleManager::checkRequirements ); + } + } ); QTimer::singleShot( 0, rq, &RequirementsChecker::run ); } diff --git a/src/libcalamaresui/modulesystem/PythonQtViewModule.cpp b/src/libcalamaresui/modulesystem/PythonQtViewModule.cpp deleted file mode 100644 index 105dd2998..000000000 --- a/src/libcalamaresui/modulesystem/PythonQtViewModule.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-FileCopyrightText: 2018 Raul Rodrigo Segura - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PythonQtViewModule.h" - -#include "CalamaresConfig.h" -#include "GlobalStorage.h" -#include "JobQueue.h" -#include "ViewManager.h" -#include "utils/Logger.h" -#include "viewpages/PythonQtGlobalStorageWrapper.h" -#include "viewpages/PythonQtUtilsWrapper.h" -#include "viewpages/PythonQtViewStep.h" -#include "viewpages/ViewStep.h" - -#include -#include - -#include -#include - - -static QPointer< GlobalStorage > s_gs = nullptr; -static QPointer< Utils > s_utils = nullptr; - -namespace Calamares -{ - -Module::Type -PythonQtViewModule::type() const -{ - return Module::Type::View; -} - - -Module::Interface -PythonQtViewModule::interface() const -{ - return Module::Interface::PythonQt; -} - - -void -PythonQtViewModule::loadSelf() -{ - if ( !m_scriptFileName.isEmpty() ) - { - if ( PythonQt::self() == nullptr ) - { - if ( Py_IsInitialized() ) - PythonQt::init( PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut - | PythonQt::PythonAlreadyInitialized ); - else - { - PythonQt::init(); - } - - PythonQt_QtAll::init(); - cDebug() << "Initializing PythonQt bindings." - << "This should only happen once."; - - //TODO: register classes here into the PythonQt environment, like this: - //PythonQt::self()->registerClass( &PythonQtViewStep::staticMetaObject, - // "calamares" ); - - // We only do the following to force PythonQt to create a submodule - // "calamares" for us to put our static objects in - PythonQt::self()->registerClass( &::GlobalStorage::staticMetaObject, "calamares" ); - - // Get a PythonQtObjectPtr to the PythonQt.calamares submodule - PythonQtObjectPtr pqtm = PythonQt::priv()->pythonQtModule(); - PythonQtObjectPtr cala = PythonQt::self()->lookupObject( pqtm, "calamares" ); - - // Prepare GlobalStorage object, in module PythonQt.calamares - if ( !s_gs ) - { - s_gs = new ::GlobalStorage( Calamares::JobQueue::instance()->globalStorage() ); - } - cala.addObject( "global_storage", s_gs ); - - // Prepare Utils object, in module PythonQt.calamares - if ( !s_utils ) - { - s_utils = new ::Utils( Calamares::JobQueue::instance()->globalStorage() ); - } - cala.addObject( "utils", s_utils ); - - // Append configuration object, in module PythonQt.calamares - cala.addVariable( "configuration", m_configurationMap ); - - // Basic stdout/stderr handling - QObject::connect( PythonQt::self(), - &PythonQt::pythonStdOut, - []( const QString& message ) { cDebug() << "PythonQt OUT>" << message; } ); - QObject::connect( PythonQt::self(), - &PythonQt::pythonStdErr, - []( const QString& message ) { cDebug() << "PythonQt ERR>" << message; } ); - } - - QDir workingDir( m_workingPath ); - if ( !workingDir.exists() ) - { - cDebug() << "Invalid working directory" << m_workingPath << "for module" << name(); - return; - } - - QString fullPath = workingDir.absoluteFilePath( m_scriptFileName ); - QFileInfo scriptFileInfo( fullPath ); - if ( !scriptFileInfo.isReadable() ) - { - cDebug() << "Invalid main script file path" << fullPath << "for module" << name(); - return; - } - - // Construct empty Python module with the given name - PythonQtObjectPtr cxt = PythonQt::self()->createModuleFromScript( name() ); - if ( cxt.isNull() ) - { - cDebug() << "Cannot load PythonQt context from file" << fullPath << "for module" << name(); - return; - } - - static const QLatin1String calamares_module_annotation( - "_calamares_module_typename = ''\n" - "def calamares_module(viewmodule_type):\n" - " global _calamares_module_typename\n" - " _calamares_module_typename = viewmodule_type.__name__\n" - " return viewmodule_type\n" ); - - // Load in the decorator - PythonQt::self()->evalScript( cxt, calamares_module_annotation ); - - // Load the module - PythonQt::self()->evalFile( cxt, fullPath ); - - m_viewStep = new PythonQtViewStep( cxt ); - - cDebug() << "PythonQtViewModule loading self for instance" << instanceKey() << "\nPythonQtViewModule at address" - << this << "\nViewStep at address" << m_viewStep; - - m_viewStep->setModuleInstanceKey( instanceKey() ); - m_viewStep->setConfigurationMap( m_configurationMap ); - ViewManager::instance()->addViewStep( m_viewStep ); - m_loaded = true; - cDebug() << "PythonQtViewModule" << instanceKey() << "loading complete."; - } -} - - -JobList -PythonQtViewModule::jobs() const -{ - return m_viewStep->jobs(); -} - - -void -PythonQtViewModule::initFrom( const QVariantMap& moduleDescriptor ) -{ - QDir directory( location() ); - m_workingPath = directory.absolutePath(); - - if ( !moduleDescriptor.value( "script" ).toString().isEmpty() ) - { - m_scriptFileName = moduleDescriptor.value( "script" ).toString(); - } -} - -PythonQtViewModule::PythonQtViewModule() - : Module() -{ -} - -PythonQtViewModule::~PythonQtViewModule() {} - -} // namespace Calamares diff --git a/src/libcalamaresui/modulesystem/PythonQtViewModule.h b/src/libcalamaresui/modulesystem/PythonQtViewModule.h deleted file mode 100644 index 8267dd2cb..000000000 --- a/src/libcalamaresui/modulesystem/PythonQtViewModule.h +++ /dev/null @@ -1,50 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef CALAMARES_PYTHONQTVIEWMODULE_H -#define CALAMARES_PYTHONQTVIEWMODULE_H - -#include "DllMacro.h" -#include "Module.h" - -namespace Calamares -{ - -class ViewStep; - -class UIDLLEXPORT PythonQtViewModule : public Module -{ -public: - Type type() const override; - Interface interface() const override; - - void loadSelf() override; - JobList jobs() const override; - -protected: - void initFrom( const QVariantMap& moduleDescriptor ) override; - -private: - explicit PythonQtViewModule(); - virtual ~PythonQtViewModule(); - - ViewStep* m_viewStep = nullptr; - - QString m_scriptFileName; - QString m_workingPath; - - friend Module* Calamares::moduleFromDescriptor( const ModuleSystem::Descriptor& moduleDescriptor, - const QString& instanceId, - const QString& configFileName, - const QString& moduleDirectory ); -}; - -} // namespace Calamares - -#endif // CALAMARES_PYTHONQTVIEWMODULE_H diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp index d10aada73..a1030d03e 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.cpp +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.cpp @@ -128,62 +128,12 @@ defaultPixmap( ImageType type, ImageMode mode, const QSize& size ) } -QPixmap -createRoundedImage( const QPixmap& pixmap, const QSize& size, float frameWidthPct ) -{ - int height; - int width; - - if ( !size.isEmpty() ) - { - height = size.height(); - width = size.width(); - } - else - { - height = pixmap.height(); - width = pixmap.width(); - } - - if ( !height || !width ) - { - return QPixmap(); - } - - QPixmap scaledAvatar = pixmap.scaled( width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); - if ( frameWidthPct == 0.00f ) - { - return scaledAvatar; - } - - QPixmap frame( width, height ); - frame.fill( Qt::transparent ); - - QPainter painter( &frame ); - painter.setRenderHint( QPainter::Antialiasing ); - - QRect outerRect( 0, 0, width, height ); - QBrush brush( scaledAvatar ); - QPen pen; - pen.setColor( Qt::transparent ); - pen.setJoinStyle( Qt::RoundJoin ); - - painter.setBrush( brush ); - painter.setPen( pen ); - painter.drawRoundedRect( - outerRect, qreal( frameWidthPct ) * 100.0, qreal( frameWidthPct ) * 100.0, Qt::RelativeSize ); - - return frame; -} - - void unmarginLayout( QLayout* layout ) { if ( layout ) { layout->setContentsMargins( 0, 0, 0, 0 ); - layout->setMargin( 0 ); layout->setSpacing( 0 ); for ( int i = 0; i < layout->count(); i++ ) @@ -224,15 +174,6 @@ defaultFontHeight() } -QFont -defaultFont() -{ - QFont f; - f.setPointSize( defaultFontSize() ); - return f; -} - - QFont largeFont() { @@ -257,24 +198,4 @@ defaultIconSize() return QSize( w, w ); } - -void -clearLayout( QLayout* layout ) -{ - while ( QLayoutItem* item = layout->takeAt( 0 ) ) - { - if ( QWidget* widget = item->widget() ) - { - widget->deleteLater(); - } - - if ( QLayout* childLayout = item->layout() ) - { - clearLayout( childLayout ); - } - - delete item; - } -} - } // namespace CalamaresUtils diff --git a/src/libcalamaresui/utils/CalamaresUtilsGui.h b/src/libcalamaresui/utils/CalamaresUtilsGui.h index aa7aff79b..5a0ee336f 100644 --- a/src/libcalamaresui/utils/CalamaresUtilsGui.h +++ b/src/libcalamaresui/utils/CalamaresUtilsGui.h @@ -63,7 +63,6 @@ enum ImageMode CoverInCase, Grid, DropShadow, - RoundedCorners }; /** @@ -78,35 +77,15 @@ UIDLLEXPORT QPixmap defaultPixmap( ImageType type, ImageMode mode = CalamaresUtils::Original, const QSize& size = QSize( 0, 0 ) ); -// TODO:3.3:This has only one consumer, move to ImageRegistry, make static -/** - * @brief createRoundedImage returns a rounded version of a pixmap. - * @param avatar the input pixmap. - * @param size the new size. - * @param frameWidthPct the frame size, as percentage of width. - * @return the transformed pixmap. - * This one is currently unused. - */ -UIDLLEXPORT QPixmap createRoundedImage( const QPixmap& avatar, const QSize& size, float frameWidthPct = 0.20f ); - /** * @brief unmarginLayout recursively walks the QLayout tree and removes all margins. * @param layout the layout to unmargin. */ UIDLLEXPORT void unmarginLayout( QLayout* layout ); -// TODO:3.3:This has only one consumer, move to LicensePage, make static -/** - * @brief clearLayout recursively walks the QLayout tree and deletes all the child - * widgets and layouts. - * @param layout the layout to clear. - */ -UIDLLEXPORT void clearLayout( QLayout* layout ); - UIDLLEXPORT void setDefaultFontSize( int points ); UIDLLEXPORT int defaultFontSize(); // in points UIDLLEXPORT int defaultFontHeight(); // in pixels, DPI-specific -UIDLLEXPORT QFont defaultFont(); // TODO:3.3:This has one consumer, move to BlankViewStep UIDLLEXPORT QFont largeFont(); UIDLLEXPORT QSize defaultIconSize(); diff --git a/src/libcalamaresui/utils/ImageRegistry.cpp b/src/libcalamaresui/utils/ImageRegistry.cpp index 3ae519f55..96dd79e78 100644 --- a/src/libcalamaresui/utils/ImageRegistry.cpp +++ b/src/libcalamaresui/utils/ImageRegistry.cpp @@ -8,6 +8,7 @@ #include "ImageRegistry.h" +#include #include #include #include @@ -89,11 +90,6 @@ ImageRegistry::pixmap( const QString& image, const QSize& size, CalamaresUtils:: if ( !pixmap.isNull() ) { - if ( mode == CalamaresUtils::RoundedCorners ) - { - pixmap = CalamaresUtils::createRoundedImage( pixmap, size ); - } - if ( !size.isNull() && pixmap.size() != size ) { if ( size.width() == 0 ) diff --git a/src/libcalamaresui/utils/PythonQtUtils.cpp b/src/libcalamaresui/utils/PythonQtUtils.cpp deleted file mode 100644 index bc4e034f0..000000000 --- a/src/libcalamaresui/utils/PythonQtUtils.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PythonQtUtils.h" - -namespace CalamaresUtils -{ - -QVariant -lookupAndCall( PyObject* object, - const QStringList& candidateNames, - const QVariantList& args, - const QVariantMap& kwargs ) -{ - Q_ASSERT( object ); - Q_ASSERT( !candidateNames.isEmpty() ); - - for ( const QString& name : candidateNames ) - { - PythonQtObjectPtr callable = PythonQt::self()->lookupCallable( object, name ); - if ( callable ) - { - return callable.call( args, kwargs ); - } - } - - // If we haven't found a callable with the given names, we force an error: - return PythonQt::self()->call( object, candidateNames.first(), args, kwargs ); -} - -} // namespace CalamaresUtils diff --git a/src/libcalamaresui/utils/PythonQtUtils.h b/src/libcalamaresui/utils/PythonQtUtils.h deleted file mode 100644 index 49f3bb1c4..000000000 --- a/src/libcalamaresui/utils/PythonQtUtils.h +++ /dev/null @@ -1,29 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PYTHONQTUTILS_H -#define PYTHONQTUTILS_H - -#include - -#include - - -namespace CalamaresUtils -{ -//NOTE: when running this, it is assumed that Python is initialized and -// PythonQt::self() is valid. -QVariant lookupAndCall( PyObject* object, - const QStringList& candidateNames, - const QVariantList& args = QVariantList(), - const QVariantMap& kwargs = QVariantMap() ); - -} // namespace CalamaresUtils - -#endif // PYTHONQTUTILS_H diff --git a/src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.cpp b/src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.cpp deleted file mode 100644 index 0d667a097..000000000 --- a/src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PythonQtGlobalStorageWrapper.h" - -#include "GlobalStorage.h" - - -GlobalStorage::GlobalStorage( Calamares::GlobalStorage* gs ) - : QObject( gs ) - , m_gs( gs ) -{ -} - - -bool -GlobalStorage::contains( const QString& key ) const -{ - return m_gs->contains( key ); -} - - -int -GlobalStorage::count() const -{ - return m_gs->count(); -} - - -void -GlobalStorage::insert( const QString& key, const QVariant& value ) -{ - m_gs->insert( key, value ); -} - - -QStringList -GlobalStorage::keys() const -{ - return m_gs->keys(); -} - - -int -GlobalStorage::remove( const QString& key ) -{ - return m_gs->remove( key ); -} - - -QVariant -GlobalStorage::value( const QString& key ) const -{ - return m_gs->value( key ); -} diff --git a/src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.h b/src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.h deleted file mode 100644 index 5d1282d0f..000000000 --- a/src/libcalamaresui/viewpages/PythonQtGlobalStorageWrapper.h +++ /dev/null @@ -1,48 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PYTHONQTGLOBALSTORAGEWRAPPER_H -#define PYTHONQTGLOBALSTORAGEWRAPPER_H - -#include -#include -#include - -namespace Calamares -{ -class GlobalStorage; -} - - -/** - * @brief This GlobalStorage class is a namespace-free wrapper for - * Calamares::GlobalStorage. This is unfortunately a necessity - * because PythonQt doesn't like namespaces. - */ -class GlobalStorage : public QObject -{ - Q_OBJECT -public: - explicit GlobalStorage( Calamares::GlobalStorage* gs ); - virtual ~GlobalStorage() {} - -public slots: - bool contains( const QString& key ) const; - int count() const; - void insert( const QString& key, const QVariant& value ); - QStringList keys() const; - int remove( const QString& key ); - QVariant value( const QString& key ) const; - -private: - Calamares::GlobalStorage* m_gs; -}; - -#endif // PYTHONQTGLOBALSTORAGEWRAPPER_H diff --git a/src/libcalamaresui/viewpages/PythonQtJob.cpp b/src/libcalamaresui/viewpages/PythonQtJob.cpp deleted file mode 100644 index d41c70f1f..000000000 --- a/src/libcalamaresui/viewpages/PythonQtJob.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PythonQtJob.h" - -#include "utils/PythonQtUtils.h" - -PythonQtJob::PythonQtJob( PythonQtObjectPtr cxt, PythonQtObjectPtr pyJob, QObject* parent ) - : Calamares::Job( parent ) - , m_cxt( cxt ) - , m_pyJob( pyJob ) -{ -} - - -QString -PythonQtJob::prettyName() const -{ - return CalamaresUtils::lookupAndCall( m_pyJob, { "prettyName", "prettyname", "pretty_name" } ).toString(); -} - - -QString -PythonQtJob::prettyDescription() const -{ - return CalamaresUtils::lookupAndCall( m_pyJob, { "prettyDescription", "prettydescription", "pretty_description" } ) - .toString(); -} - - -QString -PythonQtJob::prettyStatusMessage() const -{ - return CalamaresUtils::lookupAndCall( m_pyJob, - { "prettyStatusMessage", "prettystatusmessage", "pretty_status_message" } ) - .toString(); -} - - -Calamares::JobResult -PythonQtJob::exec() -{ - QVariant response = m_pyJob.call( "exec" ); - if ( response.isNull() ) - { - return Calamares::JobResult::ok(); - } - - QVariantMap map = response.toMap(); - if ( map.isEmpty() || map.value( "ok" ).toBool() ) - { - return Calamares::JobResult::ok(); - } - - return Calamares::JobResult::error( map.value( "message" ).toString(), map.value( "details" ).toString() ); -} diff --git a/src/libcalamaresui/viewpages/PythonQtJob.h b/src/libcalamaresui/viewpages/PythonQtJob.h deleted file mode 100644 index 4d48921e1..000000000 --- a/src/libcalamaresui/viewpages/PythonQtJob.h +++ /dev/null @@ -1,53 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PYTHONQTJOB_H -#define PYTHONQTJOB_H - -#include "Job.h" - -#include - -namespace Calamares -{ -class PythonQtViewStep; -} - -class PythonQtJobResult : public QObject, public Calamares::JobResult -{ - Q_OBJECT -public: - explicit PythonQtJobResult( bool ok, const QString& message, const QString& details ) - : QObject( nullptr ) - , Calamares::JobResult( message, details, ok ? 0 : Calamares::JobResult::GenericError ) - { - } -}; - - -class PythonQtJob : public Calamares::Job -{ - Q_OBJECT -public: - virtual ~PythonQtJob() {} - - QString prettyName() const override; - QString prettyDescription() const override; - QString prettyStatusMessage() const override; - Calamares::JobResult exec() override; - -private: - explicit PythonQtJob( PythonQtObjectPtr cxt, PythonQtObjectPtr pyJob, QObject* parent = nullptr ); - friend class Calamares::PythonQtViewStep; // only this one can call the ctor - - PythonQtObjectPtr m_cxt; - PythonQtObjectPtr m_pyJob; -}; - -#endif // PYTHONQTJOB_H diff --git a/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp b/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp deleted file mode 100644 index 4cd72f8c0..000000000 --- a/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2019 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PythonQtUtilsWrapper.h" - -#include "partition/Mount.h" -#include "utils/CalamaresUtilsSystem.h" -#include "utils/Logger.h" -#include "utils/String.h" - -#include - - -Utils::Utils( QObject* parent ) - : QObject( parent ) - , m_exceptionCxt( PythonQt::self()->createUniqueModule() ) -{ - PythonQt::self()->evalScript( m_exceptionCxt, "import subprocess" ); -} - - -void -Utils::debug( const QString& s ) const -{ - cDebug() << "PythonQt DBG>" << s; -} - - -int -Utils::mount( const QString& device_path, - const QString& mount_point, - const QString& filesystem_name, - const QString& options ) const -{ - return CalamaresUtils::Partition::mount( device_path, mount_point, filesystem_name, options ); -} - - -int -Utils::target_env_call( const QString& command, const QString& stdin, int timeout ) const -{ - return CalamaresUtils::System::instance()->targetEnvCall( - command, QString(), stdin, std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); -} - - -int -Utils::target_env_call( const QStringList& args, const QString& stdin, int timeout ) const -{ - return CalamaresUtils::System::instance()->targetEnvCall( - args, QString(), stdin, std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); -} - - -int -Utils::check_target_env_call( const QString& command, const QString& stdin, int timeout ) const -{ - int ec = target_env_call( command, stdin, timeout ); - return _handle_check_target_env_call_error( ec, command ); -} - - -int -Utils::check_target_env_call( const QStringList& args, const QString& stdin, int timeout ) const -{ - int ec = target_env_call( args, stdin, timeout ); - return _handle_check_target_env_call_error( ec, args.join( ' ' ) ); -} - - -QString -Utils::check_target_env_output( const QString& command, const QString& stdin, int timeout ) const -{ - QString output; - int ec = CalamaresUtils::System::instance()->targetEnvOutput( - command, output, QString(), stdin, std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); - _handle_check_target_env_call_error( ec, command ); - return output; -} - - -QString -Utils::check_target_env_output( const QStringList& args, const QString& stdin, int timeout ) const -{ - QString output; - int ec = CalamaresUtils::System::instance()->targetEnvOutput( - args, output, QString(), stdin, std::chrono::seconds( timeout > 0 ? timeout : 0 ) ); - _handle_check_target_env_call_error( ec, args.join( ' ' ) ); - return output; -} - - -QString -Utils::obscure( const QString& string ) const -{ - return CalamaresUtils::obscure( string ); -} - - -int -Utils::_handle_check_target_env_call_error( int ec, const QString& cmd ) const -{ - if ( ec ) - { - QString raise = QString( "raise subprocess.CalledProcessError(%1,\"%2\")" ).arg( ec ).arg( cmd ); - PythonQt::self()->evalScript( m_exceptionCxt, raise ); - } - return ec; -} diff --git a/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.h b/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.h deleted file mode 100644 index e39249185..000000000 --- a/src/libcalamaresui/viewpages/PythonQtUtilsWrapper.h +++ /dev/null @@ -1,57 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PYTHONQTUTILSWRAPPER_H -#define PYTHONQTUTILSWRAPPER_H - -#include - -#include - - -/** - * @brief The Utils class wraps around functions from CalamaresUtils to make them - * available in the PythonQt interface. - */ -class Utils : public QObject -{ - Q_OBJECT -public: - explicit Utils( QObject* parent = nullptr ); - virtual ~Utils() {} - -public slots: - void debug( const QString& s ) const; - - int mount( const QString& device_path, - const QString& mount_point, - const QString& filesystem_name, - const QString& options ) const; - - int target_env_call( const QString& command, const QString& stdin = QString(), int timeout = 0 ) const; - - int target_env_call( const QStringList& args, const QString& stdin = QString(), int timeout = 0 ) const; - - int check_target_env_call( const QString& command, const QString& stdin = QString(), int timeout = 0 ) const; - - int check_target_env_call( const QStringList& args, const QString& stdin = QString(), int timeout = 0 ) const; - - QString check_target_env_output( const QString& command, const QString& stdin = QString(), int timeout = 0 ) const; - - QString check_target_env_output( const QStringList& args, const QString& stdin = QString(), int timeout = 0 ) const; - - QString obscure( const QString& string ) const; - -private: - inline int _handle_check_target_env_call_error( int ec, const QString& cmd ) const; - - PythonQtObjectPtr m_exceptionCxt; -}; - -#endif // PYTHONQTUTILSWRAPPER_H diff --git a/src/libcalamaresui/viewpages/PythonQtViewStep.cpp b/src/libcalamaresui/viewpages/PythonQtViewStep.cpp deleted file mode 100644 index df3c11994..000000000 --- a/src/libcalamaresui/viewpages/PythonQtViewStep.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-FileCopyrightText: 2018 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "PythonQtViewStep.h" -#include "utils/CalamaresUtilsGui.h" -#include "utils/Logger.h" -#include "utils/PythonQtUtils.h" -#include "utils/Retranslator.h" -#include "viewpages/PythonQtJob.h" - -#include - -#include -#include - - -namespace Calamares -{ - -PythonQtViewStep::PythonQtViewStep( PythonQtObjectPtr cxt, QObject* parent ) - : ViewStep( parent ) - , m_widget( new QWidget() ) - , m_cxt( cxt ) -{ - PythonQt* pq = PythonQt::self(); - Q_ASSERT( pq ); - - // The @calamares_module decorator should have filled _calamares_module_typename - // for us. - QString className = m_cxt.getVariable( "_calamares_module_typename" ).toString(); - - // Instantiate an object of the class marked with @calamares_module and - // store it as _calamares_module. - pq->evalScript( m_cxt, QString( "_calamares_module = %1()" ).arg( className ) ); - m_obj = pq->lookupObject( m_cxt, "_calamares_module" ); - - Q_ASSERT( !m_obj.isNull() ); // no entry point, no party - - // Prepare the base widget for the module's pages - m_widget->setLayout( new QVBoxLayout ); - CalamaresUtils::unmarginLayout( m_widget->layout() ); - m_cxt.addObject( "_calamares_module_basewidget", m_widget ); - - CALAMARES_RETRANSLATE_FOR( - m_widget, - CalamaresUtils::lookupAndCall( m_obj, { "retranslate" }, { CalamaresUtils::translatorLocaleName() } ); ) -} - - -QString -PythonQtViewStep::prettyName() const -{ - return CalamaresUtils::lookupAndCall( m_obj, { "prettyName", "prettyname", "pretty_name" } ).toString(); -} - - -QWidget* -PythonQtViewStep::widget() -{ - if ( m_widget->layout()->count() > 1 ) - cWarning() << "PythonQtViewStep wrapper widget has more than 1 child. " - "This should never happen."; - - bool nothingChanged - = m_cxt.evalScript( "_calamares_module.widget() in _calamares_module_basewidget.children()" ).toBool(); - if ( nothingChanged ) - { - return m_widget; - } - - // Else, we either don't have a child widget, or we have a child widget that - // was previously set and doesn't apply any more since the Python module - // set a new one. - - // First we clear the layout, which should only ever have 1 item. - // We only remove from the layout and not delete because Python is in charge - // of memory management for these widgets. - while ( m_widget->layout()->itemAt( 0 ) ) - { - m_widget->layout()->takeAt( 0 ); - } - - m_cxt.evalScript( "_calamares_module_basewidget.layout().addWidget(_calamares_module.widget())" ); - - return m_widget; -} - - -void -PythonQtViewStep::next() -{ - CalamaresUtils::lookupAndCall( m_obj, { "next" } ); -} - - -void -PythonQtViewStep::back() -{ - CalamaresUtils::lookupAndCall( m_obj, { "back" } ); -} - - -bool -PythonQtViewStep::isNextEnabled() const -{ - return CalamaresUtils::lookupAndCall( m_obj, { "isNextEnabled", "isnextenabled", "is_next_enabled" } ).toBool(); -} - - -bool -PythonQtViewStep::isBackEnabled() const -{ - return CalamaresUtils::lookupAndCall( m_obj, { "isBackEnabled", "isbackenabled", "is_back_enabled" } ).toBool(); -} - - -bool -PythonQtViewStep::isAtBeginning() const -{ - return CalamaresUtils::lookupAndCall( m_obj, { "isAtBeginning", "isatbeginning", "is_at_beginning" } ).toBool(); -} - - -bool -PythonQtViewStep::isAtEnd() const -{ - return CalamaresUtils::lookupAndCall( m_obj, { "isAtEnd", "isatend", "is_at_end" } ).toBool(); -} - -void -PythonQtViewStep::onActivate() -{ - CalamaresUtils::lookupAndCall( m_obj, { "onActivate", "onactivate", "on_activate" } ); -} - -void -PythonQtViewStep::onLeave() -{ - CalamaresUtils::lookupAndCall( m_obj, { "onLeave", "onleave", "on_leave" } ); -} - - -JobList -PythonQtViewStep::jobs() const -{ - JobList jobs; - - PythonQtObjectPtr jobsCallable = PythonQt::self()->lookupCallable( m_obj, "jobs" ); - if ( jobsCallable.isNull() ) - { - return jobs; - } - - PythonQtObjectPtr response = PythonQt::self()->callAndReturnPyObject( jobsCallable ); - if ( response.isNull() ) - { - return jobs; - } - - PythonQtObjectPtr listPopCallable = PythonQt::self()->lookupCallable( response, "pop" ); - if ( listPopCallable.isNull() ) - { - return jobs; - } - - forever - { - PythonQtObjectPtr aJob = PythonQt::self()->callAndReturnPyObject( listPopCallable, { 0 } ); - if ( aJob.isNull() ) - { - break; - } - - jobs.append( Calamares::job_ptr( new PythonQtJob( m_cxt, aJob ) ) ); - } - - return jobs; -} - - -void -PythonQtViewStep::setConfigurationMap( const QVariantMap& configurationMap ) -{ - m_obj.addVariable( "configuration", configurationMap ); -} - - -QWidget* -PythonQtViewStep::createScriptingConsole() -{ - PythonQtScriptingConsole* console = new PythonQtScriptingConsole( nullptr, m_cxt ); - console->setProperty( "classname", m_cxt.getVariable( "_calamares_module_typename" ).toString() ); - return console; -} - -} // namespace Calamares diff --git a/src/libcalamaresui/viewpages/PythonQtViewStep.h b/src/libcalamaresui/viewpages/PythonQtViewStep.h deleted file mode 100644 index b23a540b9..000000000 --- a/src/libcalamaresui/viewpages/PythonQtViewStep.h +++ /dev/null @@ -1,57 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2016 Teo Mrnjavac - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef PYTHONQTVIEWSTEP_H -#define PYTHONQTVIEWSTEP_H - -#include "ViewStep.h" - -#include - -namespace Calamares -{ - -class PythonQtViewStep : public Calamares::ViewStep -{ - Q_OBJECT -public: - PythonQtViewStep( PythonQtObjectPtr cxt, QObject* parent = nullptr ); - - QString prettyName() const override; - - QWidget* widget() override; - - void next() override; - void back() override; - void onLeave() override; - void onActivate() override; - - bool isNextEnabled() const override; - bool isBackEnabled() const override; - - bool isAtBeginning() const override; - bool isAtEnd() const override; - - JobList jobs() const override; - - void setConfigurationMap( const QVariantMap& configurationMap ) override; - - QWidget* createScriptingConsole(); - -protected: - QWidget* m_widget; - -private: - PythonQtObjectPtr m_cxt; - PythonQtObjectPtr m_obj; -}; - -} // namespace Calamares - -#endif // PYTHONQTVIEWSTEP_H diff --git a/src/libcalamaresui/viewpages/ViewStep.h b/src/libcalamaresui/viewpages/ViewStep.h index c20a9d396..22e72e5fd 100644 --- a/src/libcalamaresui/viewpages/ViewStep.h +++ b/src/libcalamaresui/viewpages/ViewStep.h @@ -29,8 +29,7 @@ namespace Calamares * A view module is a Calamares module which has at least one UI page (exposed as * ViewStep::widget), and can optionally create Calamares jobs at runtime. * As of early 2020, a view module can be implemented by deriving from ViewStep - * in C++ (as a Qt Plugin or a Qml ViewStep) or in Python with the PythonQt interface - * (which also mimics the ViewStep class). + * in C++ (as a Qt Plugin or a Qml ViewStep). * * A ViewStep can describe itself in human-readable format for the SummaryPage * (which shows all of the things which have been collected to be done in the diff --git a/src/libcalamaresui/widgets/ClickableLabel.cpp b/src/libcalamaresui/widgets/ClickableLabel.cpp index be7b142f1..8475a5aea 100644 --- a/src/libcalamaresui/widgets/ClickableLabel.cpp +++ b/src/libcalamaresui/widgets/ClickableLabel.cpp @@ -13,7 +13,8 @@ namespace Calamares { - +namespace Widgets +{ ClickableLabel::ClickableLabel( QWidget* parent ) : QLabel( parent ) @@ -47,5 +48,5 @@ ClickableLabel::mouseReleaseEvent( QMouseEvent* event ) emit clicked(); } } - +} // namespace Widgets } // namespace Calamares diff --git a/src/libcalamaresui/widgets/ClickableLabel.h b/src/libcalamaresui/widgets/ClickableLabel.h index 8c5561677..259f4a71f 100644 --- a/src/libcalamaresui/widgets/ClickableLabel.h +++ b/src/libcalamaresui/widgets/ClickableLabel.h @@ -8,8 +8,8 @@ * */ -#ifndef LIBCALAMARESUI_CLICKABLELABEL_H -#define LIBCALAMARESUI_CLICKABLELABEL_H +#ifndef LIBCALAMARESUI_WIDGETS_CLICKABLELABEL_H +#define LIBCALAMARESUI_WIDGETS_CLICKABLELABEL_H #include #include @@ -18,7 +18,8 @@ namespace Calamares { - +namespace Widgets +{ /** @brief A Label where the whole label area is clickable * * When clicking anywhere on the Label (text, background, whatever) @@ -44,7 +45,7 @@ protected: private: QElapsedTimer m_time; }; - +} // namespace Widgets } // namespace Calamares -#endif // LIBCALAMARESUI_CLICKABLELABEL_H +#endif // LIBCALAMARESUI_WIDGETS_CLICKABLELABEL_H diff --git a/src/libcalamaresui/widgets/PrettyRadioButton.cpp b/src/libcalamaresui/widgets/PrettyRadioButton.cpp index b79f93a25..62e462a58 100644 --- a/src/libcalamaresui/widgets/PrettyRadioButton.cpp +++ b/src/libcalamaresui/widgets/PrettyRadioButton.cpp @@ -20,6 +20,8 @@ namespace Calamares { +namespace Widgets +{ PrettyRadioButton::PrettyRadioButton( QWidget* parent ) : QWidget( parent ) @@ -124,5 +126,5 @@ PrettyRadioButton::toggleOptions( bool toggle ) m_optionsLayout->parentWidget()->setVisible( toggle ); } } - +} // namespace Widgets } // namespace Calamares diff --git a/src/libcalamaresui/widgets/PrettyRadioButton.h b/src/libcalamaresui/widgets/PrettyRadioButton.h index 1874457a8..fd00911e1 100644 --- a/src/libcalamaresui/widgets/PrettyRadioButton.h +++ b/src/libcalamaresui/widgets/PrettyRadioButton.h @@ -7,8 +7,8 @@ * */ -#ifndef LIBCALAMARESUI_PRETTYRADIOBUTTON_H -#define LIBCALAMARESUI_PRETTYRADIOBUTTON_H +#ifndef LIBCALAMARESUI_WIDGETS_PRETTYRADIOBUTTON_H +#define LIBCALAMARESUI_WIDGETS_PRETTYRADIOBUTTON_H #include "DllMacro.h" @@ -21,6 +21,8 @@ class QHBoxLayout; namespace Calamares { +namespace Widgets +{ class ClickableLabel; /** @brief A radio button with fancy label next to it. @@ -72,6 +74,6 @@ protected: QGridLayout* m_mainLayout; QHBoxLayout* m_optionsLayout; }; - +} // namespace Widgets } // namespace Calamares -#endif // LIBCALAMARESUI_PRETTYRADIOBUTTON_H +#endif // LIBCALAMARESUI_WIDGETS_PRETTYRADIOBUTTON_H diff --git a/src/libcalamaresui/widgets/WaitingWidget.cpp b/src/libcalamaresui/widgets/WaitingWidget.cpp index aef5aecf5..18acc11b7 100644 --- a/src/libcalamaresui/widgets/WaitingWidget.cpp +++ b/src/libcalamaresui/widgets/WaitingWidget.cpp @@ -12,46 +12,108 @@ #include "utils/CalamaresUtilsGui.h" -#include "3rdparty/waitingspinnerwidget.h" - #include #include +#include WaitingWidget::WaitingWidget( const QString& text, QWidget* parent ) - : QWidget( parent ) + : WaitingSpinnerWidget( parent, false, false ) { - QBoxLayout* waitingLayout = new QVBoxLayout; - setLayout( waitingLayout ); - waitingLayout->addStretch(); - QBoxLayout* pbLayout = new QHBoxLayout; - waitingLayout->addLayout( pbLayout ); - pbLayout->addStretch(); - - WaitingSpinnerWidget* spnr = new WaitingSpinnerWidget(); - pbLayout->addWidget( spnr ); - - pbLayout->addStretch(); - - m_waitingLabel = new QLabel( text ); - - int spnrSize = m_waitingLabel->fontMetrics().height() * 4; - spnr->setFixedSize( spnrSize, spnrSize ); - spnr->setInnerRadius( spnrSize / 2 ); - spnr->setLineLength( spnrSize / 2 ); - spnr->setLineWidth( spnrSize / 8 ); - spnr->start(); - - m_waitingLabel->setAlignment( Qt::AlignCenter ); - waitingLayout->addSpacing( spnrSize / 2 ); - waitingLayout->addWidget( m_waitingLabel ); - waitingLayout->addStretch(); - - CalamaresUtils::unmarginLayout( waitingLayout ); + int spnrSize = CalamaresUtils::defaultFontHeight() * 4; + setFixedSize( spnrSize, spnrSize ); + setInnerRadius( spnrSize / 2 ); + setLineLength( spnrSize / 2 ); + setLineWidth( spnrSize / 8 ); + setAlignment( Qt::AlignmentFlag::AlignBottom ); + setText( text ); + start(); } +WaitingWidget::~WaitingWidget() {} + +struct CountdownWaitingWidget::Private +{ + std::chrono::seconds duration; + // int because we count down, need to be able to show a 0, + // and then wrap around to duration a second later. + int count = 0; + QTimer* timer = nullptr; + + Private( std::chrono::seconds seconds, QWidget* parent ) + : duration( seconds ) + , timer( new QTimer( parent ) ) + { + } +}; + +CountdownWaitingWidget::CountdownWaitingWidget( std::chrono::seconds duration, QWidget* parent ) + : WaitingSpinnerWidget( parent, false, false ) + , d( std::make_unique< Private >( duration, this ) ) +{ + // Set up the label first for sizing + const int labelHeight = qBound( 16, CalamaresUtils::defaultFontHeight() * 3 / 2, 64 ); + + // Set up the spinner + setFixedSize( labelHeight, labelHeight ); + setRevolutionsPerSecond( 1.0 / double( duration.count() ) ); + setInnerRadius( labelHeight / 2 ); + setLineLength( labelHeight / 2 ); + setLineWidth( labelHeight / 8 ); + setAlignment( Qt::AlignmentFlag::AlignVCenter ); + + // Last because it updates the text + setInterval( duration ); + + d->timer->setInterval( std::chrono::seconds( 1 ) ); + connect( d->timer, &QTimer::timeout, this, &CountdownWaitingWidget::tick ); +} + +CountdownWaitingWidget::~CountdownWaitingWidget() +{ + d->timer->stop(); +} void -WaitingWidget::setText( const QString& text ) +CountdownWaitingWidget::setInterval( std::chrono::seconds duration ) { - m_waitingLabel->setText( text ); + d->duration = duration; + d->count = int( duration.count() ); + tick(); +} + +void +CountdownWaitingWidget::start() +{ + // start it from the top + if ( d->count <= 0 ) + { + d->count = int( d->duration.count() ); + tick(); + } + d->timer->start(); + WaitingSpinnerWidget::start(); +} + +void +CountdownWaitingWidget::stop() +{ + d->timer->stop(); + WaitingSpinnerWidget::stop(); +} + +void +CountdownWaitingWidget::tick() +{ + // We do want to **display** a 0 which is why we wrap around only + // after counting down from 0. + d->count--; + if ( d->count < 0 ) + { + d->count = int( d->duration.count() ); + } + setText( QString::number( d->count ) ); + if ( d->count == 0 ) + { + timeout(); + } } diff --git a/src/libcalamaresui/widgets/WaitingWidget.h b/src/libcalamaresui/widgets/WaitingWidget.h index 850b81ca9..1b78809de 100644 --- a/src/libcalamaresui/widgets/WaitingWidget.h +++ b/src/libcalamaresui/widgets/WaitingWidget.h @@ -10,20 +10,61 @@ #ifndef WAITINGWIDGET_H #define WAITINGWIDGET_H -#include +#include "widgets/waitingspinnerwidget.h" + +#include +#include class QLabel; +class QTimer; -class WaitingWidget : public QWidget +/** @brief A spinner and a label below it + * + * The spinner has a fixed size of 4* the font height, + * and the text is displayed centered below it. Use this + * to display a long-term waiting situation with a status report. + */ +class WaitingWidget : public WaitingSpinnerWidget +{ +public: + /// Create a WaitingWidget with initial @p text label. + explicit WaitingWidget( const QString& text, QWidget* parent = nullptr ); + ~WaitingWidget() override; +}; + +/** @brief A spinner and a countdown next to it + * + * The spinner is sized to the text-height and displays a + * numeric countdown next to it. The countdown is updated + * every second. The signal timeout() is sent every time + * the countdown reaches 0. + */ +class CountdownWaitingWidget : public WaitingSpinnerWidget { Q_OBJECT public: - explicit WaitingWidget( const QString& text, QWidget* parent = nullptr ); + /// Create a countdown widget with a given @p duration + explicit CountdownWaitingWidget( std::chrono::seconds duration = std::chrono::seconds( 5 ), + QWidget* parent = nullptr ); + ~CountdownWaitingWidget() override; - void setText( const QString& text ); + /// Changes the duration used and resets the countdown + void setInterval( std::chrono::seconds duration ); + + /// Start the countdown, resets to the full duration + void start(); + /// Stop the countdown + void stop(); + +Q_SIGNALS: + void timeout(); + +protected Q_SLOTS: + void tick(); private: - QLabel* m_waitingLabel; + struct Private; + std::unique_ptr< Private > d; }; #endif // WAITINGWIDGET_H diff --git a/src/libcalamaresui/widgets/waitingspinnerwidget.cpp b/src/libcalamaresui/widgets/waitingspinnerwidget.cpp new file mode 100644 index 000000000..3073e9b97 --- /dev/null +++ b/src/libcalamaresui/widgets/waitingspinnerwidget.cpp @@ -0,0 +1,390 @@ +/* + * SPDX-FileCopyrightText: 2012-2014 Alexander Turkin + * SPDX-FileCopyrightText: 2014 William Hallatt + * SPDX-FileCopyrightText: 2015 Jacob Dawid + * SPDX-FileCopyrightText: 2018 huxingyi + * SPDX-License-Identifier: MIT + */ + +/* Original Work Copyright (c) 2012-2014 Alexander Turkin + Modified 2014 by William Hallatt + Modified 2015 by Jacob Dawid + +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 "waitingspinnerwidget.h" + +#include +#include +#include + +static bool +isAlignCenter( Qt::AlignmentFlag a ) +{ + return a == Qt::AlignmentFlag::AlignVCenter; +} + +static int +lineCountDistanceFromPrimary( int current, int primary, int totalNrOfLines ) +{ + int distance = primary - current; + if ( distance < 0 ) + { + distance += totalNrOfLines; + } + return distance; +} + +static QColor +currentLineColor( int countDistance, int totalNrOfLines, qreal trailFadePerc, qreal minOpacity, QColor color ) +{ + if ( countDistance == 0 ) + { + return color; + } + const qreal minAlphaF = minOpacity / 100.0; + int distanceThreshold = static_cast< int >( qCeil( ( totalNrOfLines - 1 ) * trailFadePerc / 100.0 ) ); + if ( countDistance > distanceThreshold ) + { + color.setAlphaF( minAlphaF ); + } + else + { + qreal alphaDiff = color.alphaF() - minAlphaF; + qreal gradient = alphaDiff / static_cast< qreal >( distanceThreshold + 1 ); + qreal resultAlpha = color.alphaF() - gradient * countDistance; + + // If alpha is out of bounds, clip it. + resultAlpha = qBound( 0.0, resultAlpha, 1.0 ); + color.setAlphaF( resultAlpha ); + } + return color; +} + +WaitingSpinnerWidget::WaitingSpinnerWidget( QWidget* parent, bool centerOnParent, bool disableParentWhenSpinning ) + : WaitingSpinnerWidget( Qt::WindowModality::NonModal, parent, centerOnParent, disableParentWhenSpinning ) +{ +} + +WaitingSpinnerWidget::WaitingSpinnerWidget( Qt::WindowModality modality, + QWidget* parent, + bool centerOnParent, + bool disableParentWhenSpinning ) + : QWidget( parent, + modality == Qt::WindowModality::NonModal ? Qt::WindowFlags() : Qt::Dialog | Qt::FramelessWindowHint ) + , _centerOnParent( centerOnParent ) + , _disableParentWhenSpinning( disableParentWhenSpinning ) +{ + _timer = new QTimer( this ); + connect( _timer, SIGNAL( timeout() ), this, SLOT( rotate() ) ); + updateSize(); + updateTimer(); + hide(); + + // We need to set the window modality AFTER we've hidden the + // widget for the first time since changing this property while + // the widget is visible has no effect. + // + // Non-modal windows don't need any work + if ( modality != Qt::WindowModality::NonModal ) + { + setWindowModality( modality ); + setAttribute( Qt::WA_TranslucentBackground ); + } +} + +void +WaitingSpinnerWidget::paintEvent( QPaintEvent* ) +{ + updatePosition(); + QPainter painter( this ); + painter.fillRect( this->rect(), Qt::transparent ); + painter.setRenderHint( QPainter::Antialiasing, true ); + + if ( _currentCounter >= _numberOfLines ) + { + _currentCounter = 0; + } + + painter.setPen( Qt::NoPen ); + for ( int i = 0; i < _numberOfLines; ++i ) + { + painter.save(); + painter.translate( _innerRadius + _lineLength, _innerRadius + _lineLength ); + painter.translate( ( width() - _imageSize.width() ) / 2, 0 ); + qreal rotateAngle = static_cast< qreal >( 360 * i ) / static_cast< qreal >( _numberOfLines ); + painter.rotate( rotateAngle ); + painter.translate( _innerRadius, 0 ); + int distance = lineCountDistanceFromPrimary( i, _currentCounter, _numberOfLines ); + QColor color = currentLineColor( distance, _numberOfLines, _trailFadePercentage, _minimumTrailOpacity, _color ); + painter.setBrush( color ); + // TODO improve the way rounded rect is painted + painter.drawRoundedRect( + QRect( 0, -_lineWidth / 2, _lineLength, _lineWidth ), _roundness, _roundness, Qt::RelativeSize ); + painter.restore(); + } + + if ( !_text.isEmpty() ) + { + painter.setPen( QPen( _textColor ) ); + if ( isAlignCenter( alignment() ) ) + { + painter.drawText( QRect( 0, 0, width(), height() ), Qt::AlignVCenter | Qt::AlignHCenter, _text ); + } + else + { + painter.drawText( QRect( 0, _imageSize.height(), width(), height() - _imageSize.height() ), + Qt::AlignBottom | Qt::AlignHCenter, + _text ); + } + } +} + +void +WaitingSpinnerWidget::start() +{ + updatePosition(); + _isSpinning = true; + show(); + + if ( parentWidget() && _disableParentWhenSpinning ) + { + parentWidget()->setEnabled( false ); + } + + if ( !_timer->isActive() ) + { + _timer->start(); + _currentCounter = 0; + } +} + +void +WaitingSpinnerWidget::stop() +{ + _isSpinning = false; + hide(); + + if ( parentWidget() && _disableParentWhenSpinning ) + { + parentWidget()->setEnabled( true ); + } + + if ( _timer->isActive() ) + { + _timer->stop(); + _currentCounter = 0; + } +} + +void +WaitingSpinnerWidget::setNumberOfLines( int lines ) +{ + _numberOfLines = lines; + _currentCounter = 0; + updateTimer(); +} + +void +WaitingSpinnerWidget::setLineLength( int length ) +{ + _lineLength = length; + updateSize(); +} + +void +WaitingSpinnerWidget::setLineWidth( int width ) +{ + _lineWidth = width; + updateSize(); +} + +void +WaitingSpinnerWidget::setInnerRadius( int radius ) +{ + _innerRadius = radius; + updateSize(); +} + +void +WaitingSpinnerWidget::setText( const QString& text ) +{ + _text = text; + updateSize(); +} + +void +WaitingSpinnerWidget::setAlignment( Qt::AlignmentFlag align ) +{ + _alignment = align; + updateSize(); +} + +QColor +WaitingSpinnerWidget::color() const +{ + return _color; +} + +QColor +WaitingSpinnerWidget::textColor() const +{ + return _textColor; +} + +QString +WaitingSpinnerWidget::text() const +{ + return _text; +} + +qreal +WaitingSpinnerWidget::roundness() const +{ + return _roundness; +} + +qreal +WaitingSpinnerWidget::minimumTrailOpacity() const +{ + return _minimumTrailOpacity; +} + +qreal +WaitingSpinnerWidget::trailFadePercentage() const +{ + return _trailFadePercentage; +} + +qreal +WaitingSpinnerWidget::revolutionsPersSecond() const +{ + return _revolutionsPerSecond; +} + +int +WaitingSpinnerWidget::numberOfLines() const +{ + return _numberOfLines; +} + +int +WaitingSpinnerWidget::lineLength() const +{ + return _lineLength; +} + +int +WaitingSpinnerWidget::lineWidth() const +{ + return _lineWidth; +} + +int +WaitingSpinnerWidget::innerRadius() const +{ + return _innerRadius; +} + +bool +WaitingSpinnerWidget::isSpinning() const +{ + return _isSpinning; +} + +void +WaitingSpinnerWidget::setRoundness( qreal roundness ) +{ + _roundness = qBound( 0.0, roundness, 100.0 ); +} + +void +WaitingSpinnerWidget::setColor( QColor color ) +{ + _color = color; +} + +void +WaitingSpinnerWidget::setTextColor( QColor color ) +{ + _textColor = color; +} + +void +WaitingSpinnerWidget::setRevolutionsPerSecond( qreal revolutionsPerSecond ) +{ + _revolutionsPerSecond = revolutionsPerSecond; + updateTimer(); +} + +void +WaitingSpinnerWidget::setTrailFadePercentage( qreal trail ) +{ + _trailFadePercentage = trail; +} + +void +WaitingSpinnerWidget::setMinimumTrailOpacity( qreal minimumTrailOpacity ) +{ + _minimumTrailOpacity = minimumTrailOpacity; +} + +void +WaitingSpinnerWidget::rotate() +{ + ++_currentCounter; + if ( _currentCounter >= _numberOfLines ) + { + _currentCounter = 0; + } + update(); +} + +void +WaitingSpinnerWidget::updateSize() +{ + int size = ( _innerRadius + _lineLength ) * 2; + _imageSize = QSize( size, size ); + if ( _text.isEmpty() || isAlignCenter( alignment() ) ) + { + setFixedSize( size, size ); + } + else + { + QFontMetrics fm( font() ); + QSize textSize = QSize( fm.horizontalAdvance( _text ), fm.height() ); + setFixedSize( qMax( size, textSize.width() ), size + size / 4 + textSize.height() ); + } +} + +void +WaitingSpinnerWidget::updateTimer() +{ + // Old-style interval in milliseconds; force to int to suppress warning + _timer->setInterval( int( 1000 / ( _numberOfLines * _revolutionsPerSecond ) ) ); +} + +void +WaitingSpinnerWidget::updatePosition() +{ + if ( parentWidget() && _centerOnParent ) + { + move( parentWidget()->width() / 2 - width() / 2, parentWidget()->height() / 2 - height() / 2 ); + } +} diff --git a/src/libcalamaresui/widgets/waitingspinnerwidget.h b/src/libcalamaresui/widgets/waitingspinnerwidget.h new file mode 100644 index 000000000..ce4a4cbff --- /dev/null +++ b/src/libcalamaresui/widgets/waitingspinnerwidget.h @@ -0,0 +1,157 @@ +/* + * SPDX-FileCopyrightText: 2012-2014 Alexander Turkin + * SPDX-FileCopyrightText: 2014 William Hallatt + * SPDX-FileCopyrightText: 2015 Jacob Dawid + * SPDX-FileCopyrightText: 2018 huxingyi + * SPDX-License-Identifier: MIT + */ + +/* Original Work Copyright (c) 2012-2014 Alexander Turkin + Modified 2014 by William Hallatt + Modified 2015 by Jacob Dawid + +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 + +// Qt includes +#include +#include +#include + +class WaitingSpinnerWidget : public QWidget +{ + Q_OBJECT +public: + /** @brief Constructor for "standard" widget behaviour + * + * Use this constructor if you wish to, e.g. embed your widget in another. + */ + WaitingSpinnerWidget( QWidget* parent = nullptr, + bool centerOnParent = true, + bool disableParentWhenSpinning = true ); + + /** @brief Constructor + * + * Use this constructor to automatically create a modal + * ("blocking") spinner on top of the calling widget/window. If a valid + * parent widget is provided, "centreOnParent" will ensure that + * QtWaitingSpinner automatically centres itself on it, if not, + * @p centerOnParent is ignored. + */ + WaitingSpinnerWidget( Qt::WindowModality modality, + QWidget* parent = nullptr, + bool centerOnParent = true, + bool disableParentWhenSpinning = true ); + + WaitingSpinnerWidget( const WaitingSpinnerWidget& ) = delete; + WaitingSpinnerWidget& operator=( const WaitingSpinnerWidget& ) = delete; + + void setColor( QColor color ); + void setTextColor( QColor color ); + void setRoundness( qreal roundness ); + void setMinimumTrailOpacity( qreal minimumTrailOpacity ); + void setTrailFadePercentage( qreal trail ); + void setRevolutionsPerSecond( qreal revolutionsPerSecond ); + void setNumberOfLines( int lines ); + void setLineLength( int length ); + void setLineWidth( int width ); + void setInnerRadius( int radius ); + + /** @brief Sets the text displayed in or below the spinner + * + * If the text is empty, no text is displayed. The text is displayed + * in or below the spinner depending on the value of alignment(). + * With AlignBottom, the text is displayed below the spinner, + * centered horizontally relative to the spinner; any other alignment + * will put the text in the middle of the spinner itself. + */ + void setText( const QString& text ); + /** @brief Sets the alignment of text for the spinner + * + * The only meaningful values are AlignBottom and AlignVCenter, + * for text below the spinner and text in the middle. + */ + void setAlignment( Qt::AlignmentFlag align ); + /// Convenience to set text-in-the-middle (@c true) or text-at-bottom (@c false) + void setCenteredText( bool centered ) + { + setAlignment( centered ? Qt::AlignmentFlag::AlignVCenter : Qt::AlignmentFlag::AlignBottom ); + } + + QColor color() const; + QColor textColor() const; + QString text() const; + Qt::AlignmentFlag alignment() const { return _alignment; } + qreal roundness() const; + qreal minimumTrailOpacity() const; + qreal trailFadePercentage() const; + qreal revolutionsPersSecond() const; + int numberOfLines() const; + int lineLength() const; + int lineWidth() const; + int innerRadius() const; + + bool isSpinning() const; + +public Q_SLOTS: + void start(); + void stop(); + +private Q_SLOTS: + void rotate(); + +protected: + void paintEvent( QPaintEvent* paintEvent ) override; + +private: + void updateSize(); + void updateTimer(); + void updatePosition(); + +private: + // PI, leading to a full fade in one whole revolution + static constexpr const auto radian = 3.14159265358979323846; + + // Spinner-wheel related settings + QColor _color = Qt::black; + qreal _roundness = 100.0; // 0..100 + qreal _minimumTrailOpacity = radian; + qreal _trailFadePercentage = 80.0; + qreal _revolutionsPerSecond = radian / 2; + int _numberOfLines = 20; + int _lineLength = 10; + int _lineWidth = 2; + int _innerRadius = 10; + QSize _imageSize; + + // Text-related settings + Qt::AlignmentFlag _alignment = Qt::AlignmentFlag::AlignBottom; + QString _text; + QColor _textColor = Qt::black; + + // Environment settings + bool _centerOnParent = true; + bool _disableParentWhenSpinning = true; + + // Internal bits + QTimer* _timer = nullptr; + int _currentCounter = 0; + bool _isSpinning = false; +}; diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt index 03384105e..bb7335316 100644 --- a/src/modules/CMakeLists.txt +++ b/src/modules/CMakeLists.txt @@ -8,7 +8,7 @@ # individual modules can also decide they must be skipped (e.g. OS-specific # modules, or ones with unmet dependencies). Collect the skipped modules # in this list. -set( LIST_SKIPPED_MODULES "" ) +set(LIST_SKIPPED_MODULES "") include_directories( ${CMAKE_SOURCE_DIR}/src/libcalamares @@ -16,29 +16,46 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/libcalamaresui ) -string( REPLACE " " ";" SKIP_LIST "${SKIP_MODULES}" ) +string(REPLACE " " ";" SKIP_LIST "${SKIP_MODULES}") -file( GLOB SUBDIRECTORIES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*" ) -list( SORT SUBDIRECTORIES ) +file(GLOB SUBDIRECTORIES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*") +list(SORT SUBDIRECTORIES) -foreach( SUBDIRECTORY ${SUBDIRECTORIES} ) +foreach(SUBDIRECTORY ${SUBDIRECTORIES}) calamares_add_module_subdirectory( ${SUBDIRECTORY} LIST_SKIPPED_MODULES ) endforeach() -# TODO:3.3: Use FindPython3 -if ( BUILD_TESTING AND BUILD_SCHEMA_TESTING AND PYTHONINTERP_FOUND AND PYTHON_EXECUTABLE ) +if(BUILD_TESTING AND BUILD_SCHEMA_TESTING AND Python_Interpreter_FOUND) # The tests for each config file are independent of whether the # module is enabled or not: the config file should match its schema # regardless. - foreach( SUBDIRECTORY ${SUBDIRECTORIES} ) - set( _schema_file "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/${SUBDIRECTORY}.schema.yaml" ) - set( _conf_file "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/${SUBDIRECTORY}.conf" ) - if ( EXISTS "${_schema_file}" AND EXISTS "${_conf_file}" ) - add_test( - NAME validate-${SUBDIRECTORY} - COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_SOURCE_DIR}/ci/configvalidator.py" "${_schema_file}" "${_conf_file}" - ) + foreach(SUBDIRECTORY ${SUBDIRECTORIES}) + set(_schema_file "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/${SUBDIRECTORY}.schema.yaml") + # Collect config files from the module-directory and from a tests/ subdir, + # using the same mechanism to find those test-config-files as function + # calamares_add_module_subdirectory() would do. + set(_conf_files "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/${SUBDIRECTORY}.conf") + set(_count 1) + set(_testdir "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/tests") + while(EXISTS "${_testdir}/${_count}.global" OR EXISTS "${_testdir}/${_count}.job") + if(EXISTS "${_testdir}/${_count}.job") + list(APPEND _conf_files "${_testdir}/${_count}.job") + endif() + math(EXPR _count "${_count} + 1") + endwhile() + + if(EXISTS "${_schema_file}") + foreach(_conf_file ${_conf_files}) + if(EXISTS ${_conf_file}) + get_filename_component(_conf_base "${_conf_file}" NAME_WE) + add_test( + NAME validate-${SUBDIRECTORY}-${_conf_base} + COMMAND + ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/ci/configvalidator.py" "${_schema_file}" + "${_conf_file}" + ) + endif() + endforeach() endif() endforeach() endif() - diff --git a/src/modules/README.md b/src/modules/README.md index e5bd2e7b6..e654177c7 100644 --- a/src/modules/README.md +++ b/src/modules/README.md @@ -180,26 +180,40 @@ it is possible to take the whole installation-process into account for determining the relative weights there. -## Global storage keys +## Global Storage keys -Some modules place values in global storage so that they can be referenced later by other modules or even other parts of the same module. The following table represents a partial list of the values available as well as where they originate from and which module consume them. +Some modules place values in Global Storage so that they can be referenced later by other modules or even other parts of the same module. The following table represents a partial list of the values available as well as where they originate from and which module consume them. +Keys whose name is followed by a `+` are **structured** data, and have +entries (which start with `+`) below the parent key describing subkeys. +Some structured keys refer to other documentation sources. -Key |Source |Consumers|Description -------------------|----------------|---|--- -btrfsSubvolumes |mount |fstab|List of maps containing the mountpoint and btrtfs subvolume +Key |Source |Consumers |Description +------------------|----------------|---------------|--- +bootloader + |partition | |Bootloader location +\+ installPath | | |Device (e.g. `/dev/sda`) where the bootloader is installed +branding + | | |See `src/branding/README.md` +btrfsSubvolumes |mount |fstab |List of maps containing the mountpoint and btrtfs subvolume btrfsRootSubvolume|mount |bootloader, luksopenswaphook|String containing the subvolume mounted at root efiSystemPartition|partition |bootloader, fstab|String containing the path to the ESP relative to the installed system extraMounts |mount |unpackfs|List of maps holding metadata for the temporary mountpoints used by the installer -fullname |users ||The full username (e.g. "Jane Q. Public") -hostname |users ||A string containing the hostname of the new system -netinstallAdd |packagechooser |netinstall|Data to add to netinstall tree. Same format as netinstall.yaml -netinstallSelect |packagechooser |netinstall|List of group names to select in the netinstall tree -partitions |partition, rawfs|numerous modules|List of maps of metadata about each partition -rootMountPoint |mount |numerous modules|A string with the absolute path to the root mountpoint +fullname |users | |The full username (e.g. "Jane Q. Public") +hostname |users | |A string containing the hostname of the new system +netinstallAdd |packagechooser |netinstall |Data to add to netinstall tree. Same format as netinstall.yaml +netinstallSelect |packagechooser |netinstall |List of group names to select in the netinstall tree +packageOperations +|packagechooser, netinstall|packages|Operations to perform +\+ (list data) | | |See `packages.conf` +partitions + |partition, rawfs|(many) |List of maps of metadata about each partition +\+ device | | |path to the partition device +\+ fs | | |the name of the file system +\+ mountPoint | | |where the device should be mounted +\+ uuid | | |the UUID of the partition device +rootMountPoint |mount |(many) |A string with the absolute path to the root mountpoint username |users |networkcfg, plasmainf, preservefiles|A string containing the username of the new user zfsDatasets |zfs |bootloader, grubcfg, mount|List of maps of zfs datasets including the name and mount information -zfsInfo |partition |mount, zfs|List of encrypted zfs partitions and the encription info -zfsPoolInfo |zfs |mount, umount|List of maps of zfs pool info including the name and mountpoint +zfsInfo |partition |mount, zfs |List of encrypted zfs partitions and the encription info +zfsPoolInfo |zfs |mount, umount |List of maps of zfs pool info including the name and mountpoint + + ## C++ modules diff --git a/src/modules/bootloader/bootloader.conf b/src/modules/bootloader/bootloader.conf index c9d5c78bb..bac9e517f 100644 --- a/src/modules/bootloader/bootloader.conf +++ b/src/modules/bootloader/bootloader.conf @@ -13,19 +13,21 @@ # Possible options are 'grub', 'sb-shim' and 'systemd-boot'. efiBootLoader: "grub" -# systemd-boot configuration files settings, set kernel and initramfs file names +# systemd-boot configuration files settings, set kernel search path, kernel name # and amount of time before default selection boots -kernel: "/vmlinuz-linux" -img: "/initramfs-linux.img" -fallback: "/initramfs-linux-fallback.img" +kernelSearchPath: "/usr/lib/modules" +kernelName: "vmlinuz" timeout: "10" -# Optionally set the menu entry name and kernel name to use in systemd-boot. +# additionalInitrdFiles is a comma seperated list of file names +additionalInitrdFiles: + - "/boot/amd-ucode" + - "/boot/intel-ucode" + +# Optionally set the menu entry name to use in systemd-boot. # If not specified here, these settings will be taken from branding.desc. # # bootloaderEntryName: "Generic GNU/Linux" -# kernelLine: ", with Stable-Kernel" -# fallbackKernelLine: ", with Stable-Kernel (fallback initramfs)" # GRUB 2 binary names and boot directory # Some distributions (e.g. Fedora) use grub2-* (resp. /boot/grub2/) names. diff --git a/src/modules/bootloader/bootloader.schema.yaml b/src/modules/bootloader/bootloader.schema.yaml index 152d3ab72..0849f6865 100644 --- a/src/modules/bootloader/bootloader.schema.yaml +++ b/src/modules/bootloader/bootloader.schema.yaml @@ -7,10 +7,13 @@ additionalProperties: false type: object properties: efiBootLoader: { type: string } - kernel: { type: string } - img: { type: string } - fallback: { type: string } + kernelSearchPath: { type: string } + kernelName: { type: string } timeout: { type: string } # Inserted verbatim + additionalInitrdFiles: + type: array + items: + type: string bootloaderEntryName: { type: string } kernelLine: { type: string } fallbackKernelLine: { type: string } @@ -27,9 +30,10 @@ properties: required: - efiBootLoader - - kernel - - img + - kernelSearchPath + - kernelName - grubInstall - grubMkconfig - grubCfg - grubProbe + - machineid diff --git a/src/modules/bootloader/main.py b/src/modules/bootloader/main.py index fb8e19ac2..cc22746dd 100644 --- a/src/modules/bootloader/main.py +++ b/src/modules/bootloader/main.py @@ -136,18 +136,18 @@ def is_zfs_root(partition): return partition["mountPoint"] == "/" and partition["fs"] == "zfs" -def create_systemd_boot_conf(install_path, efi_dir, uuid, entry, entry_name, kernel_type): +def create_systemd_boot_conf(installation_root_path, efi_dir, uuid, entry, kernel, kernel_type, kernel_version): """ Creates systemd-boot configuration files based on given parameters. - :param install_path: - :param efi_dir: - :param uuid: - :param entry: - :param entry_name: - :param kernel_type: + :param installation_root_path: A string containing the absolute path to the root of the installation + :param efi_dir: A string containing the path to the efi dir relative to the root of the installation + :param uuid: A string containing the UUID of the root volume + :param entry: A string containing the name of the entry as it will be displayed on boot + :param kernel: A string containing the path to the kernel relative to the root of the installation + :param kernel_type: A string which should be set if there is a special version of the entry, for example "fallback" + :param kernel_version: The kernel version string """ - kernel = libcalamares.job.configuration["kernel"] kernel_params = ["quiet"] partitions = libcalamares.globalstorage.value("partitions") @@ -208,42 +208,59 @@ def create_systemd_boot_conf(install_path, efi_dir, uuid, entry, entry_name, ker kernel_params.append("resume=/dev/mapper/{!s}".format( swap_outer_mappername)) - kernel_line = get_kernel_line(kernel_type) - libcalamares.utils.debug("Configure: \"{!s}\"".format(kernel_line)) + libcalamares.utils.debug("Configure: \"{!s}\"".format(f"{entry} {kernel_version}")) if kernel_type == "fallback": - img = libcalamares.job.configuration["fallback"] - entry_name = entry_name + "-fallback" + version_string = kernel_version + "-fallback" + initrd = "initrd-fallback" else: - img = libcalamares.job.configuration["img"] + version_string = kernel_version + initrd = "initrd" - conf_path = os.path.join(install_path + efi_dir, + # get the machine-id + with open(os.path.join(installation_root_path, "etc", "machine-id"), 'r') as machineid_file: + machine_id = machineid_file.read().rstrip('\n') + + # Copy kernel to a subdirectory of /efi partition + machine_dir = os.path.join(installation_root_path + efi_dir, machine_id) + os.makedirs(machine_dir, exist_ok=True) + + target_efi_files_dir = os.path.join(machine_dir, kernel_version) + os.makedirs(target_efi_files_dir, exist_ok=True) + + kernel_path = os.path.join(installation_root_path, kernel) + kernel_name = os.path.basename(kernel_path) + shutil.copyfile(kernel_path, os.path.join(target_efi_files_dir, "linux")) + + # write the entry + lines = [ + '## Generated by Calamares\n', + '\n', + "title {!s}\n".format(entry), + "version {!s}\n".format(version_string), + "machine-id {!s}\n".format(machine_id), + "linux {!s}\n".format(os.path.join("/", machine_id, kernel_version, "linux")), + ] + + try: + additional_initrd_files = libcalamares.job.configuration["additionalInitrdFiles"] + for initrd_file in additional_initrd_files: + libcalamares.utils.debug("Attempting to handle initrd image " + initrd_file) + if os.path.isfile(os.path.join(installation_root_path, initrd_file.lstrip('/'))): + libcalamares.utils.debug("Found image " + initrd_file) + shutil.copyfile(os.path.join(installation_root_path, initrd_file.lstrip('/')), os.path.join(target_efi_files_dir, os.path.basename(initrd_file))) + lines.append("initrd {!s}\n".format(os.path.join("/", machine_id, kernel_version, os.path.basename(initrd_file)))) + except KeyError: # If the configuration option isn't set, we can just move on + libcalamares.utils.debug("Failed to find key additionalInitrdFiles") + pass + + lines.append("initrd {!s}\n".format(os.path.join("/", machine_id, kernel_version, initrd))) + lines.append("options {!s} rw\n".format(" ".join(kernel_params))) + + conf_path = os.path.join(installation_root_path + efi_dir, "loader", "entries", - entry_name + ".conf") - - # Copy kernel and initramfs to a subdirectory of /efi partition - files_dir = os.path.join(install_path + efi_dir, entry_name) - os.makedirs(files_dir, exist_ok=True) - - kernel_path = install_path + kernel - kernel_name = os.path.basename(kernel_path) - shutil.copyfile(kernel_path, os.path.join(files_dir, kernel_name)) - - img_path = install_path + img - img_name = os.path.basename(img_path) - shutil.copyfile(img_path, os.path.join(files_dir, img_name)) - - lines = [ - '## This is just an example config file.\n', - '## Please edit the paths and kernel parameters according\n', - '## to your system.\n', - '\n', - "title {!s}{!s}\n".format(entry, kernel_line), - "linux {!s}\n".format(os.path.join("/", entry_name, kernel_name)), - "initrd {!s}\n".format(os.path.join("/", entry_name, img_name)), - "options {!s} rw\n".format(" ".join(kernel_params)), - ] + machine_id + "-" + version_string + ".conf") with open(conf_path, 'w') as conf_file: for line in lines: @@ -465,6 +482,30 @@ def efi_boot_next(): if boot_entry: subprocess.call([boot_mgr, "-n", boot_entry]) +def get_kernels(installation_root_path): + """ + Gets a list of kernels and associated values for each kernel. This will work as is for many distros. + If not, it should be safe to modify it to better support your distro + + :param installation_root_path: A string with the absolute path to the root of the installation + + Returns a list of 3-tuples + + Each 3-tuple contains the kernel, kernel_type and kernel_version + """ + kernel_search_path = libcalamares.job.configuration["kernelSearchPath"] + source_kernel_name = libcalamares.job.configuration["kernelName"] + kernel_list = [] + + # find all the installed kernels and generate default and fallback entries for each + for root, dirs, files in os.walk(os.path.join(installation_root_path, kernel_search_path.lstrip('/'))): + for file in files: + if file == source_kernel_name: + rel_root = os.path.relpath(root, installation_root_path) + kernel_list.append((os.path.join(rel_root, file),"default",os.path.basename(root))) + kernel_list.append((os.path.join(rel_root, file),"fallback",os.path.basename(root))) + + return kernel_list def install_systemd_boot(efi_directory): """ @@ -473,8 +514,8 @@ def install_systemd_boot(efi_directory): :param efi_directory: """ libcalamares.utils.debug("Bootloader: systemd-boot") - install_path = libcalamares.globalstorage.value("rootMountPoint") - install_efi_directory = install_path + efi_directory + installation_root_path = libcalamares.globalstorage.value("rootMountPoint") + install_efi_directory = installation_root_path + efi_directory uuid = get_uuid() distribution = get_bootloader_entry_name() distribution_translated = distribution.translate(file_name_sanitizer) @@ -484,21 +525,17 @@ def install_systemd_boot(efi_directory): subprocess.call(["bootctl", "--path={!s}".format(install_efi_directory), "install"]) - create_systemd_boot_conf(install_path, - efi_directory, - uuid, - distribution, - distribution_translated, - "default") - if "fallback" in libcalamares.job.configuration: - create_systemd_boot_conf(install_path, - efi_directory, - uuid, - distribution, - distribution_translated, - "fallback") - create_loader(loader_path, distribution_translated) + for (kernel, kernel_type, kernel_version) in get_kernels(installation_root_path): + create_systemd_boot_conf(installation_root_path, + efi_directory, + uuid, + distribution, + kernel, + kernel_type, + kernel_version) + + create_loader(loader_path, distribution_translated) def get_grub_efi_parameters(): """ @@ -616,8 +653,8 @@ def install_grub(efi_directory, fw_type): if fw_type == "efi": libcalamares.utils.debug("Bootloader: grub (efi)") - install_path = libcalamares.globalstorage.value("rootMountPoint") - install_efi_directory = install_path + efi_directory + installation_root_path = libcalamares.globalstorage.value("rootMountPoint") + install_efi_directory = installation_root_path + efi_directory if not os.path.isdir(install_efi_directory): os.makedirs(install_efi_directory) @@ -668,8 +705,8 @@ def install_secureboot(efi_directory): """ efi_bootloader_id = efi_label(efi_directory) - install_path = libcalamares.globalstorage.value("rootMountPoint") - install_efi_directory = install_path + efi_directory + installation_root_path = libcalamares.globalstorage.value("rootMountPoint") + install_efi_directory = installation_root_path + efi_directory if efi_word_size() == "64": install_efi_bin = "shimx64.efi" @@ -761,8 +798,12 @@ def run(): fw_type = libcalamares.globalstorage.value("firmwareType") - if (libcalamares.globalstorage.value("bootLoader") is None and fw_type != "efi"): - libcalamares.utils.warning( "Non-EFI system, and no bootloader is set." ) + if libcalamares.globalstorage.value("bootLoader") is None: + # Don't want a bootloader, but do log that this has an effect: + if fw_type != "efi": + libcalamares.utils.warning( "Non-EFI system, and no bootloader is set." ) + else: + libcalamares.utils.warning( "EFI system, and no bootloader is set." ) return None partitions = libcalamares.globalstorage.value("partitions") diff --git a/src/modules/contextualprocess/CMakeLists.txt b/src/modules/contextualprocess/CMakeLists.txt index d7716bbfb..9520515ce 100644 --- a/src/modules/contextualprocess/CMakeLists.txt +++ b/src/modules/contextualprocess/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -calamares_add_plugin( contextualprocess +calamares_add_plugin(contextualprocess TYPE job EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -15,7 +15,6 @@ calamares_add_test( contextualprocesstest SOURCES Tests.cpp - ContextualProcessJob.cpp # Builds it a second time - LIBRARIES - yamlcpp::yamlcpp + ContextualProcessJob.cpp # Builds it a second time + LIBRARIES yamlcpp::yamlcpp ) diff --git a/src/modules/displaymanager/displaymanager.conf b/src/modules/displaymanager/displaymanager.conf index 0fd2af163..c5c0e0b78 100644 --- a/src/modules/displaymanager/displaymanager.conf +++ b/src/modules/displaymanager/displaymanager.conf @@ -22,7 +22,6 @@ displaymanagers: - gdm - mdm - lxdm - - kdm - greetd # Enable the following settings to force a desktop environment diff --git a/src/modules/displaymanager/displaymanager.schema.yaml b/src/modules/displaymanager/displaymanager.schema.yaml index 89d657a3b..7e4c5f54c 100644 --- a/src/modules/displaymanager/displaymanager.schema.yaml +++ b/src/modules/displaymanager/displaymanager.schema.yaml @@ -10,7 +10,7 @@ properties: type: array items: type: string - enum: [slim, sddm, lightdm, gdm, mdm, lxdm, kdm, greetd] + enum: [slim, sddm, lightdm, gdm, mdm, lxdm, greetd] minItems: 1 # Must be non-empty, if present at all defaultDesktopEnvironment: type: object diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index ab68488ed..2b49a595c 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -481,84 +481,6 @@ class DMgdm(DisplayManager): pass -class DMkdm(DisplayManager): - name = "kdm" - executable = "kdm" - - def set_autologin(self, username, do_autologin, default_desktop_environment): - # Systems with KDM as Desktop Manager - kdm_conf_path = os.path.join( - self.root_mount_point, "usr/share/config/kdm/kdmrc" - ) - # Check which path is in use: SUSE does something else. - # Also double-check the default setting. Pick the first - # one that exists in the target. - for candidate_kdmrc in ( - "usr/share/config/kdm/kdmrc", - "usr/share/kde4/config/kdm/kdmrc", - ): - p = os.path.join(self.root_mount_point, candidate_kdmrc) - if os.path.exists(p): - kdm_conf_path = p - break - text = [] - - if os.path.exists(kdm_conf_path): - with open(kdm_conf_path, 'r') as kdm_conf: - text = kdm_conf.readlines() - - with open(kdm_conf_path, 'w') as kdm_conf: - for line in text: - if 'AutoLoginEnable=' in line: - if do_autologin: - line = 'AutoLoginEnable=true\n' - else: - line = 'AutoLoginEnable=false\n' - - if do_autologin and 'AutoLoginUser=' in line: - line = "AutoLoginUser={!s}\n".format(username) - - kdm_conf.write(line) - else: - return ( - _("Cannot write KDM configuration file"), - _("KDM config file {!s} does not exist").format(kdm_conf_path) - ) - - def basic_setup(self): - if libcalamares.utils.target_env_call( - ['getent', 'group', 'kdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['groupadd', '-g', '135', 'kdm'] - ) - - if libcalamares.utils.target_env_call( - ['getent', 'passwd', 'kdm'] - ) != 0: - libcalamares.utils.target_env_call( - ['useradd', - '-u', '135', - '-g', 'kdm', - '-d', '/var/lib/kdm', - '-s', '/bin/false', - '-r', - '-M', - 'kdm' - ] - ) - - libcalamares.utils.target_env_call( - ['chown', '-R', '135:135', 'var/lib/kdm'] - ) - - def desktop_environment_setup(self, desktop_environment): - pass - - def greeter_setup(self): - pass - - class DMlxdm(DisplayManager): name = "lxdm" executable = "lxdm" diff --git a/src/modules/dracutlukscfg/CMakeLists.txt b/src/modules/dracutlukscfg/CMakeLists.txt index aaa7a8c17..85efccc0c 100644 --- a/src/modules/dracutlukscfg/CMakeLists.txt +++ b/src/modules/dracutlukscfg/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -calamares_add_plugin( dracutlukscfg +calamares_add_plugin(dracutlukscfg TYPE job EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/dummycpp/CMakeLists.txt b/src/modules/dummycpp/CMakeLists.txt index 2916b4d67..b822a03be 100644 --- a/src/modules/dummycpp/CMakeLists.txt +++ b/src/modules/dummycpp/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -calamares_add_plugin( dummycpp +calamares_add_plugin(dummycpp TYPE job EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/dummypythonqt/dummypythonqt.conf b/src/modules/dummypythonqt/dummypythonqt.conf deleted file mode 100644 index 6caf9cc18..000000000 --- a/src/modules/dummypythonqt/dummypythonqt.conf +++ /dev/null @@ -1,24 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# -# This is a dummy (example) module for PythonQt. -# -# The code is the documentation for the configuration file. ---- -syntax: "YAML map of anything" -example: - whats_this: "module-specific configuration" - from_where: "dummypythonqt.conf" -a_list: - - "item1" - - "item2" - - "item3" - - "item4" -a_list_of_maps: - - name: "an Item" - contents: - - "an element" - - "another element" - - name: "another item" - contents: - - "not much" diff --git a/src/modules/dummypythonqt/lang/ar/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/ar/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 91d430930..000000000 --- a/src/modules/dummypythonqt/lang/ar/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Abubakaragoub Y , 2018 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Abubakaragoub Y , 2018\n" -"Language-Team: Arabic (https://www.transifex.com/calamares/teams/20061/ar/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ar\n" -"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "اضغط علي!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "QLabel جديد" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "دميه خطوة PythonQt " - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "دميه عملية PythonQt " - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "هذة دميه عملية خطوة PythonQt. و تقول: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "رسالة حاله دميه عملية خطوة PythonQt" diff --git a/src/modules/dummypythonqt/lang/as/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/as/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 75d63e46e..000000000 --- a/src/modules/dummypythonqt/lang/as/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,47 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Deep Jyoti Choudhury , 2020 -# Wrishiraj Kaushik , 2020 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-02-19 17:27+0100\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Wrishiraj Kaushik , 2020\n" -"Language-Team: Assamese (https://www.transifex.com/calamares/teams/20061/as/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: as\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "ইয়াত ক্লিক কৰক!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "এটা নতুন QLabel।" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "ডামী পাইথন-কিউট্ ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "ডামী পাইথন-কিউট্ কায্য" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "এইটোৱে ডামী পাইথন-কিউট্ কাৰ্য্য। ডামী কাৰ্য্যটোৱে কয় যে: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "ডামী পাইথন-কিউট্ কায্যৰ বাবে এটা অৱস্থা বাৰ্তা।" diff --git a/src/modules/dummypythonqt/lang/ast/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/ast/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 1807e45d6..000000000 --- a/src/modules/dummypythonqt/lang/ast/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# enolp , 2019 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-02-22 07:09-0500\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: enolp , 2019\n" -"Language-Team: Asturian (https://www.transifex.com/calamares/teams/20061/ast/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ast\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "¡Cálcame!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Una QLabel nueva." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "ViewStep maniquín en PythonQt" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "El trabayu maniquín en PythonQt" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Esti ye'l trabayu maniquín en PythonQt. El trabayu maniquín diz: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Un mensaxe d'estáu pal trabayu maniquín en PythonQt." diff --git a/src/modules/dummypythonqt/lang/be/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/be/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index c14151114..000000000 --- a/src/modules/dummypythonqt/lang/be/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Zmicer Turok , 2018 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-05-10 19:18-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Zmicer Turok , 2018\n" -"Language-Team: Belarusian (https://www.transifex.com/calamares/teams/20061/be/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: be\n" -"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Націсніце сюды! " - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Новы QLabel. " - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Dummy PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "The Dummy PythonQt Job" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Гэта Dummy PythonQt Job. Фіктыўная задача паведамляе: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Паведамленне статусу Dummy PythonQt Job. " diff --git a/src/modules/dummypythonqt/lang/bg/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/bg/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 831105b95..000000000 --- a/src/modules/dummypythonqt/lang/bg/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Georgi Georgiev , 2018 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Georgi Georgiev , 2018\n" -"Language-Team: Bulgarian (https://www.transifex.com/calamares/teams/20061/bg/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: bg\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Натисни ме!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Нов QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Фиктивен PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Фиктивната задача PythonQt" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Това е фиктивната задача PythonQt. Фиктивната задача заявява: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Съобщение за състоянието на фиктивната задача PythonQt." diff --git a/src/modules/dummypythonqt/lang/bn/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/bn/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index d2783e5e3..000000000 --- a/src/modules/dummypythonqt/lang/bn/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-04-30 23:13+0200\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Bengali (https://www.transifex.com/calamares/teams/20061/bn/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: bn\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/ca/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/ca/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 19f669849..000000000 --- a/src/modules/dummypythonqt/lang/ca/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Davidmp , 2019 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-05-10 19:18-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Davidmp , 2019\n" -"Language-Team: Catalan (https://www.transifex.com/calamares/teams/20061/ca/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ca\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Clica'm!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Una etiqueta Q nova." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Vistes de Dummy PythonQt" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "La tasca Dummy PythonQt" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Soc la tasca Dummy PythonQt. La tasca diu el següent: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Un missatge d'estat per a la tasca Dummy PythonQt." diff --git a/src/modules/dummypythonqt/lang/ca@valencia/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/ca@valencia/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index e67e371f3..000000000 --- a/src/modules/dummypythonqt/lang/ca@valencia/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-05-10 19:18-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Catalan (Valencian) (https://www.transifex.com/calamares/teams/20061/ca@valencia/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ca@valencia\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/cs_CZ/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/cs_CZ/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 44cd1e2d4..000000000 --- a/src/modules/dummypythonqt/lang/cs_CZ/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,47 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# pavelrz, 2017 -# Pavel Borecki , 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-02-22 07:09-0500\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Pavel Borecki , 2017\n" -"Language-Team: Czech (Czech Republic) (https://www.transifex.com/calamares/teams/20061/cs_CZ/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: cs_CZ\n" -"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Klikněte na mě!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Nový QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Testovací PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Testovací úloha PythonQt" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Toto je testovací úloha PythonQt. Testovací úloha sděluje: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Stavová zpráva o testovací úloze PythonQt." diff --git a/src/modules/dummypythonqt/lang/da/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/da/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 5a1473add..000000000 --- a/src/modules/dummypythonqt/lang/da/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# scootergrisen, 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: scootergrisen, 2017\n" -"Language-Team: Danish (https://www.transifex.com/calamares/teams/20061/da/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: da\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Klik på mig!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "En ny QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Dummy PythonQt-visningstrin" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Dummy PythonQt-jobbet" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Dette er dummy PythonQt-jobbet. Dummy-jobbet siger: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "En statusmeddelelse til dummy PythonQt-job." diff --git a/src/modules/dummypythonqt/lang/de/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/de/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index b0121397f..000000000 --- a/src/modules/dummypythonqt/lang/de/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Christian Spaan, 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Christian Spaan, 2017\n" -"Language-Team: German (https://www.transifex.com/calamares/teams/20061/de/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: de\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Klick mich!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Ein neues QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Dummy PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Der Dummy-PythonQt-Job" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Dies ist der Dummy-PythonQt-Job. Der Dummy-Job lautet: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Eine Statusmeldung für den Dummy-PythonQt-Job." diff --git a/src/modules/dummypythonqt/lang/dummypythonqt.pot b/src/modules/dummypythonqt/lang/dummypythonqt.pot deleted file mode 100644 index 54bb63666..000000000 --- a/src/modules/dummypythonqt/lang/dummypythonqt.pot +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-27 11:18+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: src/modules/dummypythonqt/main.py:75 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:85 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:88 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:174 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:177 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:181 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/el/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/el/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 316384619..000000000 --- a/src/modules/dummypythonqt/lang/el/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Greek (https://www.transifex.com/calamares/teams/20061/el/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: el\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/en_GB/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/en_GB/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index a0e21be1f..000000000 --- a/src/modules/dummypythonqt/lang/en_GB/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Jason Collins , 2018 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Jason Collins , 2018\n" -"Language-Team: English (United Kingdom) (https://www.transifex.com/calamares/teams/20061/en_GB/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: en_GB\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Click me!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "A new QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Dummy PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "The Dummy PythonQt Job" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "This is the Dummy PythonQt Job. The dummy job says: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "A status message for Dummy PythonQt Job." diff --git a/src/modules/dummypythonqt/lang/eo/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/eo/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index a656d0608..000000000 --- a/src/modules/dummypythonqt/lang/eo/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Kurt Ankh Phoenix , 2018 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Kurt Ankh Phoenix , 2018\n" -"Language-Team: Esperanto (https://www.transifex.com/calamares/teams/20061/eo/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: eo\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Alklaku min!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Nova QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Formala PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "La Formala PythonQt Laboro" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Ĉi tiu estas la Formala PythonQt Laboro. La formala laboro diras: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Statusa mesaĝo por Formala PythonQt Laboro." diff --git a/src/modules/dummypythonqt/lang/es/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/es/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index b29ba10b3..000000000 --- a/src/modules/dummypythonqt/lang/es/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# strel, 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: strel, 2017\n" -"Language-Team: Spanish (https://www.transifex.com/calamares/teams/20061/es/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: es\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "¡Púlsame!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Una nueva QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "ViewStep de PythonQt Ficticia" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "La Tarea PythonQt Ficticia" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Esta es la Tarea PythonQt Ficticia. La tarea ficticia dice: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Un mensaje de estado para la Tarea PythonQt Ficticia." diff --git a/src/modules/dummypythonqt/lang/es_MX/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/es_MX/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 6dc2d8278..000000000 --- a/src/modules/dummypythonqt/lang/es_MX/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# guillermo pacheco , 2018 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: guillermo pacheco , 2018\n" -"Language-Team: Spanish (Mexico) (https://www.transifex.com/calamares/teams/20061/es_MX/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: es_MX\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "¡Haz clic en mí!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Una nueva QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Vision del PythonQt ficticio" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Trabajo del PythonQt ficticio" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Este es el Trabajo PythonQt ficticio. El trabajo ficticio dice: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Un mensaje de estado para el trabajo PythonQt ficticio." diff --git a/src/modules/dummypythonqt/lang/es_PR/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/es_PR/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 1b767f1ad..000000000 --- a/src/modules/dummypythonqt/lang/es_PR/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Spanish (Puerto Rico) (https://www.transifex.com/calamares/teams/20061/es_PR/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: es_PR\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/et/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/et/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 4ab56cc0f..000000000 --- a/src/modules/dummypythonqt/lang/et/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Madis Otenurm, 2018 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-06 01:16+0200\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Madis Otenurm, 2018\n" -"Language-Team: Estonian (https://www.transifex.com/calamares/teams/20061/et/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: et\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Klõpsa mind!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Uus QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Testiv PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Testiv PythonQt Töö" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "See on testiv PythonQt töö. Testiv töö ütleb: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Olekusõnum testivale PythonQt tööle." diff --git a/src/modules/dummypythonqt/lang/eu/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/eu/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index a336c22a0..000000000 --- a/src/modules/dummypythonqt/lang/eu/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Ander Elortondo, 2019 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Ander Elortondo, 2019\n" -"Language-Team: Basque (https://www.transifex.com/calamares/teams/20061/eu/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: eu\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Egidazu klik!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "QLabel berria." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Dummy PythonQt pauso-ikuspegia" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr " Dummy PythonQt lana" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Hau Dummy PythonQt lana da. Dummy lanak zera dio: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Dummy PythonQt lanaren egoera mezua." diff --git a/src/modules/dummypythonqt/lang/fa/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/fa/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 373a4c3e9..000000000 --- a/src/modules/dummypythonqt/lang/fa/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Danial Behzadi , 2020 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-04-30 23:13+0200\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Danial Behzadi , 2020\n" -"Language-Team: Persian (https://www.transifex.com/calamares/teams/20061/fa/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fa\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "کلیکم کنید!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "یک QLabel جدید." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "گام نمایش PythonQt الکی" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "کار PythonQt الکی" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "این کار PythonQt الکی است. کار الکی می‌گوید: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "پیام وضعیتی برای کار PythonQt الکی." diff --git a/src/modules/dummypythonqt/lang/fi_FI/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/fi_FI/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 1d8526f2a..000000000 --- a/src/modules/dummypythonqt/lang/fi_FI/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,47 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Assalat3 , 2017 -# Kimmo Kujansuu , 2019 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-05-10 19:18-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Kimmo Kujansuu , 2019\n" -"Language-Team: Finnish (Finland) (https://www.transifex.com/calamares/teams/20061/fi_FI/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fi_FI\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Klikkaa minua!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Uusi Qtyönimi." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Näppärä Python Qt-näkymä" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Näppärä Python Qt-työkalu" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Tämä on näppärä Python Qt-työkalu. Näennäinen työ sanoo: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Python Qt-työkalun tilailmoitus." diff --git a/src/modules/dummypythonqt/lang/fr/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/fr/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index fe75d0c55..000000000 --- a/src/modules/dummypythonqt/lang/fr/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,47 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Paul Combal , 2017 -# Aestan , 2018 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Aestan , 2018\n" -"Language-Team: French (https://www.transifex.com/calamares/teams/20061/fr/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fr\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Cliquez-moi!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Un nouveau QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "ViewStep Factice PythonQt" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Tâche Factice PythonQt" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Ceci est la tâche factice PythonQt. La tâche factice dit : {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Un message d'état pour la tâche factice PythonQt." diff --git a/src/modules/dummypythonqt/lang/fr_CH/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/fr_CH/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 9e8862d54..000000000 --- a/src/modules/dummypythonqt/lang/fr_CH/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: French (Switzerland) (https://www.transifex.com/calamares/teams/20061/fr_CH/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fr_CH\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/gl/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/gl/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index c7917c72b..000000000 --- a/src/modules/dummypythonqt/lang/gl/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Xosé, 2018 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Xosé, 2018\n" -"Language-Team: Galician (https://www.transifex.com/calamares/teams/20061/gl/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: gl\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Prémeme!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Unha QLabel nova." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "ViewStep parvo de PythonQt" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "A tarefa parva de PythonQt" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Esta é a tarefa parva de PythonQt. A tarefa parva di: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Unha mensaxe parva para Dummy PythonQt Job." diff --git a/src/modules/dummypythonqt/lang/gu/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/gu/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 62b6d5560..000000000 --- a/src/modules/dummypythonqt/lang/gu/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Gujarati (https://www.transifex.com/calamares/teams/20061/gu/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: gu\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/he/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/he/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 1d4c544a8..000000000 --- a/src/modules/dummypythonqt/lang/he/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Eli Shleifer , 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Eli Shleifer , 2017\n" -"Language-Team: Hebrew (https://www.transifex.com/calamares/teams/20061/he/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: he\n" -"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "לחץ עליי!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "QLabel חדש." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "שלב הצפייה של משימת הדמה של PythonQt" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "משימת הדמה של PythonQt" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "זוהי משימת הדמה של PythonQt. משימת הדמה אומרת: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "הודעת מצב עבור משימת דמה של PythonQt." diff --git a/src/modules/dummypythonqt/lang/hi/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/hi/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 4f43a75f8..000000000 --- a/src/modules/dummypythonqt/lang/hi/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Panwar108 , 2018 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Panwar108 , 2018\n" -"Language-Team: Hindi (https://www.transifex.com/calamares/teams/20061/hi/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: hi\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "यहाँ क्लिक करें!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "नया QLabel।" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "डमी पाइथन प्रक्रिया की चरण संख्या देखें" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "डमी पाइथन प्रक्रिया" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "यह डमी पाइथन प्रक्रिया है। डमी प्रक्रिया संबंधी संदेश : {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "डमी पाइथन प्रक्रिया की अवस्था संबंधी संदेश।" diff --git a/src/modules/dummypythonqt/lang/hr/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/hr/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index a6e05ada6..000000000 --- a/src/modules/dummypythonqt/lang/hr/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Lovro Kudelić , 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Lovro Kudelić , 2017\n" -"Language-Team: Croatian (https://www.transifex.com/calamares/teams/20061/hr/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: hr\n" -"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Klikni me!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Novi QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Testni PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Testni PythonQt posao" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Ovo je testni PythonQt posao. Testni posao kaže: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Statusna poruka za testni PythonQt posao." diff --git a/src/modules/dummypythonqt/lang/hu/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/hu/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index bae97b375..000000000 --- a/src/modules/dummypythonqt/lang/hu/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,47 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Lajos Pasztor , 2016 -# miku84, 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: miku84, 2017\n" -"Language-Team: Hungarian (https://www.transifex.com/calamares/teams/20061/hu/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: hu\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Kattints ide!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Egy új QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Hamis PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Egy PythonQt Job teszt" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Ez egy PythonQt Job teszt. A teszt job azt mondja: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Sztátus üzenet egy PythonQt Job-hoz." diff --git a/src/modules/dummypythonqt/lang/id/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/id/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 41a0444c0..000000000 --- a/src/modules/dummypythonqt/lang/id/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,47 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Kukuh Syafaat , 2016 -# Wantoyèk , 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-04-30 23:13+0200\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Wantoyèk , 2017\n" -"Language-Team: Indonesian (https://www.transifex.com/calamares/teams/20061/id/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: id\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Klik saya!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Sebuah QLabel baru." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Dummy PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Dummy PythonQt Job" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Ini adalah Dummy PythonQt Job. Dummy job mengatakan: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Sebuah pesan status untuk Dummy PythonQt Job." diff --git a/src/modules/dummypythonqt/lang/is/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/is/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index ed89dbc18..000000000 --- a/src/modules/dummypythonqt/lang/is/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Kristján Magnússon, 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Kristján Magnússon, 2017\n" -"Language-Team: Icelandic (https://www.transifex.com/calamares/teams/20061/is/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: is\n" -"Plural-Forms: nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Smelltu mig!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Nýtt QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Dummy PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Dummy PythonQt Job" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Þetta er Dummy PythonQt Job. Dummy job segir: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Stöðuskilaboð fyrir Dummy PythonQt Job." diff --git a/src/modules/dummypythonqt/lang/it_IT/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/it_IT/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 211f9d9c2..000000000 --- a/src/modules/dummypythonqt/lang/it_IT/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,47 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Teo Mrnjavac , 2016 -# Saverio , 2018 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-02-22 07:09-0500\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Saverio , 2018\n" -"Language-Team: Italian (Italy) (https://www.transifex.com/calamares/teams/20061/it_IT/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: it_IT\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Clicca qui!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Una nuova QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "PythonQt ViewStep fittizio" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Il Job Dummy PythonQt" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Questo è il Job Dummy PythonQt. Il dummy job notifica: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Un messaggio di stato per il Job Dummy PythonQt." diff --git a/src/modules/dummypythonqt/lang/ja/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/ja/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 6ed47ce1b..000000000 --- a/src/modules/dummypythonqt/lang/ja/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Takefumi Nagata, 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Takefumi Nagata, 2017\n" -"Language-Team: Japanese (https://www.transifex.com/calamares/teams/20061/ja/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ja\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "クリックしてください!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "新しいQLabel" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Dummy PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "The Dummy PythonQt Job" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "これはDummy PythonQtジョブです。Dummy ジョブの出力: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "ダミーのPythonQtジョブの状態" diff --git a/src/modules/dummypythonqt/lang/kk/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/kk/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 1d941e24e..000000000 --- a/src/modules/dummypythonqt/lang/kk/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Kazakh (https://www.transifex.com/calamares/teams/20061/kk/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: kk\n" -"Plural-Forms: nplurals=2; plural=(n!=1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/kn/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/kn/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index ff9def1e0..000000000 --- a/src/modules/dummypythonqt/lang/kn/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Kannada (https://www.transifex.com/calamares/teams/20061/kn/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: kn\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/ko/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/ko/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index e6dc4af27..000000000 --- a/src/modules/dummypythonqt/lang/ko/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,47 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# MarongHappy , 2019 -# 김지현 , 2020 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-02-19 17:27+0100\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: 김지현 , 2020\n" -"Language-Team: Korean (https://www.transifex.com/calamares/teams/20061/ko/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ko\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "여기를 클릭하세요!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "새로운 QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "더미 PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "더미 PythonQt 작업" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "더미 PythonQt 작업입니다. 이 더미 작업의 출력은 다음과 같습니다: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "더미 PythonQt 작업의 상태 메시지" diff --git a/src/modules/dummypythonqt/lang/lo/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/lo/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 87614dc88..000000000 --- a/src/modules/dummypythonqt/lang/lo/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Lao (https://www.transifex.com/calamares/teams/20061/lo/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: lo\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/lt/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/lt/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 443ab99d8..000000000 --- a/src/modules/dummypythonqt/lang/lt/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Moo, 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Moo, 2017\n" -"Language-Team: Lithuanian (https://www.transifex.com/calamares/teams/20061/lt/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: lt\n" -"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Spustelėkite mane!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Naujas QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Fiktyvi PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Fiktyvi PythonQt užduotis" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Tai yra fiktyvi PythonQt užduotis. Fiktyvi užduotis sako: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Fiktyvios PythonQt užduoties būsenos pranešimas." diff --git a/src/modules/dummypythonqt/lang/lv/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/lv/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 651fe2fa4..000000000 --- a/src/modules/dummypythonqt/lang/lv/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-04-30 23:13+0200\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Latvian (https://www.transifex.com/calamares/teams/20061/lv/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: lv\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/mk/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/mk/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 82998bf47..000000000 --- a/src/modules/dummypythonqt/lang/mk/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Martin Ristovski , 2018 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Martin Ristovski , 2018\n" -"Language-Team: Macedonian (https://www.transifex.com/calamares/teams/20061/mk/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: mk\n" -"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Кликни ме!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Нов QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/ml/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/ml/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index faf773770..000000000 --- a/src/modules/dummypythonqt/lang/ml/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Balasankar C , 2019 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-09-15 21:54+0200\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Balasankar C , 2019\n" -"Language-Team: Malayalam (https://www.transifex.com/calamares/teams/20061/ml/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ml\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "എന്നെ ക്ലിക്ക് ചെയ്യൂ!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "ഒരു പുതിയ QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/mr/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/mr/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index eaafadeac..000000000 --- a/src/modules/dummypythonqt/lang/mr/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Marathi (https://www.transifex.com/calamares/teams/20061/mr/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: mr\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/nb/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/nb/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 4bf83c283..000000000 --- a/src/modules/dummypythonqt/lang/nb/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Norwegian Bokmål (https://www.transifex.com/calamares/teams/20061/nb/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: nb\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/ne_NP/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/ne_NP/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 37f213df2..000000000 --- a/src/modules/dummypythonqt/lang/ne_NP/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Ghost Hackz , 2019 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-01-25 08:04-0500\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Ghost Hackz , 2019\n" -"Language-Team: Nepali (Nepal) (https://www.transifex.com/calamares/teams/20061/ne_NP/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ne_NP\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "यहाँ क्लिक गर्नुहोस्!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "नयाँ QLabel।" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "डमी पाइथन भ्यूस्टेप" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "डमी पाइथन प्रकृया" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "यो डमी पाइथन प्रकृया हो। डमी प्रकृया सम्बन्धित सन्देश: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "डमी पाइथन प्रकृयाको अवस्था सम्बन्धित सन्देश।" diff --git a/src/modules/dummypythonqt/lang/nl/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/nl/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 7f17f9973..000000000 --- a/src/modules/dummypythonqt/lang/nl/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# De Zeeappel , 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: De Zeeappel , 2017\n" -"Language-Team: Dutch (https://www.transifex.com/calamares/teams/20061/nl/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: nl\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Klik mij!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Een nieuw QLabel" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Dummy PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "De Dummy PythonQt opdracht" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Dit is de Dummy PythonQt opdracht. De opdracht zegt: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Een statusbericht voor de Dummy PythonQt opdracht." diff --git a/src/modules/dummypythonqt/lang/pl/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/pl/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 8502113bd..000000000 --- a/src/modules/dummypythonqt/lang/pl/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,47 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Marcin Mikołajczak , 2016 -# Piotr Strębski , 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-05-10 19:18-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Piotr Strębski , 2017\n" -"Language-Team: Polish (https://www.transifex.com/calamares/teams/20061/pl/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: pl\n" -"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Naciśnij mnie!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Nowy QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Podgląd kroków fikcyjnego PythonQt" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Zadanie fikcyjne PythonQt" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "To jest zadanie fikcyjne PythonQt mówiące: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Wiadomość o stanie zadania fikcyjnego PythonQt." diff --git a/src/modules/dummypythonqt/lang/pt_BR/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/pt_BR/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 4e5391043..000000000 --- a/src/modules/dummypythonqt/lang/pt_BR/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,47 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Rodrigo de Almeida Sottomaior Macedo , 2017 -# Guilherme, 2018 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-01-25 23:02+0100\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Guilherme, 2018\n" -"Language-Team: Portuguese (Brazil) (https://www.transifex.com/calamares/teams/20061/pt_BR/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: pt_BR\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Clique em mim!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Uma nova QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "ViewStep do Modelo PythonQt" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "A Tarefa de Modelo PythonQt" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Esta é a Tarefa Modelo PythonQt. A tarefa modelo diz: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Uma mensagem de status para a Tarefa Modelo PythonQt." diff --git a/src/modules/dummypythonqt/lang/pt_PT/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/pt_PT/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 952413cfa..000000000 --- a/src/modules/dummypythonqt/lang/pt_PT/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Ricardo Simões , 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Ricardo Simões , 2017\n" -"Language-Team: Portuguese (Portugal) (https://www.transifex.com/calamares/teams/20061/pt_PT/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: pt_PT\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Clique-me!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Uma nova QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Dummy PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "A Tarefa Dummy PythonQt" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Esta é a tarefa Dummy PythonQt. A tarefa dummy diz: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Uma mensagem de estado para a Tarefa Dummy PythonQt." diff --git a/src/modules/dummypythonqt/lang/ro/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/ro/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 3ac2bfcba..000000000 --- a/src/modules/dummypythonqt/lang/ro/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Baadur Jobava , 2018 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Baadur Jobava , 2018\n" -"Language-Team: Romanian (https://www.transifex.com/calamares/teams/20061/ro/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ro\n" -"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Clic aici!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Un nou QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Dummy PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Un job job fictiv PythonQt" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Acesta este jobul fictiv PythonQt. Descrierea jobului: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Un mesaj de stare pentru jobul fictiv PythonQt." diff --git a/src/modules/dummypythonqt/lang/ru/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/ru/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index cedc4d483..000000000 --- a/src/modules/dummypythonqt/lang/ru/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,47 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Вадим Сабынич , 2017 -# Simon Schwartz , 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Simon Schwartz , 2017\n" -"Language-Team: Russian (https://www.transifex.com/calamares/teams/20061/ru/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ru\n" -"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Нажать здесь!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Новый QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "The Dummy PythonQt Job" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Сообщение состояния для Dummy PythonQt Job." diff --git a/src/modules/dummypythonqt/lang/sk/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/sk/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 9c1d60dfd..000000000 --- a/src/modules/dummypythonqt/lang/sk/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Dušan Kazik , 2016 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Dušan Kazik , 2016\n" -"Language-Team: Slovak (https://www.transifex.com/calamares/teams/20061/sk/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sk\n" -"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Kliknite sem!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Nová menovka QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Fiktívna úloha PythonQt" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Toto je fiktívna úloha PythonQt. Fiktívna úloha hovorí: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Stavová správa pre fiktívnu úlohu PythonQt." diff --git a/src/modules/dummypythonqt/lang/sl/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/sl/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 178fc694a..000000000 --- a/src/modules/dummypythonqt/lang/sl/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Slovenian (https://www.transifex.com/calamares/teams/20061/sl/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sl\n" -"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/sq/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/sq/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 6335e9c56..000000000 --- a/src/modules/dummypythonqt/lang/sq/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Besnik Bleta , 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-04-15 13:39+0200\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Besnik Bleta , 2017\n" -"Language-Team: Albanian (https://www.transifex.com/calamares/teams/20061/sq/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sq\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Klikomëni!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Një QLabel e re." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Dummy PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Akti PythonQt Dummy" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Ky është Akti PythonQt Dummy. Akti dummy thotë: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Një mesazh gjendjeje nga Akti PythonQt Dummy." diff --git a/src/modules/dummypythonqt/lang/sr/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/sr/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 6660b1500..000000000 --- a/src/modules/dummypythonqt/lang/sr/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Slobodan Simić , 2019 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-18 15:54+0200\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Slobodan Simić , 2019\n" -"Language-Team: Serbian (https://www.transifex.com/calamares/teams/20061/sr/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sr\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Кликни ме!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Нова КуОзнака" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Провизорни ПитонКуТ корак прегледа" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Провизорни ПитонКуТ посао" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Ово је провизорни ПитонКуТ посао. Он каже: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Порука стања за провизорни ПитонКуТ посао." diff --git a/src/modules/dummypythonqt/lang/sr@latin/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/sr@latin/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index b3e4fe47b..000000000 --- a/src/modules/dummypythonqt/lang/sr@latin/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-02-22 07:09-0500\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Serbian (Latin) (https://www.transifex.com/calamares/teams/20061/sr@latin/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sr@latin\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/sv/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/sv/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 192ed25e6..000000000 --- a/src/modules/dummypythonqt/lang/sv/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Luna Jernberg , 2020 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-03-19 00:13+0100\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Luna Jernberg , 2020\n" -"Language-Team: Swedish (https://www.transifex.com/calamares/teams/20061/sv/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sv\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Klicka på mig!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "En ny QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Exempel PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Exempel PythonQt jobb" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Detta är ett exempel PythonQt jobb. Exempel jobbet säger: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Ett statusmeddelande för exempel PythonQt jobb." diff --git a/src/modules/dummypythonqt/lang/th/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/th/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 22d304458..000000000 --- a/src/modules/dummypythonqt/lang/th/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Thai (https://www.transifex.com/calamares/teams/20061/th/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: th\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/tr_TR/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/tr_TR/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index fe0f567c5..000000000 --- a/src/modules/dummypythonqt/lang/tr_TR/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Demiray Muhterem , 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Demiray Muhterem , 2017\n" -"Language-Team: Turkish (Turkey) (https://www.transifex.com/calamares/teams/20061/tr_TR/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: tr_TR\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Buraya tıkla!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Yeni bir QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Sahte PythonQt görünümü" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Sahte PythonQt işleri" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Kukla PythonQt işleri. Sahte işleri şöyle diyor: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Kukla PythonQt Çalışması için bir durum mesajı." diff --git a/src/modules/dummypythonqt/lang/uk/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/uk/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index bcf3b814a..000000000 --- a/src/modules/dummypythonqt/lang/uk/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Yuri Chornoivan , 2020 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-02-19 17:27+0100\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: Yuri Chornoivan , 2020\n" -"Language-Team: Ukrainian (https://www.transifex.com/calamares/teams/20061/uk/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: uk\n" -"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "Натисни мене!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "Нова QLabel." - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "Фіктивний ViewStep PythonQt" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "Фіктивне завдання PythonQt" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "Це фіктивне завдання PythonQt. Фіктивне завдання повідомляє: {}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "Повідомлення щодо стану фіктивного завдання PythonQt." diff --git a/src/modules/dummypythonqt/lang/ur/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/ur/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 54352d479..000000000 --- a/src/modules/dummypythonqt/lang/ur/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Urdu (https://www.transifex.com/calamares/teams/20061/ur/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ur\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/uz/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/uz/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index 75584e15c..000000000 --- a/src/modules/dummypythonqt/lang/uz/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,42 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-05 11:34-0400\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Language-Team: Uzbek (https://www.transifex.com/calamares/teams/20061/uz/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: uz\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "" diff --git a/src/modules/dummypythonqt/lang/zh_CN/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/zh_CN/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index d7baa50f2..000000000 --- a/src/modules/dummypythonqt/lang/zh_CN/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,47 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# Mingcong Bai , 2017 -# soenggam , 2018 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-02-22 07:09-0500\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: soenggam , 2018\n" -"Language-Team: Chinese (China) (https://www.transifex.com/calamares/teams/20061/zh_CN/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_CN\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "按我按我!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "一个新的QLabel。" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "坠吼滴 PythonQt ViewStep" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "PythonQt 任务" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "我是个 PythonQt 任务。任务提示:{}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "来自 PythonQt 任务的状态消息。" diff --git a/src/modules/dummypythonqt/lang/zh_TW/LC_MESSAGES/dummypythonqt.po b/src/modules/dummypythonqt/lang/zh_TW/LC_MESSAGES/dummypythonqt.po deleted file mode 100644 index bc2056e1e..000000000 --- a/src/modules/dummypythonqt/lang/zh_TW/LC_MESSAGES/dummypythonqt.po +++ /dev/null @@ -1,46 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -# Translators: -# 黃柏諺 , 2017 -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-06 01:16+0200\n" -"PO-Revision-Date: 2016-12-16 12:18+0000\n" -"Last-Translator: 黃柏諺 , 2017\n" -"Language-Team: Chinese (Taiwan) (https://www.transifex.com/calamares/teams/20061/zh_TW/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_TW\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: src/modules/dummypythonqt/main.py:84 -msgid "Click me!" -msgstr "點擊我!" - -#: src/modules/dummypythonqt/main.py:94 -msgid "A new QLabel." -msgstr "一個新的 QLabel。" - -#: src/modules/dummypythonqt/main.py:97 -msgid "Dummy PythonQt ViewStep" -msgstr "假的 PythonQt 檢視步驟" - -#: src/modules/dummypythonqt/main.py:183 -msgid "The Dummy PythonQt Job" -msgstr "假的 PythonQt 工作" - -#: src/modules/dummypythonqt/main.py:186 -msgid "This is the Dummy PythonQt Job. The dummy job says: {}" -msgstr "這是一個假的 PythonQt 工作。假工作表示:{}" - -#: src/modules/dummypythonqt/main.py:190 -msgid "A status message for Dummy PythonQt Job." -msgstr "假的 PythonQt 工作的狀態訊息。" diff --git a/src/modules/dummypythonqt/main.py b/src/modules/dummypythonqt/main.py deleted file mode 100644 index e33c20e6f..000000000 --- a/src/modules/dummypythonqt/main.py +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# SPDX-FileCopyrightText: 2016-2017 Teo Mrnjavac -# SPDX-FileCopyrightText: 2017 Alf Gaida -# SPDX-License-Identifier: GPL-3.0-or-later -# -# Calamares is Free Software: see the License-Identifier above. -# - -import platform - -from PythonQt.QtGui import * -import PythonQt.calamares as calamares - -# WARNING: the Calamares PythonQt API is considered EXPERIMENTAL as of -# Calamares 2.5. It comes with no promise or commitment to API stability. - - -# Set up translations. -# You may skip this if your Calamares module has no user visible strings. -# DO NOT install _ into the builtin namespace because each module loads -# its own catalog. -# DO use the gettext class-based API and manually alias _ as described in: -# https://docs.python.org/3.5/library/gettext.html#localizing-your-module -import gettext -import inspect -import os -_filename = inspect.getframeinfo(inspect.currentframe()).filename -_path = os.path.dirname(os.path.abspath(_filename)) - -_ = gettext.gettext - -# Example Python ViewModule. -# A Python ViewModule is a Python program which defines a ViewStep class. -# One UI module ==> one ViewStep. -# This class must be marked with the @calamares_module decorator. A -# ViewModule may define other classes, but only one may be decorated with -# @calamares_module. Such a class must conform to the Calamares ViewStep -# interface and functions as the entry point of the module. -# A ViewStep manages one or more "wizard pages" through methods like -# back/next, and reports its status through isNextEnabled/isBackEnabled/ -# isAtBeginning/isAtEnd. The whole UI, including all the pages, must be -# exposed as a single QWidget, returned by the widget function. -# -# For convenience, both C++ and PythonQt ViewSteps are considered to be -# implementations of ViewStep.h. Additionally, the Calamares PythonQt API -# allows Python developers to keep their identifiers more Pythonic on the -# Python side. Thus, all of the following are considered valid method -# identifiers in a ViewStep implementation: isNextEnabled, isnextenabled, -# is_next_enabled. - - -@calamares_module -class DummyPythonQtViewStep: - def __init__(self): - # Importing PythonQt.QtGui provides access to most Qt widget classes. - self.main_widget = QFrame() - - self.main_widget.setLayout(QVBoxLayout()) - - label = QLabel() - self.main_widget.layout().addWidget(label) - - accumulator = "\nCalamares+PythonQt running embedded Python " +\ - platform.python_version() - label.text = accumulator - - btn = QPushButton() - - # Python strings can be used wherever a method wants a QString. Python - # gettext translations can be used seamlessly as well. - btn.setText(_("Click me!")) - self.main_widget.layout().addWidget(btn) - - # The syntax for signal-slot connections is very simple, though - # slightly different from the C++ equivalent. There are no SIGNAL and - # SLOT macros, and a signal can be connected to any Python method - # (without a special "slot" designation). - btn.connect("clicked(bool)", self.on_btn_clicked) - - def on_btn_clicked(self): - self.main_widget.layout().addWidget(QLabel(_("A new QLabel."))) - - def prettyName(self): - return _("Dummy PythonQt ViewStep") - - def isNextEnabled(self): - return True # The "Next" button should be clickable - - def isBackEnabled(self): - return True # The "Back" button should be clickable - - def isAtBeginning(self): - # True means the currently shown UI page is the first page of this - # module, thus a "Back" button click will not be handled by this - # module and will cause a skip to the previous ViewStep instead - # (if any). False means that the present ViewStep provides other UI - # pages placed logically "before" the current one, thus a "Back" button - # click will be handled by this module instead of skipping to another - # ViewStep. A module (ViewStep) with only one page will always return - # True here. - return True - - def isAtEnd(self): - # True means the currently shown UI page is the last page of this - # module, thus a "Next" button click will not be handled by this - # module and will cause a skip to the next ViewStep instead (if any). - # False means that the present ViewStep provides other UI pages placed - # logically "after" the current one, thus a "Next" button click will - # be handled by this module instead of skipping to another ViewStep. - # A module (ViewStep) with only one page will always return True here. - return True - - def jobs(self): - # Returns a list of objects that implement Calamares::Job. - return [DummyPQJob("Dummy PythonQt job reporting for duty")] - - def widget(self): - # Returns the base QWidget of this module's UI. - return self.main_widget - - def retranslate(self, locale_name): - # This is where it gets slightly weird. In most desktop applications we - # shouldn't need this kind of mechanism, because we could assume that - # the operating environment is configured to use a certain language. - # Usually the user would change the system-wide language in a settings - # UI, restart the application, done. - # Alas, Calamares runs on an unconfigured live system, and one of the - # core features of Calamares is to allow the user to pick a language. - # Unfortunately, strings in the UI do not automatically react to a - # runtime language change. To get UI strings in a new language, all - # user-visible strings must be retranslated (by calling tr() in C++ or - # _() in Python) and reapplied on the relevant widgets. - # When the user picks a new UI translation language, Qt raises a QEvent - # of type LanguageChange, which propagates through the QObject - # hierarchy. By catching and reacting to this event, we can show - # user-visible strings in the new language at the right time. - # The C++ side of the Calamares PythonQt API catches the LanguageChange - # event and calls the present method. It is then up to the module - # developer to add here all the needed code to load the module's - # translation catalog for the new language (which is separate from the - # main Calamares strings catalog) and reapply any user-visible strings. - calamares.utils.debug("PythonQt retranslation event " - "for locale name: {}".format(locale_name)) - - # First we load the catalog file for the new language... - try: - global _ - _t = gettext.translation('dummypythonqt', - localedir=os.path.join(_path, 'lang'), - languages=[locale_name]) - _ = _t.gettext - except OSError as e: - calamares.utils.debug(e) - pass - - # ... and then we can call setText(_("foo")) and similar methods on - # the relevant widgets here to reapply the strings. - -# An example Job class. Implements Calamares::Job. For method identifiers, the -# same rules apply as for ViewStep. No decorators are necessary here, because -# only the ViewStep implementation is the unique entry point, and a module can -# have any number of jobs. - - -class DummyPQJob: - def __init__(self, my_msg): - self.my_msg = my_msg - - def pretty_name(self): - return _("The Dummy PythonQt Job") - - def pretty_description(self): - return _("This is the Dummy PythonQt Job. " - "The dummy job says: {}").format(self.my_msg) - - def pretty_status_message(self): - return _("A status message for Dummy PythonQt Job.") - - def exec(self): - # As an example, we touch a file in the target root filesystem. - rmp = calamares.global_storage['rootMountPoint'] - os.system("touch {}/calamares_dpqt_was_here".format(rmp)) - calamares.utils.debug("the dummy job says {}".format(self.my_msg)) - return {'ok': True} diff --git a/src/modules/dummypythonqt/module.desc b/src/modules/dummypythonqt/module.desc deleted file mode 100644 index a747daeaa..000000000 --- a/src/modules/dummypythonqt/module.desc +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-FileCopyrightText: no -# SPDX-License-Identifier: CC0-1.0 -# Module metadata file for dummy pythonqt jobmodule -# Syntax is YAML 1.2 ---- -type: "view" -name: "dummypythonqt" -interface: "pythonqt" -script: "main.py" #assumed relative to the current directory diff --git a/src/modules/finished/CMakeLists.txt b/src/modules/finished/CMakeLists.txt index 619f6d8b0..ab435a9eb 100644 --- a/src/modules/finished/CMakeLists.txt +++ b/src/modules/finished/CMakeLists.txt @@ -3,11 +3,11 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED DBus Network ) +find_package(Qt5 ${QT_VERSION} CONFIG REQUIRED DBus Network) -include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) +include_directories(${PROJECT_BINARY_DIR}/src/libcalamaresui) -calamares_add_plugin( finished +calamares_add_plugin(finished TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/finishedq/CMakeLists.txt b/src/modules/finishedq/CMakeLists.txt index facc2d691..2e688c45d 100644 --- a/src/modules/finishedq/CMakeLists.txt +++ b/src/modules/finishedq/CMakeLists.txt @@ -3,21 +3,21 @@ # SPDX-FileCopyrightText: 2021 Anke Boersma # SPDX-License-Identifier: BSD-2-Clause # -if( NOT WITH_QML ) +if(NOT WITH_QML) calamares_skip_module( "finishedq (QML is not supported in this build)" ) return() endif() -find_package( Qt5 ${QT_VERSION} CONFIG COMPONENTS DBus Network ) -if ( NOT TARGET Qt5::DBus OR NOT TARGET Qt5::Network ) +find_package(Qt5 ${QT_VERSION} CONFIG COMPONENTS DBus Network) +if(NOT TARGET Qt5::DBus OR NOT TARGET Qt5::Network) calamares_skip_module( "finishedq (missing DBus or Network)" ) return() endif() -set( _finished ${CMAKE_CURRENT_SOURCE_DIR}/../finished ) -include_directories( ${_finished} ) +set(_finished ${CMAKE_CURRENT_SOURCE_DIR}/../finished) +include_directories(${_finished}) -calamares_add_plugin( finishedq +calamares_add_plugin(finishedq TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/fsresizer/CMakeLists.txt b/src/modules/fsresizer/CMakeLists.txt index e721d7f6b..189e7c1dc 100644 --- a/src/modules/fsresizer/CMakeLists.txt +++ b/src/modules/fsresizer/CMakeLists.txt @@ -3,18 +3,18 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -find_package( KF5Config CONFIG ) -find_package( KF5I18n CONFIG ) -find_package( KF5WidgetsAddons CONFIG ) +find_package(KF5Config CONFIG) +find_package(KF5I18n CONFIG) +find_package(KF5WidgetsAddons CONFIG) -include( KPMcoreHelper ) +include(KPMcoreHelper) -if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND ) - include_directories( ${KPMCORE_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/src/modules/partition ) +if(KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND) + include_directories(${KPMCORE_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/src/modules/partition) # The PartitionIterator is a small class, and it's easiest -- but also a # gross hack -- to just compile it again from the partition module tree. - calamares_add_plugin( fsresizer + calamares_add_plugin(fsresizer TYPE job EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -27,15 +27,14 @@ if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND calamares_add_test( fsresizertest - SOURCES - Tests.cpp + SOURCES Tests.cpp LIBRARIES - calamares_job_fsresizer # From above + calamares_job_fsresizer # From above yamlcpp::yamlcpp DEFINITIONS ${KPMcore_API_DEFINITIONS} ) else() - if ( NOT KPMcore_FOUND ) + if(NOT KPMcore_FOUND) calamares_skip_module( "fsresizer (missing suitable KPMcore)" ) else() calamares_skip_module( "fsresizer (missing dependencies for KPMcore)" ) diff --git a/src/modules/fsresizer/ResizeFSJob.cpp b/src/modules/fsresizer/ResizeFSJob.cpp index f972b9fa4..562644594 100644 --- a/src/modules/fsresizer/ResizeFSJob.cpp +++ b/src/modules/fsresizer/ResizeFSJob.cpp @@ -49,12 +49,8 @@ ResizeFSJob::PartitionMatch ResizeFSJob::findPartition() { using DeviceList = QList< Device* >; -#if defined( WITH_KPMCORE4API ) DeviceList devices = m_kpmcore.backend()->scanDevices( /* not includeReadOnly, not includeLoopback */ ScanFlag( 0 ) ); -#else - DeviceList devices = m_kpmcore.backend()->scanDevices( /* excludeReadOnly */ true ); -#endif cDebug() << "ResizeFSJob found" << devices.count() << "devices."; for ( DeviceList::iterator dev_it = devices.begin(); dev_it != devices.end(); ++dev_it ) diff --git a/src/modules/fstab/fstab.conf b/src/modules/fstab/fstab.conf index 80800c44b..5c5c5662d 100644 --- a/src/modules/fstab/fstab.conf +++ b/src/modules/fstab/fstab.conf @@ -5,57 +5,8 @@ # Also creates mount points for all the filesystems. # # When creating fstab entries for a filesystem, this module -# uses the options for the filesystem type to write to the -# options field of the file. +# uses the options previously defined in the mount module --- -# Mount options to use for all filesystems. If a specific filesystem -# is listed here, use those options, otherwise use the *default* -# options from this mapping. -# -# With kernels 5.15 and newer be cautious of adding the option space_cache -# to the btrfs mount options. The default in 5.15 changed to space_cache=v2. -# If space_cache or space_cache=v1 are specified, it may fail to remount. -# -# btrfs_swap options are used when a swapfile is chosen with a btrfs root -# the options are applied to the subvolume which holds the swap partition -# -# The settings shown here apply only the btrfs defaults; these -# are generally the right ones. Commented-out lines show other -# options wich **might** be applicable for specific situations. -mountOptions: - default: defaults,noatime - # btrfs: defaults,noatime,autodefrag,compress=zstd - btrfs: defaults - # btrfs_swap: defaults,noatime - btrfs_swap: defaults - -# Mount options to use for the EFI System Partition. If not defined, the -# *mountOptions* for *vfat* are used, or if that is not set either, -# *default* from *mountOptions*. -efiMountOptions: umask=0077 - -# If a filesystem is on an SSD, add the following options. If a specific -# filesystem is listed here, use those options, otherwise no additional -# options are set (i.e. there is no *default* like in *mountOptions*). -# -# This example configuration applies the *discard* option to most -# common filesystems on an SSD. This may not be the right option -# for your distribution. If you use a systemd timer to trim the -# SSD, it may interfere with the *discard* option. Opinions vary -# as to whether *discard* is worth the effort -- it depends on -# the usage pattern of the disk as well. -# -# ssdExtraMountOptions: -# ext4: discard -# jfs: discard -# xfs: discard -# swap: discard -# btrfs: discard,compress=lzo -# -# The standard configuration applies asynchronous discard support and ssd optimizations to btrfs -# and does nothing for other filesystems. -ssdExtraMountOptions: - btrfs: discard=async,ssd # Additional options added to each line in /etc/crypttab crypttabOptions: luks diff --git a/src/modules/fstab/main.py b/src/modules/fstab/main.py index fc0649e2a..b258020a9 100755 --- a/src/modules/fstab/main.py +++ b/src/modules/fstab/main.py @@ -99,21 +99,11 @@ def disk_name_for_partition(partition): class FstabGenerator(object): - """ Class header - - :param partitions: - :param root_mount_point: - :param mount_options: - :param ssd_extra_mount_options: - :param crypttab_options: - :param tmp_options: - """ - def __init__(self, partitions, root_mount_point, mount_options, + def __init__(self, partitions, root_mount_point, mount_options_list, ssd_extra_mount_options, crypttab_options, tmp_options): self.partitions = partitions self.root_mount_point = root_mount_point - self.mount_options = mount_options - self.ssd_extra_mount_options = ssd_extra_mount_options + self.mount_options_list = mount_options_list self.crypttab_options = crypttab_options self.tmp_options = tmp_options self.ssd_disks = set() @@ -268,17 +258,7 @@ class FstabGenerator(object): libcalamares.utils.debug("Ignoring foreign swap {!s} {!s}".format(disk_name, partition.get("uuid", None))) return None - # If this is btrfs subvol a dedicated to a swapfile, use different options than a normal btrfs subvol - if filesystem == "btrfs" and partition.get("subvol", None) == "/@swap": - options = self.get_mount_options("btrfs_swap", mount_point) - else: - options = self.get_mount_options(filesystem, mount_point) - - if is_ssd: - extra = self.ssd_extra_mount_options.get(filesystem) - - if extra: - options += "," + extra + options = self.get_mount_options(mount_point) if mount_point == "/" and filesystem != "btrfs": check = 1 @@ -330,15 +310,18 @@ class FstabGenerator(object): if partition["mountPoint"]: mkdir_p(self.root_mount_point + partition["mountPoint"]) - def get_mount_options(self, filesystem, mount_point): - efiMountPoint = libcalamares.globalstorage.value("efiSystemPartition") - job_config = libcalamares.job.configuration + def get_mount_options(self, mountpoint): + """ + Returns the mount options for a given mountpoint - if (mount_point == efiMountPoint and "efiMountOptions" in job_config): - return job_config["efiMountOptions"] - - return self.mount_options.get(filesystem, - self.mount_options["default"]) + :param mountpoint: A string containing the mountpoint for the fstab entry + :return: A string containing the mount options for the entry or "defaults" if nothing is found + """ + mount_options_item = next((x for x in self.mount_options_list if x.get("mountpoint") == mountpoint), None) + if mount_options_item: + return mount_options_item.get("option_string", "defaults") + else: + return "defaults" def create_swapfile(root_mount_point, root_btrfs): @@ -417,21 +400,20 @@ def run(): swap_choice = None libcalamares.job.setprogress(0.1) - mount_options = conf.get("mountOptions", {}) - ssd_extra_mount_options = conf.get("ssdExtraMountOptions", {}) + mount_options_list = global_storage.value("mountOptionsList") crypttab_options = conf.get("crypttabOptions", "luks") tmp_options = conf.get("tmpOptions", {}) # We rely on mount_options having a default; if there wasn't one, # bail out with a meaningful error. - if not mount_options: + if not mount_options_list: return (_("Configuration Error"), _("No
{!s}
configuration is given for
{!s}
to use.") .format("mountOptions", "fstab")) generator = FstabGenerator(partitions, root_mount_point, - mount_options, + mount_options_list, ssd_extra_mount_options, crypttab_options, tmp_options) diff --git a/src/modules/grubcfg/grubcfg.conf b/src/modules/grubcfg/grubcfg.conf index afc5e89b8..2d58e5dc2 100644 --- a/src/modules/grubcfg/grubcfg.conf +++ b/src/modules/grubcfg/grubcfg.conf @@ -9,7 +9,7 @@ # # Calculated values are: # - GRUB_DISTRIBUTOR, branding module, *bootloaderEntryName* (this -# string is sanitized, and see also setting *keepDistributor*) +# string is sanitized, and see also setting *keep_distributor*) # - GRUB_ENABLE_CRYPTODISK, based on the presence of filesystems # that use LUKS # - GRUB_CMDLINE_LINUX_DEFAULT, adding LUKS setup and plymouth @@ -29,9 +29,7 @@ prefer_grub_d: false # kept, not updated to the *bootloaderEntryName* from the branding file. # Use this if the GRUB_DISTRIBUTOR setting in the file is "smart" in # some way (e.g. uses shell-command substitution). -# -# TODO:3.3:snake-case this key -keepDistributor: false +keep_distributor: false # The default kernel params that should always be applied. # This is an array of strings. If it is unset, the default is diff --git a/src/modules/grubcfg/grubcfg.schema.yaml b/src/modules/grubcfg/grubcfg.schema.yaml index 35d63c063..f10b03a83 100644 --- a/src/modules/grubcfg/grubcfg.schema.yaml +++ b/src/modules/grubcfg/grubcfg.schema.yaml @@ -7,8 +7,7 @@ additionalProperties: false type: object properties: overwrite: { type: boolean, default: false } - # TODO:3.3:snake-case this key - keepDistributor: { type: boolean, default: false } + keep_istributor: { type: boolean, default: false } prefer_grub_d: { type: boolean, default: false } kernel_params: { type: array, items: { type: string } } defaults: diff --git a/src/modules/grubcfg/main.py b/src/modules/grubcfg/main.py index ec8b01308..b992629dd 100644 --- a/src/modules/grubcfg/main.py +++ b/src/modules/grubcfg/main.py @@ -48,8 +48,12 @@ def get_grub_config_path(root_mount_point): if not os.path.exists(default_dir): try: os.mkdir(default_dir) - except: - libcalamares.utils.debug("Failed to create '%r'" % default_dir) + except Exception as error: + # exception as error is still redundant, but it print out the error + # identify a solution for each exception and + # if possible and code it within. + libcalamares.utils.debug(f"Failed to create {default_dir}") + libcalamares.utils.debug(f"{error}") raise return os.path.join(default_dir, default_config_file) @@ -91,10 +95,10 @@ def modify_grub_default(partitions, root_mount_point, distributor): :param root_mount_point: :param distributor: name of the distributor to fill in for GRUB_DISTRIBUTOR. Must be a string. If the job setting - *keepDistributor* is set, then this is only used if no - GRUB_DISTRIBUTOR is found at all (otherwise, when *keepDistributor* + *keep_distributor* is set, then this is only used if no + GRUB_DISTRIBUTOR is found at all (otherwise, when *keep_distributor* is set, the GRUB_DISTRIBUTOR lines are left unchanged). - If *keepDistributor* is unset or false, then GRUB_DISTRIBUTOR + If *keep_distributor* is unset or false, then GRUB_DISTRIBUTOR is always updated to set this value. :return: """ @@ -139,14 +143,12 @@ def modify_grub_default(partitions, root_mount_point, distributor): if partition["fs"] == "linuxswap" and not has_luks: swap_uuid = partition["uuid"] - if (partition["fs"] == "linuxswap" and has_luks): + if partition["fs"] == "linuxswap" and has_luks: swap_outer_uuid = partition["luksUuid"] swap_outer_mappername = partition["luksMapperName"] - if (partition["mountPoint"] == "/" and has_luks): - cryptdevice_params = [ - "rd.luks.uuid={!s}".format(partition["luksUuid"]) - ] + if partition["mountPoint"] == "/" and has_luks: + cryptdevice_params = [f"rd.luks.uuid={partition['luksUuid']}"] else: for partition in partitions: if partition["fs"] == "linuxswap" and not partition.get("claimed", None): @@ -156,17 +158,13 @@ def modify_grub_default(partitions, root_mount_point, distributor): if partition["fs"] == "linuxswap" and not has_luks: swap_uuid = partition["uuid"] - if (partition["fs"] == "linuxswap" and has_luks): + if partition["fs"] == "linuxswap" and has_luks: swap_outer_mappername = partition["luksMapperName"] - if (partition["mountPoint"] == "/" and has_luks): + if partition["mountPoint"] == "/" and has_luks: cryptdevice_params = [ - "cryptdevice=UUID={!s}:{!s}".format( - partition["luksUuid"], partition["luksMapperName"] - ), - "root=/dev/mapper/{!s}".format( - partition["luksMapperName"] - ) + f"cryptdevice=UUID={partition['luksUuid']}:{partition['luksMapperName']}", + f"root=/dev/mapper/{partition['luksMapperName']}" ] if partition["fs"] == "zfs" and partition["mountPoint"] == "/": @@ -185,33 +183,28 @@ def modify_grub_default(partitions, root_mount_point, distributor): kernel_params.append(use_splash) if swap_uuid: - kernel_params.append("resume=UUID={!s}".format(swap_uuid)) + kernel_params.append(f"resume=UUID={swap_uuid}") if have_dracut and swap_outer_uuid: - kernel_params.append("rd.luks.uuid={!s}".format(swap_outer_uuid)) + kernel_params.append(f"rd.luks.uuid={swap_outer_uuid}") if swap_outer_mappername: - kernel_params.append("resume=/dev/mapper/{!s}".format( - swap_outer_mappername)) - - distributor_line = "GRUB_DISTRIBUTOR='{!s}'".format(distributor_replace) - - have_kernel_cmd = False - have_distributor_line = False + kernel_params.append(f"resume=/dev/mapper/{swap_outer_mappername}") if "overwrite" in libcalamares.job.configuration: overwrite = libcalamares.job.configuration["overwrite"] else: overwrite = False + distributor_line = f"GRUB_DISTRIBUTOR='{distributor_replace}'" + kernel_cmd = f'GRUB_CMDLINE_LINUX_DEFAULT="{" ".join(kernel_params)}"' + have_kernel_cmd = False + have_distributor_line = False if os.path.exists(default_grub) and not overwrite: with open(default_grub, 'r') as grub_file: lines = [x.strip() for x in grub_file.readlines()] for i in range(len(lines)): if lines[i].startswith("#GRUB_CMDLINE_LINUX_DEFAULT"): - kernel_cmd = "GRUB_CMDLINE_LINUX_DEFAULT=\"{!s}\"".format( - " ".join(kernel_params) - ) lines[i] = kernel_cmd have_kernel_cmd = True elif lines[i].startswith("GRUB_CMDLINE_LINUX_DEFAULT"): @@ -233,18 +226,15 @@ def modify_grub_default(partitions, root_mount_point, distributor): "quiet", "resume", "splash"]: kernel_params.append(existing_param) - kernel_cmd = "GRUB_CMDLINE_LINUX_DEFAULT=\"{!s}\"".format( - " ".join(kernel_params) - ) lines[i] = kernel_cmd have_kernel_cmd = True elif (lines[i].startswith("#GRUB_DISTRIBUTOR") or lines[i].startswith("GRUB_DISTRIBUTOR")): - if libcalamares.job.configuration.get("keepDistributor", False): + if libcalamares.job.configuration.get("keep_distributor", False): lines[i] = distributor_line have_distributor_line = True else: - # We're not updating because of *keepDistributor*, but if + # We're not updating because of *keep_distributor*, but if # this was a comment line, then it's still not been set. have_distributor_line = have_distributor_line or not lines[i].startswith("#") # If btrfs or f2fs is used, don't save default @@ -264,12 +254,9 @@ def modify_grub_default(partitions, root_mount_point, distributor): else: escaped_value = str(value).replace("'", "'\\''") - lines.append("{!s}='{!s}'".format(key, escaped_value)) + lines.append(f"{key}='{escaped_value}'") if not have_kernel_cmd: - kernel_cmd = "GRUB_CMDLINE_LINUX_DEFAULT=\"{!s}\"".format( - " ".join(kernel_params) - ) lines.append(kernel_cmd) if not have_distributor_line: @@ -290,28 +277,23 @@ def run(): :return: """ - fw_type = libcalamares.globalstorage.value("firmwareType") - - if (libcalamares.globalstorage.value("bootLoader") is None - and fw_type != "efi"): - return None - partitions = libcalamares.globalstorage.value("partitions") + root_mount_point = libcalamares.globalstorage.value("rootMountPoint") + branding = libcalamares.globalstorage.value("branding") + distributor = branding["bootloaderEntryName"] + + if libcalamares.globalstorage.value("bootLoader") is None and fw_type != "efi": + return None if fw_type == "efi": esp_found = False for partition in partitions: - if (partition["mountPoint"] - == libcalamares.globalstorage.value("efiSystemPartition")): + if partition["mountPoint"] == libcalamares.globalstorage.value("efiSystemPartition"): esp_found = True if not esp_found: return None - root_mount_point = libcalamares.globalstorage.value("rootMountPoint") - branding = libcalamares.globalstorage.value("branding") - distributor = branding["bootloaderEntryName"] - return modify_grub_default(partitions, root_mount_point, distributor) diff --git a/src/modules/grubcfg/tests/2.job b/src/modules/grubcfg/tests/2.job index 92e598394..5265ef5c8 100644 --- a/src/modules/grubcfg/tests/2.job +++ b/src/modules/grubcfg/tests/2.job @@ -2,7 +2,7 @@ # SPDX-License-Identifier: CC0-1.0 --- overwrite: true -keepDistributor: false +keep_distributor: false defaults: GRUB_TIMEOUT: 5 GRUB_DEFAULT: "saved" diff --git a/src/modules/grubcfg/tests/3.job b/src/modules/grubcfg/tests/3.job index 7d579839c..94f394373 100644 --- a/src/modules/grubcfg/tests/3.job +++ b/src/modules/grubcfg/tests/3.job @@ -3,7 +3,7 @@ --- overwrite: true prefer_grub_d: true # But it doesn't exist -keepDistributor: false +keep_distributor: false defaults: GRUB_TIMEOUT: 5 GRUB_DEFAULT: "saved" diff --git a/src/modules/grubcfg/tests/4.job b/src/modules/grubcfg/tests/4.job index 58fd8bcb7..4fdc2e25c 100644 --- a/src/modules/grubcfg/tests/4.job +++ b/src/modules/grubcfg/tests/4.job @@ -3,7 +3,7 @@ --- overwrite: true prefer_grub_d: true -keepDistributor: false +keep_distributor: false defaults: GRUB_TIMEOUT: 5 GRUB_DEFAULT: "saved" diff --git a/src/modules/grubcfg/tests/CMakeTests.txt b/src/modules/grubcfg/tests/CMakeTests.txt index 54a0721e4..7ecfffceb 100644 --- a/src/modules/grubcfg/tests/CMakeTests.txt +++ b/src/modules/grubcfg/tests/CMakeTests.txt @@ -8,12 +8,10 @@ add_test( NAME make-grubcfg-dirs - COMMAND ${CMAKE_COMMAND} -E make_directory - /tmp/calamares/grubcfg-test-2/etc/default - /tmp/calamares/grubcfg-test-3/etc/default - /tmp/calamares/grubcfg-test-4/etc/default/grub.d - ) + COMMAND + ${CMAKE_COMMAND} -E make_directory /tmp/calamares/grubcfg-test-2/etc/default + /tmp/calamares/grubcfg-test-3/etc/default /tmp/calamares/grubcfg-test-4/etc/default/grub.d +) set_tests_properties(load-grubcfg-2 PROPERTIES DEPENDS make-grubcfg-dirs) set_tests_properties(load-grubcfg-3 PROPERTIES DEPENDS make-grubcfg-dirs) set_tests_properties(load-grubcfg-4 PROPERTIES DEPENDS make-grubcfg-dirs) - diff --git a/src/modules/hostinfo/CMakeLists.txt b/src/modules/hostinfo/CMakeLists.txt index 55be66f81..af1b3ff45 100644 --- a/src/modules/hostinfo/CMakeLists.txt +++ b/src/modules/hostinfo/CMakeLists.txt @@ -23,7 +23,7 @@ # - *hostCPU* the make (brand) of the CPU, if it can be determined. # Values are "Intel" or "AMD" or blank. -calamares_add_plugin( hostinfo +calamares_add_plugin(hostinfo TYPE job EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -32,15 +32,9 @@ calamares_add_plugin( hostinfo NO_CONFIG ) -if ( KF5CoreAddons_FOUND AND KF5CoreAddons_VERSION VERSION_GREATER_EQUAL 5.58 ) - target_compile_definitions( calamares_job_hostinfo PRIVATE WITH_KOSRelease ) +if(KF5CoreAddons_FOUND AND KF5CoreAddons_VERSION VERSION_GREATER_EQUAL 5.58) + target_compile_definitions(calamares_job_hostinfo PRIVATE WITH_KOSRelease) + target_link_libraries(calamares_job_hostinfo PRIVATE KF5::CoreAddons) endif() -calamares_add_test( - hostinfotest - SOURCES - Tests.cpp - HostInfoJob.cpp - LIBRARIES - yamlcpp::yamlcpp -) +calamares_add_test(hostinfotest SOURCES Tests.cpp HostInfoJob.cpp LIBRARIES yamlcpp::yamlcpp) diff --git a/src/modules/initcpio/CMakeLists.txt b/src/modules/initcpio/CMakeLists.txt index 48fd09371..1bbb9fdd9 100644 --- a/src/modules/initcpio/CMakeLists.txt +++ b/src/modules/initcpio/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -calamares_add_plugin( initcpio +calamares_add_plugin(initcpio TYPE job EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -13,8 +13,7 @@ calamares_add_plugin( initcpio calamares_add_test( initcpiotest - SOURCES - Tests.cpp + SOURCES Tests.cpp LIBRARIES calamares_job_initcpio # From above yamlcpp::yamlcpp diff --git a/src/modules/initcpiocfg/main.py b/src/modules/initcpiocfg/main.py index a821aee14..6f94594aa 100644 --- a/src/modules/initcpiocfg/main.py +++ b/src/modules/initcpiocfg/main.py @@ -12,7 +12,6 @@ # Calamares is Free Software: see the License-Identifier above. # -import libcalamares from libcalamares.utils import debug, target_env_call import os from collections import OrderedDict @@ -102,7 +101,7 @@ def get_host_initcpio(): with open(hostfile, "r") as mkinitcpio_file: mklins = [x.strip() for x in mkinitcpio_file.readlines()] except FileNotFoundError: - libcalamares.utils.debug("Could not open host file '%s'" % hostfile) + libcalamares.utils.debug(f"Could not open host file {hostfile}") mklins = [] return mklins @@ -125,11 +124,11 @@ def write_mkinitcpio_lines(hooks, modules, files, root_mount_point): # Replace HOOKS, MODULES and FILES lines with what we # have found via find_initcpio_features() if line.startswith("HOOKS"): - line = "HOOKS=\"{!s}\"".format(' '.join(hooks)) + line = 'HOOKS="{!s}"'.format(' '.join(hooks)) elif line.startswith("MODULES"): - line = "MODULES=\"{!s}\"".format(' '.join(modules)) - elif line.startswith("FILES"): - line = "FILES=\"{!s}\"".format(' '.join(files)) + line = 'MODULES="{!s}"'.format(' '.join(modules)) + elif lines.startswith("FILES"): + line = 'FILES="{!s}"'.format(' '.join(files)) mkinitcpio_file.write(line + "\n") @@ -144,7 +143,16 @@ def find_initcpio_features(partitions, root_mount_point): :return 3-tuple of lists """ - hooks = ["base", "udev", "autodetect", "modconf", "block", "keyboard", "keymap", "consolefont"] + hooks = [ + "base", + "udev", + "autodetect", + "modconf", + "block", + "keyboard", + "keymap", + "consolefont", + ] modules = [] files = [] @@ -161,6 +169,8 @@ def find_initcpio_features(partitions, root_mount_point): hooks.append("plymouth") for partition in partitions: + hooks.extend(["filesystems"]) + if partition["fs"] == "linuxswap" and not partition.get("claimed", None): # Skip foreign swap continue @@ -194,11 +204,12 @@ def find_initcpio_features(partitions, root_mount_point): hooks.append("plymouth-encrypt") else: hooks.append("encrypt") + crypto_file = "crypto_keyfile.bin" if not unencrypted_separate_boot and \ os.path.isfile( - os.path.join(root_mount_point, "crypto_keyfile.bin") + os.path.join(root_mount_point, crypto_file) ): - files.append("/crypto_keyfile.bin") + files.append(f"/{crypto_file}") if uses_lvm2: hooks.append("lvm2") @@ -207,11 +218,9 @@ def find_initcpio_features(partitions, root_mount_point): hooks.append("zfs") if swap_uuid != "": + hooks.extend(["resume"]) if encrypt_hook and openswap_hook: hooks.extend(["openswap"]) - hooks.extend(["resume", "filesystems"]) - else: - hooks.extend(["filesystems"]) if uses_btrfs: modules.append("crc32c-intel" if cpuinfo().is_intel else "crc32c") @@ -223,7 +232,7 @@ def find_initcpio_features(partitions, root_mount_point): def run(): """ - Calls routine with given parameters to modify '/etc/mkinitcpio.conf'. + Calls routine with given parameters to modify "/etc/mkinitcpio.conf". :return: """ @@ -231,13 +240,13 @@ def run(): root_mount_point = libcalamares.globalstorage.value("rootMountPoint") if not partitions: - libcalamares.utils.warning("partitions is empty, {!s}".format(partitions)) + libcalamares.utils.warning(f"partitions are empty, {partitions}") return (_("Configuration Error"), - _("No partitions are defined for
{!s}
to use." ).format("initcpiocfg")) + _("No partitions are defined for
initcpiocfg
.")) if not root_mount_point: - libcalamares.utils.warning("rootMountPoint is empty, {!s}".format(root_mount_point)) + libcalamares.utils.warning(f"rootMountPoint is empty, {root_mount_point}") return (_("Configuration Error"), - _("No root mount point is given for
{!s}
to use." ).format("initcpiocfg")) + _("No root mount point for
initcpiocfg
.")) hooks, modules, files = find_initcpio_features(partitions, root_mount_point) write_mkinitcpio_lines(hooks, modules, files, root_mount_point) diff --git a/src/modules/initramfs/CMakeLists.txt b/src/modules/initramfs/CMakeLists.txt index 2dec41cba..45f29c387 100644 --- a/src/modules/initramfs/CMakeLists.txt +++ b/src/modules/initramfs/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -calamares_add_plugin( initramfs +calamares_add_plugin(initramfs TYPE job EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -13,8 +13,7 @@ calamares_add_plugin( initramfs calamares_add_test( initramfstest - SOURCES - Tests.cpp + SOURCES Tests.cpp LIBRARIES calamares_job_initramfs # From above yamlcpp::yamlcpp diff --git a/src/modules/interactiveterminal/CMakeLists.txt b/src/modules/interactiveterminal/CMakeLists.txt index 20aee8257..8ade23dbd 100644 --- a/src/modules/interactiveterminal/CMakeLists.txt +++ b/src/modules/interactiveterminal/CMakeLists.txt @@ -5,21 +5,15 @@ # find_package(ECM ${ECM_VERSION} REQUIRED NO_MODULE) -set( kf5_ver 5.41 ) +set(kf5_ver 5.41) -find_package( KF5Service ${kf5_ver} ) -find_package( KF5Parts ${kf5_ver} ) -set_package_properties( - KF5Service PROPERTIES - PURPOSE "For finding KDE services at runtime" -) -set_package_properties( - KF5Parts PROPERTIES - PURPOSE "For finding KDE parts at runtime" -) +find_package(KF5Service ${kf5_ver}) +find_package(KF5Parts ${kf5_ver}) +set_package_properties(KF5Service PROPERTIES PURPOSE "For finding KDE services at runtime") +set_package_properties(KF5Parts PROPERTIES PURPOSE "For finding KDE parts at runtime") -if ( KF5Parts_FOUND AND KF5Service_FOUND ) - calamares_add_plugin( interactiveterminal +if(KF5Parts_FOUND AND KF5Service_FOUND) + calamares_add_plugin(interactiveterminal TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/keyboard/CMakeLists.txt b/src/modules/keyboard/CMakeLists.txt index fe341cef0..a2e09dc41 100644 --- a/src/modules/keyboard/CMakeLists.txt +++ b/src/modules/keyboard/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -calamares_add_plugin( keyboard +calamares_add_plugin(keyboard TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -21,11 +21,4 @@ calamares_add_plugin( keyboard SHARED_LIB ) -calamares_add_test( - keyboardtest - SOURCES - Tests.cpp - SetKeyboardLayoutJob.cpp - RESOURCES - keyboard.qrc -) +calamares_add_test(keyboardtest SOURCES Tests.cpp SetKeyboardLayoutJob.cpp RESOURCES keyboard.qrc) diff --git a/src/modules/keyboardq/CMakeLists.txt b/src/modules/keyboardq/CMakeLists.txt index 2b0577aa7..9c7922d86 100644 --- a/src/modules/keyboardq/CMakeLists.txt +++ b/src/modules/keyboardq/CMakeLists.txt @@ -3,16 +3,16 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -if( NOT WITH_QML ) +if(NOT WITH_QML) calamares_skip_module( "keyboardq (QML is not supported in this build)" ) return() endif() -set( _keyboard ${CMAKE_CURRENT_SOURCE_DIR}/../keyboard ) +set(_keyboard ${CMAKE_CURRENT_SOURCE_DIR}/../keyboard) -include_directories( ${_keyboard} ) +include_directories(${_keyboard}) -calamares_add_plugin( keyboardq +calamares_add_plugin(keyboardq TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/license/CMakeLists.txt b/src/modules/license/CMakeLists.txt index 0cd838799..d214d6ca7 100644 --- a/src/modules/license/CMakeLists.txt +++ b/src/modules/license/CMakeLists.txt @@ -3,9 +3,9 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) +include_directories(${PROJECT_BINARY_DIR}/src/libcalamaresui) -calamares_add_plugin( license +calamares_add_plugin(license TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/license/LicensePage.cpp b/src/modules/license/LicensePage.cpp index 8700aad60..eb609b2da 100644 --- a/src/modules/license/LicensePage.cpp +++ b/src/modules/license/LicensePage.cpp @@ -98,7 +98,12 @@ LicensePage::LicensePage( QWidget* parent ) CalamaresUtils::unmarginLayout( ui->verticalLayout ); ui->acceptFrame->setStyleSheet( mustAccept ); - ui->acceptFrame->layout()->setMargin( CalamaresUtils::defaultFontHeight() / 2 ); + { + // The inner frame was unmargined (above), reinstate margins so all are + // the same *x* (an x-height, approximately). + const auto x = CalamaresUtils::defaultFontHeight() / 2; + ui->acceptFrame->layout()->setContentsMargins( x, x, x, x ); + } updateGlobalStorage( false ); // Have not agreed yet @@ -110,7 +115,11 @@ LicensePage::LicensePage( QWidget* parent ) void LicensePage::setEntries( const QList< LicenseEntry >& entriesList ) { - CalamaresUtils::clearLayout( ui->licenseEntriesLayout ); + for ( QWidget* w : m_entries ) + { + ui->licenseEntriesLayout->removeWidget( w ); + w->deleteLater(); + } m_allLicensesOptional = true; @@ -123,7 +132,6 @@ LicensePage::setEntries( const QList< LicenseEntry >& entriesList ) m_entries.append( w ); m_allLicensesOptional &= !entry.isRequired(); } - ui->licenseEntriesLayout->addSpacerItem( new QSpacerItem( 10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding ) ); ui->acceptCheckBox->setChecked( false ); checkAcceptance( false ); diff --git a/src/modules/locale/CMakeLists.txt b/src/modules/locale/CMakeLists.txt index 272dea3de..bad6042a6 100644 --- a/src/modules/locale/CMakeLists.txt +++ b/src/modules/locale/CMakeLists.txt @@ -7,14 +7,14 @@ # When debugging the timezone widget, add this debugging definition # to have a debugging-friendly timezone widget, debug logging, # and no intrusive timezone-setting while clicking around. -option( DEBUG_TIMEZONES "Debug-friendly timezone widget." OFF ) -if( DEBUG_TIMEZONES ) - add_definitions( -DDEBUG_TIMEZONES ) +option(DEBUG_TIMEZONES "Debug-friendly timezone widget." OFF) +if(DEBUG_TIMEZONES) + add_definitions(-DDEBUG_TIMEZONES) endif() -include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) +include_directories(${PROJECT_BINARY_DIR}/src/libcalamaresui) -calamares_add_plugin( locale +calamares_add_plugin(locale TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -39,15 +39,7 @@ calamares_add_plugin( locale calamares_add_test( localetest - SOURCES - Tests.cpp - Config.cpp - LocaleConfiguration.cpp - SetTimezoneJob.cpp - timezonewidget/TimeZoneImage.cpp - DEFINITIONS - SOURCE_DIR="${CMAKE_CURRENT_LIST_DIR}/images" - DEBUG_TIMEZONES=1 - LIBRARIES - Qt5::Gui + SOURCES Tests.cpp Config.cpp LocaleConfiguration.cpp SetTimezoneJob.cpp timezonewidget/TimeZoneImage.cpp + DEFINITIONS SOURCE_DIR="${CMAKE_CURRENT_LIST_DIR}/images" DEBUG_TIMEZONES=1 + LIBRARIES Qt5::Gui ) diff --git a/src/modules/locale/LocaleViewStep.cpp b/src/modules/locale/LocaleViewStep.cpp index 2145ad201..03d1d4f5e 100644 --- a/src/modules/locale/LocaleViewStep.cpp +++ b/src/modules/locale/LocaleViewStep.cpp @@ -11,7 +11,6 @@ #include "LocaleViewStep.h" #include "LocalePage.h" -#include "widgets/WaitingWidget.h" #include "GlobalStorage.h" #include "JobQueue.h" diff --git a/src/modules/localeq/CMakeLists.txt b/src/modules/localeq/CMakeLists.txt index ee3f07314..f086676e6 100644 --- a/src/modules/localeq/CMakeLists.txt +++ b/src/modules/localeq/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -if( NOT WITH_QML ) +if(NOT WITH_QML) calamares_skip_module( "localeq (QML is not supported in this build)" ) return() endif() @@ -11,28 +11,22 @@ endif() # When debugging the timezone widget, add this debugging definition # to have a debugging-friendly timezone widget, debug logging, # and no intrusive timezone-setting while clicking around. -option( DEBUG_TIMEZONES "Debug-friendly timezone widget." OFF ) -if( DEBUG_TIMEZONES ) - add_definitions( -DDEBUG_TIMEZONES ) +option(DEBUG_TIMEZONES "Debug-friendly timezone widget." OFF) +if(DEBUG_TIMEZONES) + add_definitions(-DDEBUG_TIMEZONES) endif() find_package(Qt5Location CONFIG) -set_package_properties(Qt5Location PROPERTIES - DESCRIPTION "Used for rendering the map" - TYPE RUNTIME -) +set_package_properties(Qt5Location PROPERTIES DESCRIPTION "Used for rendering the map" TYPE RUNTIME) find_package(Qt5Positioning CONFIG) -set_package_properties(Qt5Positioning PROPERTIES - DESCRIPTION "Used for GeoLocation and GeoCoding" - TYPE RUNTIME -) +set_package_properties(Qt5Positioning PROPERTIES DESCRIPTION "Used for GeoLocation and GeoCoding" TYPE RUNTIME) # Because we're sharing sources with the regular locale module -set( _locale ${CMAKE_CURRENT_SOURCE_DIR}/../locale ) +set(_locale ${CMAKE_CURRENT_SOURCE_DIR}/../locale) -include_directories( ${_locale} ) +include_directories(${_locale}) -calamares_add_plugin( localeq +calamares_add_plugin(localeq TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/luksopenswaphookcfg/CMakeLists.txt b/src/modules/luksopenswaphookcfg/CMakeLists.txt index caede06a7..f186fbdc6 100644 --- a/src/modules/luksopenswaphookcfg/CMakeLists.txt +++ b/src/modules/luksopenswaphookcfg/CMakeLists.txt @@ -6,7 +6,7 @@ # Because LUKS Open Swap Hook (Job) is such a mouthful, we'll # use LOSH all over the place as a shorthand. -calamares_add_plugin( luksopenswaphookcfg +calamares_add_plugin(luksopenswaphookcfg TYPE job EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -14,9 +14,4 @@ calamares_add_plugin( luksopenswaphookcfg SHARED_LIB ) -calamares_add_test( - luksopenswaphooktest - SOURCES - LOSHJob.cpp - Tests.cpp -) +calamares_add_test(luksopenswaphooktest SOURCES LOSHJob.cpp Tests.cpp) diff --git a/src/modules/luksopenswaphookcfg/LOSHJob.cpp b/src/modules/luksopenswaphookcfg/LOSHJob.cpp index 42f160460..ad3b0abea 100644 --- a/src/modules/luksopenswaphookcfg/LOSHJob.cpp +++ b/src/modules/luksopenswaphookcfg/LOSHJob.cpp @@ -163,7 +163,7 @@ globalStoragePartitionInfo( Calamares::GlobalStorage* gs, LOSHInfo& info ) QString btrfsRootSubvolume = gs->value( "btrfsRootSubvolume" ).toString(); if ( !btrfsRootSubvolume.isEmpty() ) { - CalamaresUtils::removeLeading( btrfsRootSubvolume, '/' ); + Calamares::String::removeLeading( btrfsRootSubvolume, '/' ); info.keyfile_device_mount_options = QStringLiteral( "keyfile_device_mount_options=--options=subvol=" ) + btrfsRootSubvolume; } diff --git a/src/modules/machineid/CMakeLists.txt b/src/modules/machineid/CMakeLists.txt index 0ab035ab4..869d11387 100644 --- a/src/modules/machineid/CMakeLists.txt +++ b/src/modules/machineid/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -calamares_add_plugin( machineid +calamares_add_plugin(machineid TYPE job EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -12,10 +12,4 @@ calamares_add_plugin( machineid SHARED_LIB ) -calamares_add_test( - machineidtest - SOURCES - Tests.cpp - MachineIdJob.cpp - Workers.cpp -) +calamares_add_test(machineidtest SOURCES Tests.cpp MachineIdJob.cpp Workers.cpp) diff --git a/src/modules/mount/main.py b/src/modules/mount/main.py index a3318d1a0..d8041f9ce 100644 --- a/src/modules/mount/main.py +++ b/src/modules/mount/main.py @@ -16,6 +16,7 @@ import tempfile import subprocess import os +import re import libcalamares @@ -42,6 +43,79 @@ def pretty_name(): return _("Mounting partitions.") +def disk_name_for_partition(partition): + """ Returns disk name for each found partition. + + :param partition: + :return: + """ + name = os.path.basename(partition["device"]) + + if name.startswith("/dev/mmcblk") or name.startswith("/dev/nvme"): + return re.sub("p[0-9]+$", "", name) + + return re.sub("[0-9]+$", "", name) + + +def is_ssd_disk(partition): + """ Checks if given partition is on an ssd disk. + + :param partition: A dict containing the partition information + :return: True is the partition in on an ssd, False otherwise + """ + + try: + disk_name = disk_name_for_partition(partition) + filename = os.path.join("/sys/block", disk_name, "queue/rotational") + + with open(filename) as sysfile: + return sysfile.read() == "0\n" + except: + return False + + +def get_mount_options(filesystem, mount_options, partition): + """ + Returns the mount options for the partition object and filesystem + + :param filesystem: A string containing the filesystem + :param mount_options: A list of dicts that descripes the mount options for each mountpoint + :param partition: A dict containing information about the partition + :return: A comma seperated string containing the mount options suitable for passing to mount + """ + + # Extra mounts can optionally have "options" set, in this case, they override other all other settings + if "options" in partition: + return ",".join(partition["options"]) + + # If there are no mount options defined then we use the defaults + if mount_options is None: + return "defaults" + + options = next((x for x in mount_options if x["filesystem"] == filesystem), None) + + # If there is no match then check for default options + if options is None: + options = next((x for x in mount_options if x["filesystem"] == "default"), None) + + # If it is still None, then fallback to returning defaults + if options is None: + return "defaults" + + option_items = options.get("options", []).copy() + + # Append the appropriate options for ssd or hdd if set + if is_ssd_disk(partition): + option_items.extend(options.get("ssdOptions", [])) + else: + option_items.extend(options.get("hddOptions", [])) + + if option_items: + return ",".join(option_items) + else: + return "defaults" + + def get_btrfs_subvolumes(partitions): """ Gets the job-configuration for btrfs subvolumes, or if there is @@ -69,7 +143,9 @@ def get_btrfs_subvolumes(partitions): # If we have a swap **file**, give it a separate subvolume. swap_choice = libcalamares.globalstorage.value("partitionChoices") if swap_choice and swap_choice.get("swap", None) == "file": - btrfs_subvolumes.append({'mountPoint': '/swap', 'subvolume': '/@swap'}) + swap_subvol = libcalamares.job.configuration.get("btrfsSwapSubvol", "/@swap") + btrfs_subvolumes.append({'mountPoint': '/swap', 'subvolume': swap_subvol}) + libcalamares.globalstorage.insert("btrfsSwapSubvol", swap_subvol) return btrfs_subvolumes @@ -138,9 +214,16 @@ def mount_zfs(root_mount_point, partition): raise ZfsException(_("Failed to set zfs mountpoint")) -def mount_partition(root_mount_point, partition, partitions): +def mount_partition(root_mount_point, partition, partitions, mount_options, mount_options_list): """ Do a single mount of @p partition inside @p root_mount_point. + + :param root_mount_point: A string containing the root of the install + :param partition: A dict containing information about the partition + :param partitions: The full list of partitions used to filter out btrfs subvols which have duplicate mountpoints + :param mount_options: The mount options from the config file + :param mount_options_list: A list of options for each mountpoint to be placed in global storage for future modules + :return: """ # Create mount point with `+` rather than `os.path.join()` because # `partition["mountPoint"]` starts with a '/'. @@ -176,11 +259,13 @@ def mount_partition(root_mount_point, partition, partitions): if fstype == "zfs": mount_zfs(root_mount_point, partition) else: # fstype == "zfs" + mount_options_string = get_mount_options(fstype, mount_options, partition) if libcalamares.utils.mount(device, mount_point, fstype, - partition.get("options", "")) != 0: + mount_options_string) != 0: libcalamares.utils.warning("Cannot mount {}".format(device)) + mount_options_list.append({"mountpoint": raw_mount_point, "option_string": mount_options_string}) # Special handling for btrfs subvolumes. Create the subvolumes listed in mount.conf if fstype == "btrfs" and partition["mountPoint"] == '/': @@ -207,13 +292,19 @@ def mount_partition(root_mount_point, partition, partitions): device = os.path.join("/dev/mapper", partition["luksMapperName"]) # Mount the subvolumes + swap_subvol = libcalamares.job.configuration.get("btrfsSwapSubvol", "/@swap") for s in btrfs_subvolumes: mount_option = "subvol={}".format(s['subvolume']) + if s['subvolume'] == swap_subvol: + mount_option += "," + get_mount_options("btrfs_swap", mount_options, partition) + else: + mount_option += "," + get_mount_options(fstype, mount_options, partition) subvolume_mountpoint = mount_point[:-1] + s['mountPoint'] + mount_options_list.append({"mountpoint": s['mountPoint'], "option_string": mount_option}) if libcalamares.utils.mount(device, subvolume_mountpoint, fstype, - ",".join([mount_option, partition.get("options", "")])) != 0: + mount_option) != 0: libcalamares.utils.warning("Cannot mount {}".format(device)) @@ -222,6 +313,7 @@ def run(): Mount all the partitions from GlobalStorage and from the job configuration. Partitions are mounted in-lexical-order of their mountPoint. """ + partitions = libcalamares.globalstorage.value("partitions") if not partitions: @@ -231,14 +323,18 @@ def run(): root_mount_point = tempfile.mkdtemp(prefix="calamares-root-") + # Get the mountOptions, if this is None, that is OK and will be handled later + mount_options = libcalamares.job.configuration.get("mountOptions") + # Guard against missing keys (generally a sign that the config file is bad) extra_mounts = libcalamares.job.configuration.get("extraMounts") or [] - extra_mounts_efi = libcalamares.job.configuration.get("extraMountsEfi") or [] - if not extra_mounts and not extra_mounts_efi: + if not extra_mounts: libcalamares.utils.warning("No extra mounts defined. Does mount.conf exist?") - if libcalamares.globalstorage.value("firmwareType") == "efi": - extra_mounts.extend(extra_mounts_efi) + if libcalamares.globalstorage.value("firmwareType") != "efi": + for mount in extra_mounts: + if mount.get("efi", None) is True: + extra_mounts.remove(mount) # Add extra mounts to the partitions list and sort by mount points. # This way, we ensure / is mounted before the rest, and every mount point @@ -246,13 +342,17 @@ def run(): # under /tmp, we make sure /tmp is mounted before the partition) mountable_partitions = [p for p in partitions + extra_mounts if "mountPoint" in p and p["mountPoint"]] mountable_partitions.sort(key=lambda x: x["mountPoint"]) + + # mount_options_list will be inserted into global storage for use in fstab later + mount_options_list = [] try: for partition in mountable_partitions: - mount_partition(root_mount_point, partition, partitions) + mount_partition(root_mount_point, partition, partitions, mount_options, mount_options_list) except ZfsException as ze: return _("zfs mounting error"), ze.message libcalamares.globalstorage.insert("rootMountPoint", root_mount_point) + libcalamares.globalstorage.insert("mountOptionsList", mount_options_list) # Remember the extra mounts for the unpackfs module libcalamares.globalstorage.insert("extraMounts", extra_mounts) diff --git a/src/modules/mount/mount.conf b/src/modules/mount/mount.conf index 84dca05a7..97e512846 100644 --- a/src/modules/mount/mount.conf +++ b/src/modules/mount/mount.conf @@ -5,16 +5,15 @@ # target as a usable chroot / "live" system). Filesystems are # automatically mounted from the partitioning module. Filesystems # listed here are **extra**. The filesystems listed in *extraMounts* -# are mounted in all target systems. The filesystems listed in -# *extraMountsEfi* are mounted in the target system **only** if -# the host machine uses UEFI. +# are mounted in all target systems. --- # Extra filesystems to mount. The key's value is a list of entries; each -# entry has four keys: +# entry has five keys: # - device The device node to mount # - fs (optional) The filesystem type to use # - mountPoint Where to mount the filesystem -# - options (optional) Extra options to pass to mount(8) +# - options (optional) An array of options to pass to mount +# - efi (optional) A boolean that when true is only mounted for UEFI installs # # The device is not mounted if the mountPoint is unset or if the fs is # set to unformatted. @@ -28,18 +27,17 @@ extraMounts: mountPoint: /sys - device: /dev mountPoint: /dev - options: bind + options: [ bind ] - device: tmpfs fs: tmpfs mountPoint: /run - device: /run/udev mountPoint: /run/udev - options: bind - -extraMountsEfi: + options: [ bind ] - device: efivarfs fs: efivarfs mountPoint: /sys/firmware/efi/efivars + efi: true # Btrfs subvolumes to create if root filesystem is on btrfs volume. # If *mountpoint* is mounted already to another partition, it is ignored. @@ -47,10 +45,8 @@ extraMountsEfi: # # It is possible to prevent subvolume creation -- this is likely only relevant # for the root (/) subvolume -- by giving an empty string as a subvolume -# name. In this case no subvolume will be created. When using snapper as -# a rollback mechanism, it is recommended to **not** create a subvolume -# for root. - +# name. In this case no subvolume will be created. +# btrfsSubvolumes: - mountPoint: / subvolume: /@ @@ -63,3 +59,67 @@ btrfsSubvolumes: subvolume: /@cache - mountPoint: /var/log subvolume: /@log + +# The name of the btrfs subvolume holding the swapfile. This only used when +# a swapfile is selected and the root filesystem is btrfs +# +btrfsSwapSubvol: /@swap + +# The mount options used to mount each filesystem. +# +# filesystem contains the name of the filesystem or on of three special +# values, "default", efi" and "btrfs_swap". The logic is applied in this manner: +# - If the partition is the EFI partition, the "efi" entry will be used +# - If the fs is btrfs and the subvolume is for the swapfile, +# the "btrfs_swap" entry is used +# - If the filesystem is an exact match for filesystem, that entry is used +# - If no match is found in the above, the default entry is used +# - If there is no match and no default entry, "defaults" is used +# - If the mountOptions key is not present, "defaults" is used +# +# Each filesystem entry contains 3 keys, all of which are optional +# options - An array of mount options that is used on all disk types +# ssdOptions - An array of mount options combined with options for ssds +# hddOptions - An array of mount options combined with options for hdds +# If combining these options results in an empty array, "defaults" is used +# +# Example 1 +# In this example, there are specific options for ext4 and btrfs filesystems, +# the EFI partition and the subvolume holding the btrfs swapfile. All other +# filesystems use the default entry. For the btrfs filesystem, there are +# additional options specific to hdds and ssds +# +# mountOptions: +# - filesystem: default +# options: [ defaults ] +# - filesystem: efi +# options: [ defaults, umask=0077 ] +# - filesystem: ext4 +# options: [ defaults, noatime ] +# - filesystem: btrfs +# options: [ defaults, noatime, compress=zstd:1 ] +# ssdOptions: [ discard=async ] +# hddOptions: [ autodefrag ] +# - filesystem: btrfs_swap +# options: [ defaults, noatime ] +# +# Example 2 +# In this example there is a single default used by all filesystems +# +# mountOptions: +# - filesystem: default +# options: [ defaults, noatime ] +# +mountOptions: + - filesystem: default + options: [ defaults, noatime ] + - filesystem: efi + options: [ defaults, umask=0077 ] + - filesystem: btrfs + options: [ defaults, noatime, compress=lzo ] + - filesystem: btrfs_swap + options: [ defaults, noatime ] + + + + diff --git a/src/modules/mount/mount.schema.yaml b/src/modules/mount/mount.schema.yaml index fb5dfb69c..a083ed75a 100644 --- a/src/modules/mount/mount.schema.yaml +++ b/src/modules/mount/mount.schema.yaml @@ -6,7 +6,6 @@ $id: https://calamares.io/schemas/mount additionalProperties: false type: object properties: - # TODO: share the schema definition, since these are identical extraMounts: type: array items: @@ -16,18 +15,8 @@ properties: device: { type: string } fs: { type: string } mountPoint: { type: string } - options: { type: string } - required: [ device, mountPoint ] - extraMountsEfi: - type: array - items: - type: object - additionalProperties: false - properties: - device: { type: string } - fs: { type: string } - mountPoint: { type: string } - options: { type: string } + options: { type: array, items: { type: string } } + efi: { type: boolean, default: false } required: [ device, mountPoint ] btrfsSubvolumes: type: array @@ -38,3 +27,17 @@ properties: mountPoint: { type: string } subvolume: { type: string } required: [ subvolume, mountPoint ] + btrfsSwapSubvol: { type: string } + mountOptions: + type: array + items: + type: object + additionalProperties: false + properties: + filesystem: { type: string } + options: { type: array, items: { type: string } } + ssdOptions: { type: array, items: { type: string } } + hddOptions: { type: array, items: { type: string } } + required: [ filesystem ] + + diff --git a/src/modules/netinstall/CMakeLists.txt b/src/modules/netinstall/CMakeLists.txt index 13c6fa0ce..e605905c4 100644 --- a/src/modules/netinstall/CMakeLists.txt +++ b/src/modules/netinstall/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -calamares_add_plugin( netinstall +calamares_add_plugin(netinstall TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -21,15 +21,10 @@ calamares_add_plugin( netinstall SHARED_LIB ) -calamares_add_test( - netinstalltest - SOURCES - Tests.cpp - Config.cpp - LoaderQueue.cpp - PackageTreeItem.cpp - PackageModel.cpp - LIBRARIES - Qt5::Gui -) - +if(KF5CoreAddons_FOUND) + calamares_add_test( + netinstalltest + SOURCES Tests.cpp Config.cpp LoaderQueue.cpp PackageTreeItem.cpp PackageModel.cpp + LIBRARIES Qt5::Gui Qt5::Network KF5::CoreAddons + ) +endif() diff --git a/src/modules/notesqml/CMakeLists.txt b/src/modules/notesqml/CMakeLists.txt index 5eab06663..c76ab5179 100644 --- a/src/modules/notesqml/CMakeLists.txt +++ b/src/modules/notesqml/CMakeLists.txt @@ -3,12 +3,12 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -if( NOT WITH_QML ) +if(NOT WITH_QML) calamares_skip_module( "notesqml (QML is not supported in this build)" ) return() endif() -calamares_add_plugin( notesqml +calamares_add_plugin(notesqml TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/oemid/CMakeLists.txt b/src/modules/oemid/CMakeLists.txt index af7fe1ff7..45825c85e 100644 --- a/src/modules/oemid/CMakeLists.txt +++ b/src/modules/oemid/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -calamares_add_plugin( oemid +calamares_add_plugin(oemid TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt index d2e6ff118..e565fd05e 100644 --- a/src/modules/packagechooser/CMakeLists.txt +++ b/src/modules/packagechooser/CMakeLists.txt @@ -3,45 +3,46 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -find_package( Qt5 COMPONENTS Core Gui Widgets REQUIRED ) -set( _extra_libraries "" ) -set( _extra_src "" ) +find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED) +set(_extra_libraries "") +set(_extra_src "") ### OPTIONAL AppData XML support in PackageModel # # # TODO:3.3:WITH->BUILD (this doesn't affect the ABI offered by Calamares) -option( WITH_APPDATA "Support appdata: items in PackageChooser (requires QtXml)" ON ) -if ( WITH_APPDATA ) +option(WITH_APPDATA "Support appdata: items in PackageChooser (requires QtXml)" ON) +if(WITH_APPDATA) find_package(Qt5 COMPONENTS Xml) - if ( Qt5Xml_FOUND ) - add_definitions( -DHAVE_APPDATA ) - list( APPEND _extra_libraries Qt5::Xml ) - list( APPEND _extra_src ItemAppData.cpp ) + if(Qt5Xml_FOUND) + add_definitions(-DHAVE_APPDATA) + list(APPEND _extra_libraries Qt5::Xml) + list(APPEND _extra_src ItemAppData.cpp) endif() endif() ### OPTIONAL AppStream support in PackageModel # # -option( WITH_APPSTREAM "Support appstream: items in PackageChooser (requires libappstream-qt)" ON ) -if ( WITH_APPSTREAM ) +option(WITH_APPSTREAM "Support appstream: items in PackageChooser (requires libappstream-qt)" ON) +if(WITH_APPSTREAM) find_package(AppStreamQt) set_package_properties( - AppStreamQt PROPERTIES + AppStreamQt + PROPERTIES DESCRIPTION "Support for AppStream (cache) data" URL "https://github.com/ximion/appstream" PURPOSE "AppStream provides package data" TYPE OPTIONAL ) - if ( AppStreamQt_FOUND ) - add_definitions( -DHAVE_APPSTREAM ) - list( APPEND _extra_libraries AppStreamQt ) - list( APPEND _extra_src ItemAppStream.cpp ) + if(AppStreamQt_FOUND) + add_definitions(-DHAVE_APPSTREAM) + list(APPEND _extra_libraries AppStreamQt) + list(APPEND _extra_src ItemAppStream.cpp) endif() endif() -calamares_add_plugin( packagechooser +calamares_add_plugin(packagechooser TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -62,9 +63,6 @@ calamares_add_plugin( packagechooser calamares_add_test( packagechoosertest GUI - SOURCES - Tests.cpp - LIBRARIES - calamares_viewmodule_packagechooser - ${_extra_libraries} + SOURCES Tests.cpp + LIBRARIES calamares_viewmodule_packagechooser ${_extra_libraries} ) diff --git a/src/modules/packagechooserq/CMakeLists.txt b/src/modules/packagechooserq/CMakeLists.txt index 51a17e215..0b2c4b23a 100644 --- a/src/modules/packagechooserq/CMakeLists.txt +++ b/src/modules/packagechooserq/CMakeLists.txt @@ -4,55 +4,56 @@ # SPDX-FileCopyrightText: 2021 Anke Boersma # SPDX-License-Identifier: BSD-2-Clause # -if( NOT WITH_QML ) +if(NOT WITH_QML) calamares_skip_module( "packagechooserq (QML is not supported in this build)" ) return() endif() -find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Core ) +find_package(Qt5 ${QT_VERSION} CONFIG REQUIRED Core) # Add optional libraries here -set( USER_EXTRA_LIB ) +set(USER_EXTRA_LIB) # include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../packagechooser ) -set( _packagechooser ${CMAKE_CURRENT_SOURCE_DIR}/../packagechooser ) -include_directories( ${_packagechooser} ) +set(_packagechooser ${CMAKE_CURRENT_SOURCE_DIR}/../packagechooser) +include_directories(${_packagechooser}) ### OPTIONAL AppData XML support in PackageModel # # # TODO:3.3:WITH->BUILD (this doesn't affect the ABI offered by Calamares) -option( WITH_APPDATA "Support appdata: items in PackageChooser (requires QtXml)" ON ) -if ( WITH_APPDATA ) +option(WITH_APPDATA "Support appdata: items in PackageChooser (requires QtXml)" ON) +if(WITH_APPDATA) find_package(Qt5 COMPONENTS Xml) - if ( Qt5Xml_FOUND ) - add_definitions( -DHAVE_APPDATA ) - list( APPEND _extra_libraries Qt5::Xml ) - list( APPEND _extra_src ${_packagechooser}/ItemAppData.cpp ) + if(Qt5Xml_FOUND) + add_definitions(-DHAVE_APPDATA) + list(APPEND _extra_libraries Qt5::Xml) + list(APPEND _extra_src ${_packagechooser}/ItemAppData.cpp) endif() endif() ### OPTIONAL AppStream support in PackageModel # # -option( WITH_APPSTREAM "Support appstream: items in PackageChooser (requires libappstream-qt)" ON ) -if ( WITH_APPSTREAM ) +option(WITH_APPSTREAM "Support appstream: items in PackageChooser (requires libappstream-qt)" ON) +if(WITH_APPSTREAM) find_package(AppStreamQt) set_package_properties( - AppStreamQt PROPERTIES + AppStreamQt + PROPERTIES DESCRIPTION "Support for AppStream (cache) data" URL "https://github.com/ximion/appstream" PURPOSE "AppStream provides package data" TYPE OPTIONAL ) - if ( AppStreamQt_FOUND ) - add_definitions( -DHAVE_APPSTREAM ) - list( APPEND _extra_libraries AppStreamQt ) - list( APPEND _extra_src ${_packagechooser}/ItemAppStream.cpp ) + if(AppStreamQt_FOUND) + add_definitions(-DHAVE_APPSTREAM) + list(APPEND _extra_libraries AppStreamQt) + list(APPEND _extra_src ${_packagechooser}/ItemAppStream.cpp) endif() endif() -calamares_add_plugin( packagechooserq +calamares_add_plugin(packagechooserq TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/packages/tests/CMakeTests.txt b/src/modules/packages/tests/CMakeTests.txt index 4f7d6185f..66da86b5a 100644 --- a/src/modules/packages/tests/CMakeTests.txt +++ b/src/modules/packages/tests/CMakeTests.txt @@ -14,29 +14,33 @@ add_test( ) add_test( NAME configure-packages-${_pm}-ops-1 - COMMAND env PYTHONPATH=.: python3 ${CMAKE_CURRENT_LIST_DIR}/test-pm-${_pm}.py ${CMAKE_CURRENT_LIST_DIR}/pm-pacman-1.yaml 4 1 1 + COMMAND + env PYTHONPATH=.: python3 ${CMAKE_CURRENT_LIST_DIR}/test-pm-${_pm}.py ${CMAKE_CURRENT_LIST_DIR}/pm-pacman-1.yaml + 4 1 1 WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) add_test( NAME configure-packages-${_pm}-ops-2 - COMMAND env PYTHONPATH=.: python3 ${CMAKE_CURRENT_LIST_DIR}/test-pm-${_pm}.py ${CMAKE_CURRENT_LIST_DIR}/pm-pacman-2.yaml 3 0 0 + COMMAND + env PYTHONPATH=.: python3 ${CMAKE_CURRENT_LIST_DIR}/test-pm-${_pm}.py ${CMAKE_CURRENT_LIST_DIR}/pm-pacman-2.yaml + 3 0 0 WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) -if ( BUILD_TESTING AND BUILD_SCHEMA_TESTING AND PYTHONINTERP_FOUND AND PYTHON_EXECUTABLE ) - set( _module packages ) - set( _schema_file "${CMAKE_CURRENT_SOURCE_DIR}/${_module}/${_module}.schema.yaml" ) +if(BUILD_TESTING AND BUILD_SCHEMA_TESTING AND Python_Interpreter_FOUND) + set(_module packages) + set(_schema_file "${CMAKE_CURRENT_SOURCE_DIR}/${_module}/${_module}.schema.yaml") message(STATUS "Schema ${_schema_file}") - foreach( _cf pm-pacman-1.yaml pm-pacman-2.yaml ) - set( _conf_file "${CMAKE_CURRENT_SOURCE_DIR}/${_module}/tests/${_cf}" ) - if ( EXISTS "${_schema_file}" AND EXISTS "${_conf_file}" ) + foreach(_cf pm-pacman-1.yaml pm-pacman-2.yaml) + set(_conf_file "${CMAKE_CURRENT_SOURCE_DIR}/${_module}/tests/${_cf}") + if(EXISTS "${_schema_file}" AND EXISTS "${_conf_file}") add_test( NAME validate-packages-${_cf} - COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_SOURCE_DIR}/ci/configvalidator.py" "${_schema_file}" "${_conf_file}" + COMMAND + ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/ci/configvalidator.py" "${_schema_file}" "${_conf_file}" ) else() message(FATAL_ERROR "Missing ${_conf_file}") endif() endforeach() endif() - diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt index 940aacdd8..6d07ec281 100644 --- a/src/modules/partition/CMakeLists.txt +++ b/src/modules/partition/CMakeLists.txt @@ -23,19 +23,19 @@ option( DEBUG_PARTITION_BAIL_OUT "Unsafe partitioning will error out on exec." O option( DEBUG_PARTITION_SKIP "Don't actually do any partitioning." OFF) # This is very chatty, useful mostly if you don't know what KPMCore offers. -option( DEBUG_FILESYSTEMS "Log all available Filesystems from KPMCore." OFF ) +option(DEBUG_FILESYSTEMS "Log all available Filesystems from KPMCore." OFF) -include_directories( ${CMAKE_SOURCE_DIR} ) # For 3rdparty +include_directories(${CMAKE_SOURCE_DIR}) # For 3rdparty set( _partition_defs ) if( DEBUG_PARTITION_UNSAFE ) if( DEBUG_PARTITION_BAIL_OUT ) list( APPEND _partition_defs DEBUG_PARTITION_BAIL_OUT ) endif() - list( APPEND _partition_defs DEBUG_PARTITION_UNSAFE ) + list(APPEND _partition_defs DEBUG_PARTITION_UNSAFE) endif() -if ( DEBUG_FILESYSTEMS ) - list( APPEND _partition_defs DEBUG_FILESYSTEMS ) +if(DEBUG_FILESYSTEMS) + list(APPEND _partition_defs DEBUG_FILESYSTEMS) endif() if( DEBUG_PARTITION_SKIP ) list( APPEND _partition_defs DEBUG_PARTITION_SKIP ) @@ -43,20 +43,20 @@ endif() find_package(ECM ${ECM_VERSION} REQUIRED NO_MODULE) -include( KPMcoreHelper ) +include(KPMcoreHelper) -find_package( KF5Config CONFIG ) -find_package( KF5I18n CONFIG ) -find_package( KF5WidgetsAddons CONFIG ) +find_package(KF5Config CONFIG) +find_package(KF5I18n CONFIG) +find_package(KF5WidgetsAddons CONFIG) -if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND ) - list( APPEND _partition_defs ${KPMcore_API_DEFINITIONS} ) - include_directories( ${KPMCORE_INCLUDE_DIR} ) - include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) +if(KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND) + list(APPEND _partition_defs ${KPMcore_API_DEFINITIONS}) + include_directories(${KPMCORE_INCLUDE_DIR}) + include_directories(${PROJECT_BINARY_DIR}/src/libcalamaresui) - add_subdirectory( tests ) + add_subdirectory(tests) - calamares_add_plugin( partition + calamares_add_plugin(partition TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -124,10 +124,9 @@ if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND SHARED_LIB ) else() - if ( NOT KPMcore_FOUND ) + if(NOT KPMcore_FOUND) calamares_skip_module( "partition (missing suitable KPMcore)" ) else() calamares_skip_module( "partition (missing dependencies for KPMcore)" ) endif() endif() - diff --git a/src/modules/partition/PartitionViewStep.cpp b/src/modules/partition/PartitionViewStep.cpp index 66817bab5..fe77bee3a 100644 --- a/src/modules/partition/PartitionViewStep.cpp +++ b/src/modules/partition/PartitionViewStep.cpp @@ -233,7 +233,7 @@ PartitionViewStep::createSummaryWidget() const QWidget* widget = new QWidget; QVBoxLayout* mainLayout = new QVBoxLayout; widget->setLayout( mainLayout ); - mainLayout->setMargin( 0 ); + CalamaresUtils::unmarginLayout( mainLayout ); Config::InstallChoice choice = m_config->installChoice(); @@ -508,11 +508,6 @@ PartitionViewStep::onLeave() { const QString espMountPoint = Calamares::JobQueue::instance()->globalStorage()->value( "efiSystemPartition" ).toString(); -#ifdef WITH_KPMCORE4API - const auto espFlag = PartitionTable::Flag::Boot; -#else - const auto espFlag = PartitionTable::FlagEsp; -#endif Partition* esp = m_core->findPartitionByMountPoint( espMountPoint ); QString message; @@ -567,7 +562,7 @@ PartitionViewStep::onLeave() cDebug() << o << "ESP missing flag"; description.append( ' ' ); description.append( tr( "The filesystem must have flag %1 set." ) - .arg( PartitionTable::flagName( espFlag ) ) ); + .arg( PartitionTable::flagName( PartitionTable::Flag::Boot ) ) ); } if ( !description.isEmpty() ) { diff --git a/src/modules/partition/core/BootLoaderModel.cpp b/src/modules/partition/core/BootLoaderModel.cpp index fd66c8514..f659fc593 100644 --- a/src/modules/partition/core/BootLoaderModel.cpp +++ b/src/modules/partition/core/BootLoaderModel.cpp @@ -3,6 +3,7 @@ * SPDX-FileCopyrightText: 2014 Aurélien Gâteau * SPDX-FileCopyrightText: 2015 Teo Mrnjavac * SPDX-FileCopyrightText: 2019 Adriaan de Groot + * SPDX-FileCopyrightText: 2021 Anubhav Choudhary * SPDX-License-Identifier: GPL-3.0-or-later * * Calamares is Free Software: see the License-Identifier above. @@ -79,7 +80,7 @@ BootLoaderModel::updateInternal() clear(); createMbrItems(); - // An empty model is possible if you don't havee permissions: don't crash though. + // An empty model is possible if you don't have permissions: don't crash though. if ( rowCount() < 1 ) { return; @@ -124,10 +125,10 @@ BootLoaderModel::updateInternal() { appendRow( createBootLoaderItem( partitionText, PartitionInfo::mountPoint( partition ), true ) ); } - - // Create "don't install bootloader" item - appendRow( createBootLoaderItem( tr( "Do not install a boot loader" ), QString(), false ) ); } + // Create "don't install bootloader" item. This is always available, + // also if there was no /boot or / partition found. + appendRow( createBootLoaderItem( tr( "Do not install a boot loader" ), QString(), false ) ); } diff --git a/src/modules/partition/core/DeviceList.cpp b/src/modules/partition/core/DeviceList.cpp index b3a10dde7..321827876 100644 --- a/src/modules/partition/core/DeviceList.cpp +++ b/src/modules/partition/core/DeviceList.cpp @@ -127,11 +127,7 @@ getDevices( DeviceType which ) cWarning() << "No KPM backend found."; return {}; } -#if defined( WITH_KPMCORE4API ) DeviceList devices = backend->scanDevices( /* not includeReadOnly, not includeLoopback */ ScanFlag( 0 ) ); -#else - DeviceList devices = backend->scanDevices( /* excludeReadOnly */ true ); -#endif /* The list of devices is cleaned up for use: * - some devices can **never** be used (e.g. floppies, nullptr) diff --git a/src/modules/partition/core/KPMHelpers.cpp b/src/modules/partition/core/KPMHelpers.cpp index 6cc188e67..d53b441d9 100644 --- a/src/modules/partition/core/KPMHelpers.cpp +++ b/src/modules/partition/core/KPMHelpers.cpp @@ -133,44 +133,6 @@ clonePartition( Device* device, Partition* partition ) partition->activeFlags() ); } -#ifndef WITH_KPMCORE4API -// This function was added in KPMCore 4, implementation copied from src/fs/luks.cpp -/* - SPDX-FileCopyrightText: 2010 Volker Lanz - SPDX-FileCopyrightText: 2012-2019 Andrius Štikonas - SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac - SPDX-FileCopyrightText: 2016 Chantara Tith - SPDX-FileCopyrightText: 2017 Christian Morlok - SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho - SPDX-FileCopyrightText: 2020 Arnaud Ferraris - SPDX-FileCopyrightText: 2020 Gaël PORTAY - - SPDX-License-Identifier: GPL-3.0-or-later -*/ -static bool -testPassphrase( FS::luks* fs, const QString& deviceNode, const QString& passphrase ) -{ - ExternalCommand cmd( QStringLiteral( "cryptsetup" ), - { QStringLiteral( "open" ), - QStringLiteral( "--tries" ), - QStringLiteral( "1" ), - QStringLiteral( "--test-passphrase" ), - deviceNode } ); - if ( cmd.write( passphrase.toLocal8Bit() + '\n' ) && cmd.start( -1 ) && cmd.exitCode() == 0 ) - { - return true; - } - - return false; -} -#else -static bool -testPassphrase( FS::luks* fs, const QString& deviceNode, const QString& passphrase ) -{ - return fs->testPassphrase( deviceNode, passphrase ); -} -#endif - // Adapted from src/fs/luks.cpp cryptOpen which always opens a dialog to ask for a passphrase SavePassphraseValue savePassphrase( Partition* partition, const QString& passphrase ) @@ -190,7 +152,7 @@ savePassphrase( Partition* partition, const QString& passphrase ) const QString deviceNode = partition->partitionPath(); // Test the given passphrase - if ( !testPassphrase( luksFs, deviceNode, passphrase ) ) + if ( !luksFs->testPassphrase( deviceNode, passphrase ) ) { return SavePassphraseValue::IncorrectPassphrase; } @@ -247,7 +209,7 @@ execute( Operation& operation, const QString& failureMessage ) // Remove the === lines from the report by trimming them to empty QStringList l = report.toText().split( '\n' ); - std::for_each( l.begin(), l.end(), []( QString& s ) { CalamaresUtils::removeLeading( s, '=' ); } ); + std::for_each( l.begin(), l.end(), []( QString& s ) { Calamares::String::removeLeading( s, '=' ); } ); return Calamares::JobResult::error( failureMessage, l.join( '\n' ) ); } diff --git a/src/modules/partition/core/KPMHelpers.h b/src/modules/partition/core/KPMHelpers.h index e059c934a..4933caa32 100644 --- a/src/modules/partition/core/KPMHelpers.h +++ b/src/modules/partition/core/KPMHelpers.h @@ -27,15 +27,10 @@ class Partition; class PartitionNode; class PartitionRole; -#if defined( WITH_KPMCORE4API ) +// TODO:3.3: Remove defines, expand in-place #define KPM_PARTITION_FLAG( x ) PartitionTable::Flag::x #define KPM_PARTITION_STATE( x ) Partition::State::x #define KPM_PARTITION_FLAG_ESP PartitionTable::Flag::Boot -#else -#define KPM_PARTITION_FLAG( x ) PartitionTable::Flag##x -#define KPM_PARTITION_STATE( x ) Partition::State##x -#define KPM_PARTITION_FLAG_ESP PartitionTable::FlagEsp -#endif /** * Helper functions to manipulate partitions diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index cb7c8a01d..3d5e1e762 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -457,9 +457,7 @@ isEfiFilesystemSuitableType( const Partition* candidate ) { case FileSystem::Type::Fat32: return true; -#ifdef WITH_KPMCORE4API case FileSystem::Type::Fat12: -#endif case FileSystem::Type::Fat16: cWarning() << "FAT12 and FAT16 are probably not supported by EFI"; return false; @@ -479,7 +477,7 @@ isEfiFilesystemSuitableSize( const Partition* candidate ) return false; } - if ( size_t( size ) >= efiFilesystemMinimumSize() ) + if ( size >= efiFilesystemMinimumSize() ) { return true; } @@ -496,40 +494,18 @@ isEfiBootable( const Partition* candidate ) { const auto flags = PartitionInfo::flags( candidate ); -#if defined( WITH_KPMCORE4API ) // In KPMCore4, the flags are remapped, and the ESP flag is the same as Boot. static_assert( KPM_PARTITION_FLAG_ESP == KPM_PARTITION_FLAG( Boot ), "KPMCore API enum changed" ); return flags.testFlag( KPM_PARTITION_FLAG_ESP ); -#else - // In KPMCore3, bit 17 is the old-style Esp flag, and it's OK - if ( flags.testFlag( KPM_PARTITION_FLAG_ESP ) ) - { - return true; - } - - /* Otherwise, if it's a GPT table, Boot (bit 0) is the same as Esp */ - const PartitionTable* table = CalamaresUtils::Partition::getPartitionTable( candidate ); - if ( !table ) - { - cWarning() << "Root of partition table is not a PartitionTable object"; - return false; - } - if ( table->type() == PartitionTable::TableType::gpt ) - { - const auto bootFlag = KPM_PARTITION_FLAG( Boot ); - return flags.testFlag( bootFlag ); - } - return false; -#endif } // TODO: this is configurable via the config file **already** -size_t +qint64 efiFilesystemMinimumSize() { using CalamaresUtils::Units::operator""_MiB; - size_t uefisys_part_sizeB = 300_MiB; + qint64 uefisys_part_sizeB = 300_MiB; // The default can be overridden; the key used here comes // from the partition module Config.cpp @@ -537,7 +513,7 @@ efiFilesystemMinimumSize() if ( gs->contains( "efiSystemPartitionSize_i" ) ) { qint64 v = gs->value( "efiSystemPartitionSize_i" ).toLongLong(); - uefisys_part_sizeB = v > 0 ? static_cast< size_t >( v ) : 0; + uefisys_part_sizeB = v > 0 ? v : 0; } // There is a lower limit of what can be configured if ( uefisys_part_sizeB < 32_MiB ) diff --git a/src/modules/partition/core/PartUtils.h b/src/modules/partition/core/PartUtils.h index 31b4cde84..f3c51df45 100644 --- a/src/modules/partition/core/PartUtils.h +++ b/src/modules/partition/core/PartUtils.h @@ -107,7 +107,7 @@ bool isEfiFilesystemSuitableSize( const Partition* candidate ); * * A minimum of 32MiB (which is bonkers-small) is enforced. */ -size_t efiFilesystemMinimumSize(); +qint64 efiFilesystemMinimumSize(); /** * @brief Is the given @p partition bootable in EFI? Depending on diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp index 0ce9ff4ed..0ceff4324 100644 --- a/src/modules/partition/core/PartitionActions.cpp +++ b/src/modules/partition/core/PartitionActions.cpp @@ -30,11 +30,8 @@ using namespace CalamaresUtils::Units; -namespace PartitionActions -{ - -qint64 -swapSuggestion( const qint64 availableSpaceB, Config::SwapChoice swap ) +static quint64 +swapSuggestion( const quint64 availableSpaceB, Config::SwapChoice swap ) { if ( ( swap != Config::SwapChoice::SmallSwap ) && ( swap != Config::SwapChoice::FullSwap ) ) { @@ -42,10 +39,8 @@ swapSuggestion( const qint64 availableSpaceB, Config::SwapChoice swap ) } // See partition.conf for explanation - qint64 suggestedSwapSizeB = 0; - auto memory = CalamaresUtils::System::instance()->getTotalMemoryB(); - qint64 availableRamB = memory.first; - qreal overestimationFactor = memory.second; + quint64 suggestedSwapSizeB = 0; + auto [ availableRamB, overestimationFactor ] = CalamaresUtils::System::instance()->getTotalMemoryB(); bool ensureSuspendToDisk = swap == Config::SwapChoice::FullSwap; @@ -66,12 +61,13 @@ swapSuggestion( const qint64 availableSpaceB, Config::SwapChoice swap ) // .. top out at 8GiB if we don't care about suspend if ( !ensureSuspendToDisk ) { - suggestedSwapSizeB = qMin( 8_GiB, suggestedSwapSizeB ); + // TODO: make the _GiB operator return unsigned + suggestedSwapSizeB = qMin( quint64( 8_GiB ), suggestedSwapSizeB ); } // Allow for a fudge factor - suggestedSwapSizeB = qRound64( suggestedSwapSizeB * overestimationFactor ); + suggestedSwapSizeB = quint64( qRound64( qreal( suggestedSwapSizeB ) * overestimationFactor ) ); // don't use more than 10% of available space if ( !ensureSuspendToDisk ) @@ -79,11 +75,15 @@ swapSuggestion( const qint64 availableSpaceB, Config::SwapChoice swap ) suggestedSwapSizeB = qMin( suggestedSwapSizeB, availableSpaceB / 10 /* 10% is 0.1 */ ); } + // TODO: make Units functions work on unsigned cDebug() << "Suggested swap size:" << CalamaresUtils::BytesToGiB( suggestedSwapSizeB ) << "GiB"; return suggestedSwapSizeB; } +namespace PartitionActions +{ + void doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionOptions o ) { @@ -118,7 +118,7 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO if ( isEfi ) { - size_t uefisys_part_sizeB = PartUtils::efiFilesystemMinimumSize(); + qint64 uefisys_part_sizeB = PartUtils::efiFilesystemMinimumSize(); qint64 efiSectorCount = CalamaresUtils::bytesToSectors( uefisys_part_sizeB, dev->logicalSize() ); Q_ASSERT( efiSectorCount > 0 ); @@ -147,16 +147,17 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO const bool mayCreateSwap = ( o.swap == Config::SwapChoice::SmallSwap ) || ( o.swap == Config::SwapChoice::FullSwap ); bool shouldCreateSwap = false; - qint64 suggestedSwapSizeB = 0; + quint64 suggestedSwapSizeB = 0; + const quint64 sectorSize = quint64( dev->logicalSize() ); if ( mayCreateSwap ) { - qint64 availableSpaceB = ( dev->totalLogical() - firstFreeSector ) * dev->logicalSize(); + quint64 availableSpaceB = quint64( dev->totalLogical() - firstFreeSector ) * sectorSize; suggestedSwapSizeB = swapSuggestion( availableSpaceB, o.swap ); // Space required by this installation is what the distro claims is needed // (via global configuration) plus the swap size plus a fudge factor of // 0.6GiB (this was 2.1GiB up to Calamares 3.2.2). - qint64 requiredSpaceB = o.requiredSpaceB + 600_MiB + suggestedSwapSizeB; + quint64 requiredSpaceB = o.requiredSpaceB + 600_MiB + suggestedSwapSizeB; // If there is enough room for ESP + root + swap, create swap, otherwise don't. shouldCreateSwap = availableSpaceB > requiredSpaceB; @@ -165,7 +166,7 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO qint64 lastSectorForRoot = dev->totalLogical() - 1; //last sector of the device if ( shouldCreateSwap ) { - lastSectorForRoot -= suggestedSwapSizeB / dev->logicalSize() + 1; + lastSectorForRoot -= suggestedSwapSizeB / sectorSize + 1; } core->layoutApply( dev, firstFreeSector, lastSectorForRoot, o.luksPassphrase ); diff --git a/src/modules/partition/core/PartitionActions.h b/src/modules/partition/core/PartitionActions.h index efe8b2456..d6b86a6cd 100644 --- a/src/modules/partition/core/PartitionActions.h +++ b/src/modules/partition/core/PartitionActions.h @@ -44,7 +44,7 @@ struct ReplacePartitionOptions struct AutoPartitionOptions : ReplacePartitionOptions { QString efiPartitionMountPoint; // optional, e.g. "/boot" - qint64 requiredSpaceB; // estimated required space for root partition + quint64 requiredSpaceB; // estimated required space for root partition Config::SwapChoice swap; AutoPartitionOptions( const QString& pt, @@ -55,7 +55,7 @@ struct AutoPartitionOptions : ReplacePartitionOptions Config::SwapChoice s ) : ReplacePartitionOptions( pt, fs, luks ) , efiPartitionMountPoint( efi ) - , requiredSpaceB( requiredBytes > 0 ? requiredBytes : 0 ) + , requiredSpaceB( requiredBytes > 0 ? quint64( requiredBytes ) : 0U ) , swap( s ) { } diff --git a/src/modules/partition/core/PartitionCoreModule.cpp b/src/modules/partition/core/PartitionCoreModule.cpp index f7d1e8278..78af2abf7 100644 --- a/src/modules/partition/core/PartitionCoreModule.cpp +++ b/src/modules/partition/core/PartitionCoreModule.cpp @@ -553,6 +553,11 @@ PartitionCoreModule::formatPartition( Device* device, Partition* partition ) void PartitionCoreModule::setFilesystemLabel( Device* device, Partition* partition, const QString& newLabel ) { + if ( newLabel.isEmpty() ) + { + // Don't bother + return; + } auto deviceInfo = infoForDevice( device ); Q_ASSERT( deviceInfo ); @@ -842,13 +847,8 @@ PartitionCoreModule::scanForLVMPVs() } } -#if defined( WITH_KPMCORE4API ) VolumeManagerDevice::scanDevices( physicalDevices ); for ( auto p : LVM::pvList::list() ) -#else - LvmDevice::scanSystemLVM( physicalDevices ); - for ( auto p : LVM::pvList ) -#endif { m_lvmPVs << p.partition().data(); @@ -885,7 +885,6 @@ PartitionCoreModule::scanForLVMPVs() m_lvmPVs << p; } } -#if defined( WITH_KPMCORE4API ) else if ( p->fileSystem().type() == FileSystem::Type::Luks2 ) { // Encrypted LVM PVs @@ -896,7 +895,6 @@ PartitionCoreModule::scanForLVMPVs() m_lvmPVs << p; } } -#endif } } } diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index 765d9fffa..a8aae61ff 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -154,11 +154,9 @@ PartitionLayout::setDefaultFsType( FileSystem::Type defaultFsType ) case FileSystem::Lvm2_PV: case FileSystem::Udf: case FileSystem::Iso9660: -#ifdef WITH_KPMCORE4API case FileSystem::Luks2: case FileSystem::LinuxRaidMember: case FileSystem::BitLocker: -#endif // bad bad cWarning() << "The selected default FS" << defaultFsType << "is not suitable." << "Using ext4 instead."; @@ -185,11 +183,9 @@ PartitionLayout::setDefaultFsType( FileSystem::Type defaultFsType ) case FileSystem::Hpfs: case FileSystem::Zfs: case FileSystem::Nilfs2: -#ifdef WITH_KPMCORE4API case FileSystem::Fat12: case FileSystem::Apfs: case FileSystem::Minix: -#endif // weird cWarning() << "The selected default FS" << defaultFsType << "is unusual, but not wrong."; break; @@ -355,30 +351,18 @@ PartitionLayout::createPartitions( Device* dev, } if ( !entry.partType.isEmpty() ) { -#if defined( WITH_KPMCORE42API ) part->setType( entry.partType ); -#else - cWarning() << "Ignoring type; requires KPMcore >= 4.2.0."; -#endif } if ( entry.partAttributes ) { -#if defined( WITH_KPMCORE42API ) part->setAttributes( entry.partAttributes ); -#else - cWarning() << "Ignoring attributes; requires KPMcore >= 4.2.0."; -#endif } if ( !entry.partFeatures.isEmpty() ) { -#if defined( WITH_KPMCORE42API ) for ( const auto& k : entry.partFeatures.keys() ) { part->fileSystem().addFeature( k, entry.partFeatures.value( k ) ); } -#else - cWarning() << "Ignoring features; requires KPMcore >= 4.2.0."; -#endif } // Some buggy (legacy) BIOSes test if the bootflag of at least one partition is set. // Otherwise they ignore the device in boot-order, so add it here. diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index 882be1022..2730e069f 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -3,6 +3,7 @@ * SPDX-FileCopyrightText: 2014-2017 Teo Mrnjavac * SPDX-FileCopyrightText: 2017-2019 Adriaan de Groot * SPDX-FileCopyrightText: 2019 Collabora Ltd + * SPDX-FileCopyrightText: 2021 Anubhav Choudhary * SPDX-License-Identifier: GPL-3.0-or-later * * Calamares is Free Software: see the License-Identifier above. @@ -42,9 +43,7 @@ #include "widgets/PrettyRadioButton.h" #include -#ifdef WITH_KPMCORE4API #include -#endif #include #include @@ -55,7 +54,7 @@ #include #include -using Calamares::PrettyRadioButton; +using Calamares::Widgets::PrettyRadioButton; using CalamaresUtils::Partition::findPartitionByPath; using CalamaresUtils::Partition::isPartitionFreeSpace; using CalamaresUtils::Partition::PartitionIterator; @@ -1038,6 +1037,12 @@ ChoicePage::updateActionChoicePreview( InstallChoice choice ) QLabel* sizeLabel = new QLabel( m_previewAfterFrame ); layout->addWidget( sizeLabel ); sizeLabel->setWordWrap( true ); + + if ( !m_isEfi ) + { + layout->addWidget( createBootloaderPanel() ); + } + connect( m_afterPartitionSplitterWidget, &PartitionSplitterWidget::partitionResized, this, @@ -1096,51 +1101,7 @@ ChoicePage::updateActionChoicePreview( InstallChoice choice ) if ( !m_isEfi ) { - QWidget* eraseWidget = new QWidget; - - QHBoxLayout* eraseLayout = new QHBoxLayout; - eraseWidget->setLayout( eraseLayout ); - eraseLayout->setContentsMargins( 0, 0, 0, 0 ); - QLabel* eraseBootloaderLabel = new QLabel( eraseWidget ); - eraseLayout->addWidget( eraseBootloaderLabel ); - eraseBootloaderLabel->setText( tr( "Boot loader location:" ) ); - - m_bootloaderComboBox = createBootloaderComboBox( eraseWidget ); - connect( m_core->bootLoaderModel(), - &QAbstractItemModel::modelReset, - [ this ]() - { - if ( !m_bootloaderComboBox.isNull() ) - { - Calamares::restoreSelectedBootLoader( *m_bootloaderComboBox, - m_core->bootLoaderInstallPath() ); - } - } ); - connect( - m_core, - &PartitionCoreModule::deviceReverted, - this, - [ this ]( Device* dev ) - { - Q_UNUSED( dev ) - if ( !m_bootloaderComboBox.isNull() ) - { - if ( m_bootloaderComboBox->model() != m_core->bootLoaderModel() ) - { - m_bootloaderComboBox->setModel( m_core->bootLoaderModel() ); - } - - m_bootloaderComboBox->setCurrentIndex( m_lastSelectedDeviceIndex ); - } - }, - Qt::QueuedConnection ); - // ^ Must be Queued so it's sure to run when the widget is already visible. - - eraseLayout->addWidget( m_bootloaderComboBox ); - eraseBootloaderLabel->setBuddy( m_bootloaderComboBox ); - eraseLayout->addStretch(); - - layout->addWidget( eraseWidget ); + layout->addWidget( createBootloaderPanel() ); } m_previewAfterFrame->show(); @@ -1254,35 +1215,6 @@ ChoicePage::setupEfiSystemPartitionSelector() } } - -QComboBox* -ChoicePage::createBootloaderComboBox( QWidget* parent ) -{ - QComboBox* comboForBootloader = new QComboBox( parent ); - comboForBootloader->setModel( m_core->bootLoaderModel() ); - - // When the chosen bootloader device changes, we update the choice in the PCM - connect( comboForBootloader, - QOverload< int >::of( &QComboBox::currentIndexChanged ), - this, - [ this ]( int newIndex ) - { - QComboBox* bootloaderCombo = qobject_cast< QComboBox* >( sender() ); - if ( bootloaderCombo ) - { - QVariant var = bootloaderCombo->itemData( newIndex, BootLoaderModel::BootLoaderPathRole ); - if ( !var.isValid() ) - { - return; - } - m_core->setBootLoaderInstallPath( var.toString() ); - } - } ); - - return comboForBootloader; -} - - static inline void force_uncheck( QButtonGroup* grp, PrettyRadioButton* button ) { @@ -1361,14 +1293,12 @@ ChoicePage::setupActions() bool isInactiveRAID = false; bool matchTableType = false; -#ifdef WITH_KPMCORE4API if ( currentDevice->type() == Device::Type::SoftwareRAID_Device && static_cast< SoftwareRAID* >( currentDevice )->status() == SoftwareRAID::Status::Inactive ) { cDebug() << Logger::SubEntry << "part of an inactive RAID device"; isInactiveRAID = true; } -#endif PartitionTable::TableType tableType = PartitionTable::unknownTableType; if ( currentDevice->partitionTable() ) @@ -1746,3 +1676,72 @@ ChoicePage::setLastSelectedDeviceIndex( int index ) m_lastSelectedDeviceIndex = index; m_drivesCombo->setCurrentIndex( m_lastSelectedDeviceIndex ); } + +QWidget* +ChoicePage::createBootloaderPanel() +{ + QWidget* panelWidget = new QWidget; + + QHBoxLayout* mainLayout = new QHBoxLayout; + panelWidget->setLayout( mainLayout ); + mainLayout->setContentsMargins( 0, 0, 0, 0 ); + QLabel* widgetLabel = new QLabel( panelWidget ); + mainLayout->addWidget( widgetLabel ); + widgetLabel->setText( tr( "Boot loader location:" ) ); + + QComboBox* comboForBootloader = new QComboBox( panelWidget ); + comboForBootloader->setModel( m_core->bootLoaderModel() ); + + // When the chosen bootloader device changes, we update the choice in the PCM + connect( comboForBootloader, + QOverload< int >::of( &QComboBox::currentIndexChanged ), + this, + [ this ]( int newIndex ) + { + QComboBox* bootloaderCombo = qobject_cast< QComboBox* >( sender() ); + if ( bootloaderCombo ) + { + QVariant var = bootloaderCombo->itemData( newIndex, BootLoaderModel::BootLoaderPathRole ); + if ( !var.isValid() ) + { + return; + } + m_core->setBootLoaderInstallPath( var.toString() ); + } + } ); + m_bootloaderComboBox = comboForBootloader; + + connect( m_core->bootLoaderModel(), + &QAbstractItemModel::modelReset, + [ this ]() + { + if ( !m_bootloaderComboBox.isNull() ) + { + Calamares::restoreSelectedBootLoader( *m_bootloaderComboBox, m_core->bootLoaderInstallPath() ); + } + } ); + connect( + m_core, + &PartitionCoreModule::deviceReverted, + this, + [ this ]( Device* ) + { + if ( !m_bootloaderComboBox.isNull() ) + { + if ( m_bootloaderComboBox->model() != m_core->bootLoaderModel() ) + { + m_bootloaderComboBox->setModel( m_core->bootLoaderModel() ); + } + + m_bootloaderComboBox->setCurrentIndex( m_lastSelectedDeviceIndex ); + } + }, + Qt::QueuedConnection ); + // ^ Must be Queued so it's sure to run when the widget is already visible. + + mainLayout->addWidget( m_bootloaderComboBox ); + widgetLabel->setBuddy( m_bootloaderComboBox ); + mainLayout->addStretch(); + + return panelWidget; +} diff --git a/src/modules/partition/gui/ChoicePage.h b/src/modules/partition/gui/ChoicePage.h index 12222ac63..ea346f5ad 100644 --- a/src/modules/partition/gui/ChoicePage.h +++ b/src/modules/partition/gui/ChoicePage.h @@ -30,8 +30,11 @@ class QListView; namespace Calamares { +namespace Widgets +{ class PrettyRadioButton; } +} // namespace Calamares class Config; class DeviceInfoWidget; @@ -108,7 +111,12 @@ private: void updateNextEnabled(); void setupChoices(); void checkInstallChoiceRadioButton( Config::InstallChoice choice ); ///< Sets the chosen button to "on" - QComboBox* createBootloaderComboBox( QWidget* parentButton ); + /** @brief Create a panel with "boot loader location:" + * + * Panel + dropdown and handling for model updates. Returns a pointer + * to the panel's widget. + */ + QWidget* createBootloaderPanel(); Device* selectedDevice(); /* Change the UI depending on the device selected. */ @@ -137,10 +145,10 @@ private: QComboBox* m_drivesCombo; QButtonGroup* m_grp; - Calamares::PrettyRadioButton* m_alongsideButton; - Calamares::PrettyRadioButton* m_eraseButton; - Calamares::PrettyRadioButton* m_replaceButton; - Calamares::PrettyRadioButton* m_somethingElseButton; + Calamares::Widgets::PrettyRadioButton* m_alongsideButton; + Calamares::Widgets::PrettyRadioButton* m_eraseButton; + Calamares::Widgets::PrettyRadioButton* m_replaceButton; + Calamares::Widgets::PrettyRadioButton* m_somethingElseButton; QComboBox* m_eraseSwapChoiceComboBox = nullptr; // UI, see also Config's swap choice QComboBox* m_eraseFsTypesChoiceComboBox = nullptr; // UI, see also Config's erase-mode FS diff --git a/src/modules/partition/gui/DeviceInfoWidget.cpp b/src/modules/partition/gui/DeviceInfoWidget.cpp index 39d9413e1..05a8c4b63 100644 --- a/src/modules/partition/gui/DeviceInfoWidget.cpp +++ b/src/modules/partition/gui/DeviceInfoWidget.cpp @@ -100,9 +100,7 @@ DeviceInfoWidget::retranslateUi() "that makes a file accessible as a block device. " "This kind of setup usually only contains a single filesystem." ); break; -#if defined( WITH_KPMCORE42API ) case PartitionTable::none: -#endif case PartitionTable::unknownTableType: typeString = " ? "; toolTipString = tr( "This installer cannot detect a partition table on the " diff --git a/src/modules/partition/gui/PartitionLabelsView.cpp b/src/modules/partition/gui/PartitionLabelsView.cpp index e3a50c576..66b1ba62a 100644 --- a/src/modules/partition/gui/PartitionLabelsView.cpp +++ b/src/modules/partition/gui/PartitionLabelsView.cpp @@ -29,7 +29,7 @@ using namespace CalamaresUtils::Units; static const int LAYOUT_MARGIN = 4; -static const int LABEL_PARTITION_SQUARE_MARGIN = qMax( QFontMetrics( CalamaresUtils::defaultFont() ).ascent() - 2, 18 ); +static const int LABEL_PARTITION_SQUARE_MARGIN = qMax( CalamaresUtils::defaultFontHeight() - 2, 18 ); static const int LABELS_MARGIN = LABEL_PARTITION_SQUARE_MARGIN; static const int CORNER_RADIUS = 2; diff --git a/src/modules/partition/gui/PartitionPage.cpp b/src/modules/partition/gui/PartitionPage.cpp index 0b3cf2478..25e6a27ab 100644 --- a/src/modules/partition/gui/PartitionPage.cpp +++ b/src/modules/partition/gui/PartitionPage.cpp @@ -42,9 +42,7 @@ // KPMcore #include #include -#ifdef WITH_KPMCORE4API #include -#endif #include #include @@ -179,14 +177,12 @@ PartitionPage::updateButtons() { allow_create_table = true; -#ifdef WITH_KPMCORE4API if ( device->type() == Device::Type::SoftwareRAID_Device && static_cast< SoftwareRAID* >( device )->status() == SoftwareRAID::Status::Inactive ) { allow_create_table = false; allow_create = false; } -#endif } else { diff --git a/src/modules/partition/gui/PartitionSplitterWidget.cpp b/src/modules/partition/gui/PartitionSplitterWidget.cpp index e52afaa74..139eef168 100644 --- a/src/modules/partition/gui/PartitionSplitterWidget.cpp +++ b/src/modules/partition/gui/PartitionSplitterWidget.cpp @@ -35,6 +35,48 @@ static const int VIEW_HEIGHT static const int CORNER_RADIUS = 3; static const int EXTENDED_PARTITION_MARGIN = qMax( 4, VIEW_HEIGHT / 6 ); +/** @brief Applies @p operation to each item + * + * A PartitionSplitterItem can contain a tree of items (each item has its + * own list of children) so recurse over all the children. Returns a count + * of how many items were affected. + */ +static int +countTransform( QVector< PartitionSplitterItem >& items, + const std::function< bool( PartitionSplitterItem& ) >& operation ) +{ + int opCount = 0; + for ( auto it = items.begin(); it != items.end(); ++it ) + { + if ( operation( *it ) ) + { + opCount++; + } + + opCount += countTransform( it->children, operation ); + } + return opCount; +} + +static PartitionSplitterItem +findTransform( QVector< PartitionSplitterItem >& items, std::function< bool( PartitionSplitterItem& ) > condition ) +{ + for ( auto it = items.begin(); it != items.end(); ++it ) + { + if ( condition( *it ) ) + { + return *it; + } + + PartitionSplitterItem candidate = findTransform( it->children, condition ); + if ( !candidate.isNull() ) + { + return candidate; + } + } + return PartitionSplitterItem::null(); +} + PartitionSplitterWidget::PartitionSplitterWidget( QWidget* parent ) : QWidget( parent ) , m_itemToResize( PartitionSplitterItem::null() ) @@ -159,16 +201,16 @@ PartitionSplitterWidget::setSplitPartition( const QString& path, qint64 minSize, m_itemToResizePath.clear(); } - PartitionSplitterItem itemToResize = _findItem( m_items, - [ path ]( PartitionSplitterItem& item ) -> bool - { - if ( path == item.itemPath ) + PartitionSplitterItem itemToResize = findTransform( m_items, + [ path ]( PartitionSplitterItem& item ) -> bool { - item.status = PartitionSplitterItem::Resizing; - return true; - } - return false; - } ); + if ( path == item.itemPath ) + { + item.status = PartitionSplitterItem::Resizing; + return true; + } + return false; + } ); if ( itemToResize.isNull() ) { @@ -186,16 +228,16 @@ PartitionSplitterWidget::setSplitPartition( const QString& path, qint64 minSize, qint64 newSize = m_itemToResize.size - preferredSize; m_itemToResize.size = preferredSize; - int opCount = _eachItem( m_items, - [ preferredSize ]( PartitionSplitterItem& item ) -> bool - { - if ( item.status == PartitionSplitterItem::Resizing ) - { - item.size = preferredSize; - return true; - } - return false; - } ); + int opCount = countTransform( m_items, + [ preferredSize ]( PartitionSplitterItem& item ) -> bool + { + if ( item.status == PartitionSplitterItem::Resizing ) + { + item.size = preferredSize; + return true; + } + return false; + } ); cDebug() << "each splitter item opcount:" << opCount; m_itemMinSize = minSize; m_itemMaxSize = maxSize; @@ -362,21 +404,21 @@ PartitionSplitterWidget::mouseMoveEvent( QMouseEvent* event ) m_itemToResize.size = qRound64( span * percent ); m_itemToResizeNext.size -= m_itemToResize.size - oldsize; - _eachItem( m_items, - [ this ]( PartitionSplitterItem& item ) -> bool - { - if ( item.status == PartitionSplitterItem::Resizing ) - { - item.size = m_itemToResize.size; - return true; - } - else if ( item.status == PartitionSplitterItem::ResizingNext ) - { - item.size = m_itemToResizeNext.size; - return true; - } - return false; - } ); + countTransform( m_items, + [ this ]( PartitionSplitterItem& item ) -> bool + { + if ( item.status == PartitionSplitterItem::Resizing ) + { + item.size = m_itemToResize.size; + return true; + } + else if ( item.status == PartitionSplitterItem::ResizingNext ) + { + item.size = m_itemToResizeNext.size; + return true; + } + return false; + } ); repaint(); @@ -553,46 +595,6 @@ PartitionSplitterWidget::drawPartitions( QPainter* painter, } } - -PartitionSplitterItem -PartitionSplitterWidget::_findItem( QVector< PartitionSplitterItem >& items, - std::function< bool( PartitionSplitterItem& ) > condition ) const -{ - for ( auto it = items.begin(); it != items.end(); ++it ) - { - if ( condition( *it ) ) - { - return *it; - } - - PartitionSplitterItem candidate = _findItem( it->children, condition ); - if ( !candidate.isNull() ) - { - return candidate; - } - } - return PartitionSplitterItem::null(); -} - - -int -PartitionSplitterWidget::_eachItem( QVector< PartitionSplitterItem >& items, - std::function< bool( PartitionSplitterItem& ) > operation ) const -{ - int opCount = 0; - for ( auto it = items.begin(); it != items.end(); ++it ) - { - if ( operation( *it ) ) - { - opCount++; - } - - opCount += _eachItem( it->children, operation ); - } - return opCount; -} - - QPair< QVector< PartitionSplitterItem >, qreal > PartitionSplitterWidget::computeItemsVector( const QVector< PartitionSplitterItem >& originalItems ) const { diff --git a/src/modules/partition/gui/PartitionSplitterWidget.h b/src/modules/partition/gui/PartitionSplitterWidget.h index 474ea313e..53f5b0b37 100644 --- a/src/modules/partition/gui/PartitionSplitterWidget.h +++ b/src/modules/partition/gui/PartitionSplitterWidget.h @@ -72,12 +72,6 @@ private: void drawSection( QPainter* painter, const QRect& rect_, int x, int width, const PartitionSplitterItem& item ); void drawResizeHandle( QPainter* painter, const QRect& rect_, int x ); - PartitionSplitterItem _findItem( QVector< PartitionSplitterItem >& items, - std::function< bool( PartitionSplitterItem& ) > condition ) const; - - int _eachItem( QVector< PartitionSplitterItem >& items, - std::function< bool( PartitionSplitterItem& ) > operation ) const; - QPair< QVector< PartitionSplitterItem >, qreal > computeItemsVector( const QVector< PartitionSplitterItem >& originalItems ) const; diff --git a/src/modules/partition/gui/ScanningDialog.cpp b/src/modules/partition/gui/ScanningDialog.cpp index 56133e21f..7dd85ff86 100644 --- a/src/modules/partition/gui/ScanningDialog.cpp +++ b/src/modules/partition/gui/ScanningDialog.cpp @@ -10,7 +10,7 @@ #include "ScanningDialog.h" -#include "3rdparty/waitingspinnerwidget.h" +#include "widgets/waitingspinnerwidget.h" #include #include diff --git a/src/modules/partition/jobs/CreatePartitionJob.cpp b/src/modules/partition/jobs/CreatePartitionJob.cpp index fe7c6f350..19a04a2de 100644 --- a/src/modules/partition/jobs/CreatePartitionJob.cpp +++ b/src/modules/partition/jobs/CreatePartitionJob.cpp @@ -111,7 +111,6 @@ CreatePartitionJob::CreatePartitionJob( Device* device, Partition* partition ) static QString prettyGptType( const Partition* partition ) { -#ifdef WITH_KPMCORE42API static const QMap< QString, QString > gptTypePrettyStrings = { { "44479540-f297-41b2-9af7-d131d5f0458a", "Linux Root Partition (x86)" }, { "4f68bce3-e8cd-4db1-96e7-fbcaf984b709", "Linux Root Partition (x86-64)" }, @@ -146,9 +145,6 @@ prettyGptType( const Partition* partition ) auto type = partition->type(); return gptTypePrettyStrings.value( type.toLower(), type ); -#else - return QString(); -#endif } static QString diff --git a/src/modules/partition/jobs/FillGlobalStorageJob.cpp b/src/modules/partition/jobs/FillGlobalStorageJob.cpp index 5be353113..d734485f0 100644 --- a/src/modules/partition/jobs/FillGlobalStorageJob.cpp +++ b/src/modules/partition/jobs/FillGlobalStorageJob.cpp @@ -88,11 +88,9 @@ mapForPartition( Partition* partition, const QString& uuid ) map[ "mountPoint" ] = PartitionInfo::mountPoint( partition ); map[ "fsName" ] = userVisibleFS( partition->fileSystem() ); map[ "fs" ] = untranslatedFS( partition->fileSystem() ); -#ifdef WITH_KPMCORE42API map[ "parttype" ] = partition->type(); map[ "partattrs" ] = partition->attributes(); map[ "features" ] = partition->fileSystem().features(); -#endif if ( partition->fileSystem().type() == FileSystem::Luks && dynamic_cast< FS::luks& >( partition->fileSystem() ).innerFS() ) { diff --git a/src/modules/partition/tests/CMakeLists.txt b/src/modules/partition/tests/CMakeLists.txt index da017d96f..26a1d83f9 100644 --- a/src/modules/partition/tests/CMakeLists.txt +++ b/src/modules/partition/tests/CMakeLists.txt @@ -3,9 +3,9 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -find_package( Qt5 COMPONENTS Gui REQUIRED ) +find_package(Qt5 COMPONENTS Gui REQUIRED) -set( PartitionModule_SOURCE_DIR .. ) +set(PartitionModule_SOURCE_DIR ..) include_directories( ${Qt5Gui_INCLUDE_DIRS} @@ -25,22 +25,17 @@ calamares_add_test( ${PartitionModule_SOURCE_DIR}/jobs/DeletePartitionJob.cpp ${PartitionModule_SOURCE_DIR}/jobs/PartitionJob.cpp ${PartitionModule_SOURCE_DIR}/jobs/ResizePartitionJob.cpp - LIBRARIES - kpmcore + LIBRARIES kpmcore DEFINITIONS ${_partition_defs} ) calamares_add_test( partitionclearmountsjobtest - SOURCES - ${PartitionModule_SOURCE_DIR}/jobs/ClearMountsJob.cpp - ClearMountsJobTests.cpp - LIBRARIES - kpmcore + SOURCES ${PartitionModule_SOURCE_DIR}/jobs/ClearMountsJob.cpp ClearMountsJobTests.cpp + LIBRARIES kpmcore DEFINITIONS ${_partition_defs} ) - calamares_add_test( partitioncreatelayoutstest SOURCES @@ -50,26 +45,19 @@ calamares_add_test( ${PartitionModule_SOURCE_DIR}/core/PartitionLayout.cpp ${PartitionModule_SOURCE_DIR}/core/PartUtils.cpp ${PartitionModule_SOURCE_DIR}/core/DeviceModel.cpp - LIBRARIES - kpmcore - Calamares::calamaresui + LIBRARIES kpmcore Calamares::calamaresui DEFINITIONS ${_partition_defs} ) calamares_add_test( partitionautomounttest - SOURCES - ${PartitionModule_SOURCE_DIR}/jobs/AutoMountManagementJob.cpp - AutoMountTests.cpp + SOURCES ${PartitionModule_SOURCE_DIR}/jobs/AutoMountManagementJob.cpp AutoMountTests.cpp DEFINITIONS ${_partition_defs} ) calamares_add_test( partitiondevicestest - SOURCES - DevicesTests.cpp - ${PartitionModule_SOURCE_DIR}/core/DeviceList.cpp - LIBRARIES - kpmcore + SOURCES DevicesTests.cpp ${PartitionModule_SOURCE_DIR}/core/DeviceList.cpp + LIBRARIES kpmcore DEFINITIONS ${_partition_defs} ) diff --git a/src/modules/partition/tests/CreateLayoutsTests.cpp b/src/modules/partition/tests/CreateLayoutsTests.cpp index 68b839e08..b83f71a26 100644 --- a/src/modules/partition/tests/CreateLayoutsTests.cpp +++ b/src/modules/partition/tests/CreateLayoutsTests.cpp @@ -125,7 +125,6 @@ CreateLayoutsTests::testMixedSizePartition() QCOMPARE( partitions[ 2 ]->length(), ( ( 5_GiB - 5_MiB ) / 2 ) / LOGICAL_SIZE ); } -#ifdef WITH_KPMCORE4API // TODO: Get a clean way to instantiate a test Device from KPMCore class DevicePrivate { @@ -150,11 +149,5 @@ TestDevice::TestDevice( const QString& name, const qint64 logicalSectorSize, con Device::Type::Unknown_Device ) { } -#else -TestDevice::TestDevice( const QString& name, const qint64 logicalSectorSize, const qint64 totalLogicalSectors ) - : Device( name, QString( "node" ), logicalSectorSize, totalLogicalSectors, QString(), Device::Type::Unknown_Device ) -{ -} -#endif TestDevice::~TestDevice() {} diff --git a/src/modules/partition/tests/DevicesTests.cpp b/src/modules/partition/tests/DevicesTests.cpp index c63d7476d..ec6bdadff 100644 --- a/src/modules/partition/tests/DevicesTests.cpp +++ b/src/modules/partition/tests/DevicesTests.cpp @@ -52,12 +52,7 @@ DevicesTests::testKPMScanDevices() cDebug() << "Getting devices via KPMCore"; CoreBackend* backend = CoreBackendManager::self()->backend(); QVERIFY( backend ); -#if defined( WITH_KPMCORE4API ) - auto flags = ScanFlag( ~0 ); -#else - auto flags = true; -#endif - auto devices = backend->scanDevices( flags ); // These flags try to get "all" + auto devices = backend->scanDevices( ScanFlag( ~0 ) ); // These flags try to get "all" cDebug() << Logger::SubEntry << "Done getting devices."; if ( !m_isRoot ) diff --git a/src/modules/plasmalnf/CMakeLists.txt b/src/modules/plasmalnf/CMakeLists.txt index 8ae205aed..9e87b5fec 100644 --- a/src/modules/plasmalnf/CMakeLists.txt +++ b/src/modules/plasmalnf/CMakeLists.txt @@ -7,28 +7,19 @@ find_package(ECM ${ECM_VERSION} REQUIRED NO_MODULE) # Requires a sufficiently recent Plasma framework, but also # needs a runtime support component (which we don't test for). -set( lnf_ver 5.41 ) +set(lnf_ver 5.41) -find_package( KF5Config ${lnf_ver} ) -set_package_properties( - KF5Config PROPERTIES - PURPOSE "For finding default Plasma Look-and-Feel" -) +find_package(KF5Config ${lnf_ver}) +set_package_properties(KF5Config PROPERTIES PURPOSE "For finding default Plasma Look-and-Feel") -find_package( KF5Plasma ${lnf_ver} ) -set_package_properties( - KF5Plasma PROPERTIES - PURPOSE "For Plasma Look-and-Feel selection" -) +find_package(KF5Plasma ${lnf_ver}) +set_package_properties(KF5Plasma PROPERTIES PURPOSE "For Plasma Look-and-Feel selection") -find_package( KF5Package ${lnf_ver} ) -set_package_properties( - KF5Package PROPERTIES - PURPOSE "For Plasma Look-and-Feel selection" -) +find_package(KF5Package ${lnf_ver}) +set_package_properties(KF5Package PROPERTIES PURPOSE "For Plasma Look-and-Feel selection") -if ( KF5Plasma_FOUND AND KF5Package_FOUND ) - calamares_add_plugin( plasmalnf +if(KF5Plasma_FOUND AND KF5Package_FOUND) + calamares_add_plugin(plasmalnf TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO COMPILE_DEFINITIONS @@ -48,7 +39,7 @@ if ( KF5Plasma_FOUND AND KF5Package_FOUND ) KF5::Plasma SHARED_LIB ) - if ( KF5Config_FOUND ) + if(KF5Config_FOUND) target_compile_definitions(calamares_viewmodule_plasmalnf PRIVATE WITH_KCONFIG) endif() else() diff --git a/src/modules/preservefiles/CMakeLists.txt b/src/modules/preservefiles/CMakeLists.txt index 5df637321..b11b1310c 100644 --- a/src/modules/preservefiles/CMakeLists.txt +++ b/src/modules/preservefiles/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -calamares_add_plugin( preservefiles +calamares_add_plugin(preservefiles TYPE job EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -14,9 +14,4 @@ calamares_add_plugin( preservefiles EMERGENCY ) -calamares_add_test( - preservefilestest - SOURCES - Item.cpp - Tests.cpp -) +calamares_add_test(preservefilestest SOURCES Item.cpp Tests.cpp) diff --git a/src/modules/removeuser/CMakeLists.txt b/src/modules/removeuser/CMakeLists.txt index 7663b3472..eaaf20157 100644 --- a/src/modules/removeuser/CMakeLists.txt +++ b/src/modules/removeuser/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -calamares_add_plugin( removeuser +calamares_add_plugin(removeuser TYPE job EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/shellprocess/CMakeLists.txt b/src/modules/shellprocess/CMakeLists.txt index ac6630c6d..8ac444fb6 100644 --- a/src/modules/shellprocess/CMakeLists.txt +++ b/src/modules/shellprocess/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -calamares_add_plugin( shellprocess +calamares_add_plugin(shellprocess TYPE job EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -11,10 +11,4 @@ calamares_add_plugin( shellprocess SHARED_LIB ) -calamares_add_test( - shellprocesstest - SOURCES - Tests.cpp - LIBRARIES - yamlcpp::yamlcpp -) +calamares_add_test(shellprocesstest SOURCES Tests.cpp LIBRARIES yamlcpp::yamlcpp) diff --git a/src/modules/shellprocess/Tests.cpp b/src/modules/shellprocess/Tests.cpp index c1489c1ab..f8727ab36 100644 --- a/src/modules/shellprocess/Tests.cpp +++ b/src/modules/shellprocess/Tests.cpp @@ -146,14 +146,14 @@ script: QVariant plainScript = CalamaresUtils::yamlMapToVariant( doc ).value( "script" ); QVariant rootScript = CalamaresUtils::yamlMapToVariant( YAML::Load( R"(--- script: - - "ls @@ROOT@@" + - "ls ${ROOT}" )" ) ) .value( "script" ); QVariant userScript = CalamaresUtils::yamlMapToVariant( YAML::Load( R"(--- script: - - mktemp -d @@ROOT@@/calatestXXXXXXXX - - "chown @@USER@@ @@ROOT@@/calatest*" - - rm -rf @@ROOT@@/calatest* + - mktemp -d ${ROOT}/calatestXXXXXXXX + - "chown ${USER} ${ROOT}/calatest*" + - rm -rf ${ROOT}/calatest* )" ) ) .value( "script" ); @@ -167,13 +167,13 @@ script: qDebug() << "Expect WARNING, ERROR, WARNING"; - // Doesn't use @@ROOT@@, so no failures + // Doesn't use ${ROOT}, so no failures QVERIFY( bool( CommandList( plainScript, false, 10s ).run() ) ); - // Doesn't use @@ROOT@@, but does chroot, so fails + // Doesn't use ${ROOT}, but does chroot, so fails QVERIFY( !bool( CommandList( plainScript, true, 10s ).run() ) ); - // Does use @@ROOT@@, which is not set, so fails + // Does use ${ROOT}, which is not set, so fails QVERIFY( !bool( CommandList( rootScript, false, 10s ).run() ) ); // .. fails for two reasons QVERIFY( !bool( CommandList( rootScript, true, 10s ).run() ) ); @@ -190,7 +190,14 @@ script: // But no user set yet QVERIFY( !bool( CommandList( userScript, false, 10s ).run() ) ); - // Now play dangerous games with shell expansion + // Show that shell expansion is now quoted. gs->insert( "username", "`id -u`" ); - QVERIFY( bool( CommandList( userScript, false, 10s ).run() ) ); + { + CalamaresUtils::CommandLine c { QStringLiteral( "chown ${USER}" ), std::chrono::seconds( 0 ) }; + QCOMPARE( c.expand().command(), QStringLiteral( "chown '`id -u`'" ) ); + } + // Now play dangerous games with shell expansion -- except the internal command is now + // quoted, so this fails because it's **highly** unlikely that the literal string + // "`id -u`" is a valid username. + QVERIFY( !bool( CommandList( userScript, false, 10s ).run() ) ); } diff --git a/src/modules/shellprocess/Tests.h b/src/modules/shellprocess/Tests.h index cabeaada2..c44fa853b 100644 --- a/src/modules/shellprocess/Tests.h +++ b/src/modules/shellprocess/Tests.h @@ -31,7 +31,7 @@ private Q_SLOTS: void testProcessFromObject(); // Create from a complex YAML list void testProcessListFromObject(); - // Check @@ROOT@@ substitution + // Check variable substitution void testRootSubstitution(); }; diff --git a/src/modules/shellprocess/shellprocess.conf b/src/modules/shellprocess/shellprocess.conf index 07947f38f..9ff83221e 100644 --- a/src/modules/shellprocess/shellprocess.conf +++ b/src/modules/shellprocess/shellprocess.conf @@ -7,11 +7,13 @@ # If the top-level key *dontChroot* is true, then the commands # are executed in the context of the live system, otherwise # in the context of the target system. In all of the commands, -# the following substitutions will take place: -# - `@@ROOT@@` is replaced by the root mount point of the **target** -# system from the point of view of the command (for chrooted -# commands, that will be */*). -# - `@@USER@@` is replaced by the username, set on the user page. +# the following variable expansions will take place: +# - `ROOT` is replaced by the root mount point of the **target** +# system from the point of view of the command (when run in the target +# system, e.g. when *dontChroot* is false, that will be `/`). +# - `USER` is replaced by the username, set on the user page. +# +# Variables are written as `${var}`, e.g. `${ROOT}`. # # The (global) timeout for the command list can be set with # the *timeout* key. The value is a time in seconds, default @@ -72,7 +74,7 @@ dontChroot: false # ignored; the slowloris command has a different timeout from the # other commands in the list): script: - - "-touch @@ROOT@@/tmp/thingy" + - "-touch ${ROOT}/tmp/thingy" - "/usr/bin/true" - command: "/usr/local/bin/slowloris" timeout: 3600 diff --git a/src/modules/summary/CMakeLists.txt b/src/modules/summary/CMakeLists.txt index e3c1a381c..16f98ebb4 100644 --- a/src/modules/summary/CMakeLists.txt +++ b/src/modules/summary/CMakeLists.txt @@ -3,8 +3,8 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) -calamares_add_plugin( summary +include_directories(${PROJECT_BINARY_DIR}/src/libcalamaresui) +calamares_add_plugin(summary TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/summaryq/CMakeLists.txt b/src/modules/summaryq/CMakeLists.txt index 8aac1bc2f..071c344ef 100644 --- a/src/modules/summaryq/CMakeLists.txt +++ b/src/modules/summaryq/CMakeLists.txt @@ -3,15 +3,15 @@ # SPDX-FileCopyrightText: 2021 Anke Boersma # SPDX-License-Identifier: BSD-2-Clause # -if( NOT WITH_QML ) +if(NOT WITH_QML) calamares_skip_module( "summaryq (QML is not supported in this build)" ) return() endif() -set( _summary ${CMAKE_CURRENT_SOURCE_DIR}/../summary ) -include_directories( ${_summary} ) +set(_summary ${CMAKE_CURRENT_SOURCE_DIR}/../summary) +include_directories(${_summary}) -calamares_add_plugin( summaryq +calamares_add_plugin(summaryq TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/tracking/CMakeLists.txt b/src/modules/tracking/CMakeLists.txt index a878961b0..0dbbeb942 100644 --- a/src/modules/tracking/CMakeLists.txt +++ b/src/modules/tracking/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -calamares_add_plugin( tracking +calamares_add_plugin(tracking TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -16,11 +16,8 @@ calamares_add_plugin( tracking RESOURCES page_trackingstep.qrc SHARED_LIB + LINK_LIBRARIES + KF5::CoreAddons ) -calamares_add_test( - trackingtest - SOURCES - Tests.cpp - Config.cpp -) +calamares_add_test(trackingtest SOURCES Tests.cpp Config.cpp) diff --git a/src/modules/umount/CMakeLists.txt b/src/modules/umount/CMakeLists.txt index d72847007..09e6a085d 100644 --- a/src/modules/umount/CMakeLists.txt +++ b/src/modules/umount/CMakeLists.txt @@ -3,7 +3,7 @@ # SPDX-FileCopyrightText: 2021 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -calamares_add_plugin( umount +calamares_add_plugin(umount TYPE job EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -12,8 +12,4 @@ calamares_add_plugin( umount EMERGENCY ) -calamares_add_test( - umounttest - SOURCES - Tests.cpp -) +calamares_add_test(umounttest SOURCES Tests.cpp) diff --git a/src/modules/umount/UmountJob.cpp b/src/modules/umount/UmountJob.cpp index 99777d2d0..fa8f28e11 100644 --- a/src/modules/umount/UmountJob.cpp +++ b/src/modules/umount/UmountJob.cpp @@ -82,7 +82,7 @@ unmountTargetMounts( const QString& rootMountPoint ) } static Calamares::JobResult -exportZFSPools( const QString& rootMountPoint ) +exportZFSPools() { auto* gs = Calamares::JobQueue::instance()->globalStorage(); QStringList poolNames; @@ -142,7 +142,7 @@ UmountJob::exec() } // For ZFS systems, export the pools { - auto r = exportZFSPools( gs->value( "rootMountPoint" ).toString() ); + auto r = exportZFSPools(); if ( !r ) { return r; @@ -155,6 +155,7 @@ UmountJob::exec() void UmountJob::setConfigurationMap( const QVariantMap& map ) { + Q_UNUSED( map ) } CALAMARES_PLUGIN_FACTORY_DEFINITION( UmountJobFactory, registerPlugin< UmountJob >(); ) diff --git a/src/modules/unpackfs/tests/4.job b/src/modules/unpackfs/tests/4.job index 8bc7de5ba..e6b067ddb 100644 --- a/src/modules/unpackfs/tests/4.job +++ b/src/modules/unpackfs/tests/4.job @@ -1,6 +1,10 @@ # SPDX-FileCopyrightText: no # SPDX-License-Identifier: CC0-1.0 +# +# Test that a "bogus" sourcefs (a filesystem kind that does not +# exist) fails gracefully. --- unpack: - source: . sourcefs: bogus + destination: / diff --git a/src/modules/users/CMakeLists.txt b/src/modules/users/CMakeLists.txt index 8203ecf08..060c9b691 100644 --- a/src/modules/users/CMakeLists.txt +++ b/src/modules/users/CMakeLists.txt @@ -3,39 +3,33 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Core DBus Network ) -find_package( Crypt REQUIRED ) +find_package(Qt5 ${QT_VERSION} CONFIG REQUIRED Core DBus Network) +find_package(Crypt REQUIRED) # Add optional libraries here -set( USER_EXTRA_LIB ) +set(USER_EXTRA_LIB) -find_package( LibPWQuality ) -set_package_properties( - LibPWQuality PROPERTIES - PURPOSE "Extra checks of password quality" -) +find_package(LibPWQuality) +set_package_properties(LibPWQuality PROPERTIES PURPOSE "Extra checks of password quality") -if( LibPWQuality_FOUND ) - list( APPEND USER_EXTRA_LIB ${LibPWQuality_LIBRARIES} ) - include_directories( ${LibPWQuality_INCLUDE_DIRS} ) - add_definitions( -DCHECK_PWQUALITY -DHAVE_LIBPWQUALITY ) +if(LibPWQuality_FOUND) + list(APPEND USER_EXTRA_LIB ${LibPWQuality_LIBRARIES}) + include_directories(${LibPWQuality_INCLUDE_DIRS}) + add_definitions(-DCHECK_PWQUALITY -DHAVE_LIBPWQUALITY) endif() -find_package( ICU COMPONENTS uc i18n ) -set_package_properties( - ICU PROPERTIES - PURPOSE "Transliteration support for full name to username conversion" -) +find_package(ICU COMPONENTS uc i18n) +set_package_properties(ICU PROPERTIES PURPOSE "Transliteration support for full name to username conversion") -if( ICU_FOUND ) - list( APPEND USER_EXTRA_LIB ICU::uc ICU::i18n ) - include_directories( ${ICU_INCLUDE_DIRS} ) - add_definitions( -DHAVE_ICU ) +if(ICU_FOUND) + list(APPEND USER_EXTRA_LIB ICU::uc ICU::i18n) + include_directories(${ICU_INCLUDE_DIRS}) + add_definitions(-DHAVE_ICU) endif() -include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) +include_directories(${PROJECT_BINARY_DIR}/src/libcalamaresui) -set( _users_src +set(_users_src # Jobs CreateUserJob.cpp MiscJobs.cpp @@ -46,6 +40,7 @@ set( _users_src Config.cpp ) +# This part of the code is shared with the usersq module calamares_add_library( users_internal EXPORT_MACRO PLUGINDLLEXPORT_PRO @@ -55,11 +50,12 @@ calamares_add_library( SOURCES ${_users_src} LINK_LIBRARIES + KF5::CoreAddons Qt5::DBus ${CRYPT_LIBRARIES} ) -calamares_add_plugin( users +calamares_add_plugin(users TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES @@ -76,42 +72,35 @@ calamares_add_plugin( users SHARED_LIB ) -calamares_add_test( - userspasswordtest - SOURCES - TestPasswordJob.cpp - SetPasswordJob.cpp - LIBRARIES - ${CRYPT_LIBRARIES} -) +calamares_add_test(userspasswordtest SOURCES TestPasswordJob.cpp SetPasswordJob.cpp LIBRARIES ${CRYPT_LIBRARIES}) calamares_add_test( usersgroupstest SOURCES TestGroupInformation.cpp - ${_users_src} # Build again with test-visibility + ${_users_src} # Build again with test-visibility LIBRARIES - Qt5::DBus # HostName job can use DBus to systemd - ${CRYPT_LIBRARIES} # SetPassword job uses crypt() + KF5::CoreAddons + Qt5::DBus # HostName job can use DBus to systemd + ${CRYPT_LIBRARIES} # SetPassword job uses crypt() ${USER_EXTRA_LIB} ) calamares_add_test( usershostnametest - SOURCES - TestSetHostNameJob.cpp - SetHostNameJob.cpp + SOURCES TestSetHostNameJob.cpp SetHostNameJob.cpp LIBRARIES - Qt5::DBus # HostName job can use DBus to systemd + Qt5::DBus # HostName job can use DBus to systemd ) calamares_add_test( userstest SOURCES Tests.cpp - ${_users_src} # Build again with test-visibility + ${_users_src} # Build again with test-visibility LIBRARIES - Qt5::DBus # HostName job can use DBus to systemd - ${CRYPT_LIBRARIES} # SetPassword job uses crypt() + KF5::CoreAddons + Qt5::DBus # HostName job can use DBus to systemd + ${CRYPT_LIBRARIES} # SetPassword job uses crypt() ${USER_EXTRA_LIB} ) diff --git a/src/modules/users/CheckPWQuality.h b/src/modules/users/CheckPWQuality.h index 6d7fb56df..db2cba0af 100644 --- a/src/modules/users/CheckPWQuality.h +++ b/src/modules/users/CheckPWQuality.h @@ -67,9 +67,9 @@ using PasswordCheckList = QVector< PasswordCheck >; * may skip adding a check, and do nothing (it should log * an error, though). */ -#define _xDEFINE_CHECK_FUNC( x ) add_check_##x( PasswordCheckList& checks, const QVariant& value ) -#define DEFINE_CHECK_FUNC( x ) void _xDEFINE_CHECK_FUNC( x ) -#define DECLARE_CHECK_FUNC( x ) void _xDEFINE_CHECK_FUNC( x ); +#define DEFINE_CHECK_FUNC_impl( x ) add_check_##x( PasswordCheckList& checks, const QVariant& value ) +#define DEFINE_CHECK_FUNC( x ) void DEFINE_CHECK_FUNC_impl( x ) +#define DECLARE_CHECK_FUNC( x ) void DEFINE_CHECK_FUNC_impl( x ); DECLARE_CHECK_FUNC( minLength ) DECLARE_CHECK_FUNC( maxLength ) diff --git a/src/modules/users/Config.cpp b/src/modules/users/Config.cpp index c75e8a6e7..f55c4fd99 100644 --- a/src/modules/users/Config.cpp +++ b/src/modules/users/Config.cpp @@ -471,7 +471,7 @@ Config::setFullName( const QString& name ) // Build login and hostname, if needed static QRegExp rx( "[^a-zA-Z0-9 ]", Qt::CaseInsensitive ); - const QString cleanName = CalamaresUtils::removeDiacritics( transliterate( name ) ) + const QString cleanName = Calamares::String::removeDiacritics( transliterate( name ) ) .replace( QRegExp( "[-']" ), "" ) .replace( rx, " " ) .toLower() @@ -874,25 +874,6 @@ either( T ( *f )( const QVariantMap&, const QString&, U ), } } -// TODO:3.3: Remove -static void -copyLegacy( const QVariantMap& source, const QString& sourceKey, QVariantMap& target, const QString& targetKey ) -{ - if ( source.contains( sourceKey ) ) - { - if ( target.contains( targetKey ) ) - { - cWarning() << "Legacy *users* key" << sourceKey << "ignored."; - } - else - { - const QVariant legacyValue = source.value( sourceKey ); - cWarning() << "Legacy *users* key" << sourceKey << "overrides hostname-settings."; - target.insert( targetKey, legacyValue ); - } - } -} - /** @brief Tidy up a list of names * * Remove duplicates, apply lowercase, sort. @@ -913,9 +894,6 @@ Config::setConfigurationMap( const QVariantMap& configurationMap ) bool ok = false; // Ignored QVariantMap userSettings = CalamaresUtils::getSubMap( configurationMap, "user", ok ); - // TODO:3.3: Remove calls to copyLegacy - copyLegacy( configurationMap, "userShell", userSettings, "shell" ); - QString shell( QLatin1String( "/bin/bash" ) ); // as if it's not set at all if ( userSettings.contains( "shell" ) ) { @@ -941,9 +919,6 @@ Config::setConfigurationMap( const QVariantMap& configurationMap ) bool ok = false; // Ignored QVariantMap hostnameSettings = CalamaresUtils::getSubMap( configurationMap, "hostname", ok ); - // TODO:3.3: Remove calls to copyLegacy - copyLegacy( configurationMap, "setHostname", hostnameSettings, "location" ); - copyLegacy( configurationMap, "writeHostsFile", hostnameSettings, "writeHostsFile" ); m_hostnameAction = getHostNameAction( hostnameSettings ); m_writeEtcHosts = CalamaresUtils::getBool( hostnameSettings, "writeHostsFile", true ); m_hostnameTemplate @@ -998,7 +973,7 @@ Config::finalizeGlobalStorage() const { gs->insert( "reuseRootPassword", reuseUserPasswordForRoot() ); } - gs->insert( "password", CalamaresUtils::obscure( userPassword() ) ); + gs->insert( "password", Calamares::String::obscure( userPassword() ) ); } Calamares::JobList diff --git a/src/modules/users/Tests.cpp b/src/modules/users/Tests.cpp index b7835251f..ac27570ca 100644 --- a/src/modules/users/Tests.cpp +++ b/src/modules/users/Tests.cpp @@ -284,8 +284,10 @@ UserTests::testHostActions2() QCOMPARE( c.hostnameAction(), HostNameAction::EtcHostname ); QCOMPARE( c.writeEtcHosts(), true ); - legacy.insert( "writeHostsFile", false ); - legacy.insert( "setHostname", "Hostnamed" ); + QVariantMap hostSettings; + hostSettings.insert( "writeHostsFile", false ); + hostSettings.insert( "location", "Hostnamed" ); + legacy.insert( "hostname", hostSettings ); c.setConfigurationMap( legacy ); QCOMPARE( c.hostnameAction(), HostNameAction::SystemdHostname ); QCOMPARE( c.writeEtcHosts(), false ); @@ -469,16 +471,14 @@ UserTests::testUserYAML_data() QTest::addColumn< QString >( "filename" ); QTest::addColumn< QString >( "shell" ); - QTest::newRow( "old, unset " ) << "tests/7ao-shell.conf" - << "/bin/bash"; - QTest::newRow( "old, empty " ) << "tests/7bo-shell.conf" - << ""; - QTest::newRow( "old, relative" ) << "tests/7co-shell.conf" - << "/bin/ls"; // Setting is ignored - QTest::newRow( "old, invalid " ) << "tests/7do-shell.conf" - << ""; - QTest::newRow( "old, absolute" ) << "tests/7eo-shell.conf" - << "/usr/bin/dash"; + const QString bash = QStringLiteral( "/bin/bash" ); + + // All the old settings are ignored + QTest::newRow( "old, unset " ) << "tests/7ao-shell.conf" << bash; + QTest::newRow( "old, empty " ) << "tests/7bo-shell.conf" << bash; + QTest::newRow( "old, relative" ) << "tests/7co-shell.conf" << bash; + QTest::newRow( "old, invalid " ) << "tests/7do-shell.conf" << bash; + QTest::newRow( "old, absolute" ) << "tests/7eo-shell.conf" << bash; QTest::newRow( "new, unset " ) << "tests/7an-shell.conf" << "/bin/bash"; diff --git a/src/modules/users/users.conf b/src/modules/users/users.conf index 779d1afdf..00a98ee7f 100644 --- a/src/modules/users/users.conf +++ b/src/modules/users/users.conf @@ -161,10 +161,6 @@ allowWeakPasswordsDefault: false user: shell: /bin/bash forbidden_names: [ root ] -# TODO:3.3: Remove this setting -# -# This is the legacy setting for user.shell -userShell: /bin/bash # Hostname settings # @@ -212,17 +208,6 @@ hostname: template: "derp-${cpu}" forbidden_names: [ localhost ] -# TODO:3.3: Remove this setting -# -# This is a legacy setting for hostname.location; if it is set -# at all, and there is no setting for hostname.location, it is used. -setHostname: EtcFile - -# TODO:3.3: Remove this setting -# -# This is a legacy setting for hostname.writeHostsFile -writeHostsFile: true - presets: fullName: # value: "OEM User" diff --git a/src/modules/users/users.schema.yaml b/src/modules/users/users.schema.yaml index 025f8a3d2..972306b80 100644 --- a/src/modules/users/users.schema.yaml +++ b/src/modules/users/users.schema.yaml @@ -6,13 +6,12 @@ $id: https://calamares.io/schemas/users additionalProperties: false type: object properties: - # User shell, should be path to /bin/sh or so - userShell: { type: string } user: additionalProperties: false type: object properties: - shell: { type: string } # Overrides userShell + # User shell, should be path to /bin/sh or so + shell: { type: string } forbidden_names: { type: array, items: { type: string } } # Group settings defaultGroups: @@ -54,9 +53,6 @@ properties: writeHostsFile: { type: boolean, default: true } template: { type: string, default: "${first}-${product}" } forbidden_names: { type: array, items: { type: string } } - # Legacy Hostname setting - setHostname: { type: string, enum: [ None, EtcFile, Hostnamed ] } - writeHostsFile: { type: boolean, default: true } # Presets # diff --git a/src/modules/usersq/CMakeLists.txt b/src/modules/usersq/CMakeLists.txt index 8465b0246..33133f439 100644 --- a/src/modules/usersq/CMakeLists.txt +++ b/src/modules/usersq/CMakeLists.txt @@ -3,45 +3,39 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -if( NOT WITH_QML ) +if(NOT WITH_QML) calamares_skip_module( "usersq (QML is not supported in this build)" ) return() endif() -find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Core DBus Network ) -find_package( Crypt REQUIRED ) +find_package(Qt5 ${QT_VERSION} CONFIG REQUIRED Core DBus Network) +find_package(Crypt REQUIRED) # Add optional libraries here -set( USER_EXTRA_LIB ) +set(USER_EXTRA_LIB) -include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/../users ) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../users) -find_package( LibPWQuality ) -set_package_properties( - LibPWQuality PROPERTIES - PURPOSE "Extra checks of password quality" -) +find_package(LibPWQuality) +set_package_properties(LibPWQuality PROPERTIES PURPOSE "Extra checks of password quality") -if( LibPWQuality_FOUND ) - list( APPEND USER_EXTRA_LIB ${LibPWQuality_LIBRARIES} ) - include_directories( ${LibPWQuality_INCLUDE_DIRS} ) - add_definitions( -DCHECK_PWQUALITY -DHAVE_LIBPWQUALITY ) +if(LibPWQuality_FOUND) + list(APPEND USER_EXTRA_LIB ${LibPWQuality_LIBRARIES}) + include_directories(${LibPWQuality_INCLUDE_DIRS}) + add_definitions(-DCHECK_PWQUALITY -DHAVE_LIBPWQUALITY) endif() #needed for ${_users}/Config.cpp -find_package( ICU COMPONENTS uc i18n ) -set_package_properties( - ICU PROPERTIES - PURPOSE "Transliteration support for full name to username conversion" -) +find_package(ICU COMPONENTS uc i18n) +set_package_properties(ICU PROPERTIES PURPOSE "Transliteration support for full name to username conversion") -if( ICU_FOUND ) - list( APPEND USER_EXTRA_LIB ICU::uc ICU::i18n ) - include_directories( ${ICU_INCLUDE_DIRS} ) - add_definitions( -DHAVE_ICU ) +if(ICU_FOUND) + list(APPEND USER_EXTRA_LIB ICU::uc ICU::i18n) + include_directories(${ICU_INCLUDE_DIRS}) + add_definitions(-DHAVE_ICU) endif() -calamares_add_plugin( usersq +calamares_add_plugin(usersq TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/webview/CMakeLists.txt b/src/modules/webview/CMakeLists.txt index 54e1d18b0..b8ef5d7d4 100644 --- a/src/modules/webview/CMakeLists.txt +++ b/src/modules/webview/CMakeLists.txt @@ -3,52 +3,41 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -set( CALA_WEBVIEW_LINK_LIBRARIES "" ) +set(CALA_WEBVIEW_LINK_LIBRARIES "") -option( WEBVIEW_FORCE_WEBKIT "Always build webview with WebKit instead of WebEngine regardless of Qt version." OFF) +option(WEBVIEW_FORCE_WEBKIT "Always build webview with WebKit instead of WebEngine regardless of Qt version." OFF) -set( _reason "" ) +set(_reason "") -message( STATUS "Found Qt version ${Qt5Core_VERSION}") -if ( Qt5Core_VERSION VERSION_LESS 5.6 OR WEBVIEW_FORCE_WEBKIT ) - message( STATUS " .. using webkit") - find_package( Qt5 ${QT_VERSION} CONFIG COMPONENTS WebKit WebKitWidgets ) +message(STATUS "Found Qt version ${Qt5Core_VERSION}") +if(Qt5Core_VERSION VERSION_LESS 5.6 OR WEBVIEW_FORCE_WEBKIT) + message(STATUS " .. using webkit") + find_package(Qt5 ${QT_VERSION} CONFIG COMPONENTS WebKit WebKitWidgets) - if ( Qt5WebKit_FOUND AND Qt5WebKitWidgets_FOUND ) - list( APPEND CALA_WEBVIEW_INCLUDE_DIRECTORIES - ${QT_QTWEBKIT_INCLUDE_DIR} - ) - list( APPEND CALA_WEBVIEW_LINK_LIBRARIES - Qt5::WebKit - Qt5::WebKitWidgets - ) - set( WEBVIEW_WITH_WEBKIT 1 ) + if(Qt5WebKit_FOUND AND Qt5WebKitWidgets_FOUND) + list(APPEND CALA_WEBVIEW_INCLUDE_DIRECTORIES ${QT_QTWEBKIT_INCLUDE_DIR}) + list(APPEND CALA_WEBVIEW_LINK_LIBRARIES Qt5::WebKit Qt5::WebKitWidgets) + set(WEBVIEW_WITH_WEBKIT 1) else() - set( _reason "No suitable WebKit" ) + set(_reason "No suitable WebKit") endif() else() - message( STATUS " .. using webengine") - find_package( Qt5 ${QT_VERSION} CONFIG COMPONENTS WebEngine WebEngineWidgets ) + message(STATUS " .. using webengine") + find_package(Qt5 ${QT_VERSION} CONFIG COMPONENTS WebEngine WebEngineWidgets) - if ( Qt5WebEngine_FOUND AND Qt5WebEngineWidgets_FOUND ) - list( APPEND CALA_WEBVIEW_INCLUDE_DIRECTORIES - ${QT_QTWEBENGINE_INCLUDE_DIR} - ) - list( APPEND CALA_WEBVIEW_LINK_LIBRARIES - Qt5::WebEngine - Qt5::WebEngineWidgets - ) - set( WEBVIEW_WITH_WEBENGINE 1 ) + if(Qt5WebEngine_FOUND AND Qt5WebEngineWidgets_FOUND) + list(APPEND CALA_WEBVIEW_INCLUDE_DIRECTORIES ${QT_QTWEBENGINE_INCLUDE_DIR}) + list(APPEND CALA_WEBVIEW_LINK_LIBRARIES Qt5::WebEngine Qt5::WebEngineWidgets) + set(WEBVIEW_WITH_WEBENGINE 1) else() - set( _reason "No suitable WebEngine" ) + set(_reason "No suitable WebEngine") endif() endif() -if ( NOT _reason ) - configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/WebViewConfig.h.in - ${CMAKE_CURRENT_BINARY_DIR}/WebViewConfig.h ) +if(NOT _reason) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/WebViewConfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/WebViewConfig.h) - calamares_add_plugin( webview + calamares_add_plugin(webview TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/webview/WebViewStep.cpp b/src/modules/webview/WebViewStep.cpp index 8e7c48f1a..d787b8ec6 100644 --- a/src/modules/webview/WebViewStep.cpp +++ b/src/modules/webview/WebViewStep.cpp @@ -28,12 +28,11 @@ WebViewStep::WebViewStep( QObject* parent ) #ifdef WEBVIEW_WITH_WEBENGINE QtWebEngine::initialize(); #endif - m_view = new C_QWEBVIEW(); + m_view = new WebViewWidget(); #ifdef WEBVIEW_WITH_WEBKIT m_view->settings()->setFontFamily( QWebSettings::StandardFont, m_view->settings()->fontFamily( QWebSettings::SansSerifFont ) ); - m_view->setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::HighQualityAntialiasing - | QPainter::SmoothPixmapTransform | QPainter::NonCosmeticDefaultPen ); + m_view->setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform ); #endif } diff --git a/src/modules/webview/WebViewStep.h b/src/modules/webview/WebViewStep.h index 6fd71222e..700da2856 100644 --- a/src/modules/webview/WebViewStep.h +++ b/src/modules/webview/WebViewStep.h @@ -20,20 +20,21 @@ #include -#ifdef WEBVIEW_WITH_WEBKIT -#define C_QWEBVIEW QWebView -#endif -#ifdef WEBVIEW_WITH_WEBENGINE -#ifdef C_QWEBVIEW +#if defined( WEBVIEW_WITH_WEBKIT ) && defined( WEBVIEW_WITH_WEBENGINE ) #error Both WEBENGINE and WEBKIT enabled #endif -#define C_QWEBVIEW QWebEngineView -#endif -#ifndef C_QWEBVIEW +#if !defined( WEBVIEW_WITH_WEBKIT ) && !defined( WEBVIEW_WITH_WEBENGINE ) #error Neither WEBENGINE nor WEBKIT enabled #endif -class C_QWEBVIEW; +#ifdef WEBVIEW_WITH_WEBKIT +class QWebView; +using WebViewWidget = QWebView; +#endif +#ifdef WEBVIEW_WITH_WEBENGINE +class QWebEngineView; +using WebViewWidget = QWebEngineView; +#endif class PLUGINDLLEXPORT WebViewStep : public Calamares::ViewStep { @@ -60,7 +61,7 @@ public: void setConfigurationMap( const QVariantMap& configurationMap ) override; private: - C_QWEBVIEW* m_view; + WebViewWidget* m_view; QString m_url; QString m_prettyName; }; diff --git a/src/modules/welcome/CMakeLists.txt b/src/modules/welcome/CMakeLists.txt index 01a89703a..0a8353084 100644 --- a/src/modules/welcome/CMakeLists.txt +++ b/src/modules/welcome/CMakeLists.txt @@ -3,25 +3,25 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED DBus Network ) +find_package(Qt5 ${QT_VERSION} CONFIG REQUIRED DBus Network) -find_package( LIBPARTED ) -if ( LIBPARTED_FOUND ) - set( PARTMAN_SRC checker/partman_devices.c ) - set( PARTMAN_LIB ${LIBPARTED_LIBRARY} ) +find_package(LIBPARTED) +if(LIBPARTED_FOUND) + set(PARTMAN_SRC checker/partman_devices.c) + set(PARTMAN_LIB ${LIBPARTED_LIBRARY}) else() - set( PARTMAN_SRC ) - set( PARTMAN_LIB ) - add_definitions( -DWITHOUT_LIBPARTED ) + set(PARTMAN_SRC) + set(PARTMAN_LIB) + add_definitions(-DWITHOUT_LIBPARTED) endif() -calamares_add_plugin( welcome +calamares_add_plugin(welcome TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES checker/CheckerContainer.cpp checker/GeneralRequirements.cpp - checker/ResultWidget.cpp + checker/ResultDelegate.cpp checker/ResultsListWidget.cpp ${PARTMAN_SRC} WelcomeViewStep.cpp @@ -41,15 +41,6 @@ calamares_add_plugin( welcome calamares_add_test( welcometest - SOURCES - checker/GeneralRequirements.cpp - ${PARTMAN_SRC} - Config.cpp - Tests.cpp - LIBRARIES - ${PARTMAN_LIB} - Qt5::DBus - Qt5::Network - Qt5::Widgets - Calamares::calamaresui + SOURCES checker/GeneralRequirements.cpp ${PARTMAN_SRC} Config.cpp Tests.cpp + LIBRARIES ${PARTMAN_LIB} Qt5::DBus Qt5::Network Qt5::Widgets Calamares::calamaresui ) diff --git a/src/modules/welcome/Config.cpp b/src/modules/welcome/Config.cpp index e5b2da211..0e692637b 100644 --- a/src/modules/welcome/Config.cpp +++ b/src/modules/welcome/Config.cpp @@ -55,12 +55,10 @@ Config::retranslate() { message = setup ? tr( "This computer does not satisfy the minimum " "requirements for setting up %1.
" - "Setup cannot continue. " - "Details..." ) + "Setup cannot continue." ) : tr( "This computer does not satisfy the minimum " "requirements for installing %1.
" - "Installation cannot continue. " - "Details..." ); + "Installation cannot continue." ); } else { @@ -130,7 +128,6 @@ Config::initLanguages() // Need to match by some other means than the exact translation Id if ( matchedLocaleIndex < 0 ) { - QLocale defaultLocale = defaultTranslation.locale(); cDebug() << "Trying to match locale" << defaultLocale; diff --git a/src/modules/welcome/checker/CheckerContainer.cpp b/src/modules/welcome/checker/CheckerContainer.cpp index 23055c2e0..dd5a6680f 100644 --- a/src/modules/welcome/checker/CheckerContainer.cpp +++ b/src/modules/welcome/checker/CheckerContainer.cpp @@ -65,13 +65,18 @@ CheckerContainer::requirementsComplete( bool ok ) } } - layout()->removeWidget( m_waitingWidget ); - m_waitingWidget->deleteLater(); - m_waitingWidget = nullptr; // Don't delete in destructor - - m_checkerWidget = new ResultsListWidget( m_config, this ); - m_checkerWidget->setObjectName( "requirementsChecker" ); - layout()->addWidget( m_checkerWidget ); + if ( m_waitingWidget ) + { + layout()->removeWidget( m_waitingWidget ); + m_waitingWidget->deleteLater(); + m_waitingWidget = nullptr; // Don't delete in destructor + } + if ( !m_checkerWidget ) + { + m_checkerWidget = new ResultsListWidget( m_config, this ); + m_checkerWidget->setObjectName( "requirementsChecker" ); + layout()->addWidget( m_checkerWidget ); + } m_verdict = ok; } diff --git a/src/modules/welcome/checker/GeneralRequirements.cpp b/src/modules/welcome/checker/GeneralRequirements.cpp index 5950bd396..5f0124ef6 100644 --- a/src/modules/welcome/checker/GeneralRequirements.cpp +++ b/src/modules/welcome/checker/GeneralRequirements.cpp @@ -15,6 +15,9 @@ #include "CheckerContainer.h" #include "partman_devices.h" +#include "CalamaresVersion.h" // For development-or-not +#include "GlobalStorage.h" +#include "JobQueue.h" #include "Settings.h" #include "modulesystem/Requirement.h" #include "network/Manager.h" @@ -26,9 +29,6 @@ #include "utils/Variant.h" #include "widgets/WaitingWidget.h" -#include "GlobalStorage.h" -#include "JobQueue.h" - #include #include #include @@ -145,19 +145,25 @@ GeneralRequirements::checkRequirements() << TR( "hasInternet", hasInternet ) << TR( "isRoot", isRoot ); // clang-format on + Calamares::RequirementsList checkEntries; foreach ( const QString& entry, m_entriesToCheck ) { + const bool required = m_entriesToRequire.contains( entry ); if ( entry == "storage" ) { checkEntries.append( { entry, [ req = m_requiredStorageGiB ] - { return tr( "has at least %1 GiB available drive space" ).arg( req ); }, + { + return tr( "Please ensure the system has at least %1 GiB available drive space." ).arg( req ) + + QStringLiteral( "

" ) + + tr( "Available drive space is all of the hard disks and SSDs connected to the system." ); + }, [ req = m_requiredStorageGiB ] { return tr( "There is not enough drive space. At least %1 GiB is required." ).arg( req ); }, enoughStorage, - m_entriesToRequire.contains( entry ) } ); + required } ); } else if ( entry == "ram" ) { @@ -169,7 +175,7 @@ GeneralRequirements::checkRequirements() .arg( req ); }, enoughRam, - m_entriesToRequire.contains( entry ) } ); + required } ); } else if ( entry == "power" ) { @@ -177,7 +183,7 @@ GeneralRequirements::checkRequirements() [] { return tr( "is plugged in to a power source" ); }, [] { return tr( "The system is not plugged in to a power source." ); }, hasPower, - m_entriesToRequire.contains( entry ) } ); + required } ); } else if ( entry == "internet" ) { @@ -185,7 +191,7 @@ GeneralRequirements::checkRequirements() [] { return tr( "is connected to the Internet" ); }, [] { return tr( "The system is not connected to the Internet." ); }, hasInternet, - m_entriesToRequire.contains( entry ) } ); + required } ); } else if ( entry == "root" ) { @@ -198,7 +204,7 @@ GeneralRequirements::checkRequirements() : tr( "The installer is not running with administrator rights." ); }, isRoot, - m_entriesToRequire.contains( entry ) } ); + required } ); } else if ( entry == "screen" ) { @@ -211,8 +217,39 @@ GeneralRequirements::checkRequirements() : tr( "The screen is too small to display the installer." ); }, enoughScreen, - false } ); + required } ); } +#ifdef CALAMARES_VERSION_RC + if ( entry == "false" ) + { + checkEntries.append( { entry, + [] { return tr( "is always false" ); }, + [] { return tr( "The computer says no." ); }, + false, + required } ); + } + if ( entry == "true" ) + { + checkEntries.append( { entry, + [] { return tr( "is always true" ); }, + [] { return tr( "The computer says yes." ); }, + true, + required } ); + } + if ( entry == "snark" ) + { + static unsigned int snark_count = 0; + checkEntries.append( { entry, + [] { return tr( "is checked three times." ); }, + [] + { + return tr( "The snark has not been checked three times.", + "The (some mythological beast) has not been checked three times." ); + }, + ++snark_count > 3, + required } ); + } +#endif } return checkEntries; } diff --git a/src/modules/welcome/checker/ResultDelegate.cpp b/src/modules/welcome/checker/ResultDelegate.cpp new file mode 100644 index 000000000..420ece812 --- /dev/null +++ b/src/modules/welcome/checker/ResultDelegate.cpp @@ -0,0 +1,104 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2022 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +#include "ResultDelegate.h" + +#include "modulesystem/RequirementsModel.h" +#include "utils/CalamaresUtilsGui.h" + +#include +#include + +static constexpr int const item_margin = 8; +static inline int +item_fontsize() +{ + return CalamaresUtils::defaultFontSize() + 4; +} + +static void +paintRequirement( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, int role ) +{ + const auto fontsize = item_fontsize(); + + QRect textRect = option.rect.adjusted( item_margin, item_margin, -item_margin, -item_margin ); + QFont font = qApp->font(); + font.setPointSize( fontsize ); + font.setBold( false ); + painter->setFont( font ); + + CalamaresUtils::ImageType statusImage = CalamaresUtils::StatusOk; + + painter->setPen( QColorConstants::Black ); + if ( index.data( Calamares::RequirementsModel::Satisfied ).toBool() ) + { + painter->fillRect( textRect, option.palette.window().color() ); + } + else + { + if ( index.data( Calamares::RequirementsModel::Mandatory ).toBool() ) + { + QColor bgColor = option.palette.window().color(); + bgColor.setHsv( 0, 64, bgColor.value() ); + painter->fillRect( option.rect, bgColor ); + statusImage = CalamaresUtils::StatusError; + } + else + { + QColor bgColor = option.palette.window().color(); + bgColor.setHsv( 60, 64, bgColor.value() ); + painter->fillRect( option.rect, bgColor ); + statusImage = CalamaresUtils::StatusWarning; + } + } + + auto image + = CalamaresUtils::defaultPixmap( statusImage, CalamaresUtils::Original, QSize( 2 * fontsize, 2 * fontsize ) ) + .toImage(); + painter->drawImage( textRect.topLeft(), image ); + + // Leave space for that image (already drawn) + textRect.moveLeft( 2 * fontsize + 2 * item_margin ); + painter->drawText( textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, index.data( role ).toString() ); +} + +QSize +ResultDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const +{ + if ( !index.isValid() ) + { + return option.rect.size(); + } + + QFont font = qApp->font(); + + font.setPointSize( item_fontsize() ); + QFontMetrics fm( font ); + + const int height = fm.height() + 2 * item_margin; + int textwidth = fm.boundingRect( index.data( Calamares::RequirementsModel::NegatedText ).toString() ).width(); + + return QSize( qMax( option.rect.width(), textwidth ), height ); +} + + +void +ResultDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const +{ + QStyleOptionViewItem opt = option; + + painter->save(); + + initStyleOption( &opt, index ); + opt.text.clear(); + + paintRequirement( painter, opt, index, m_textRole ); + + painter->restore(); +} diff --git a/src/modules/welcome/checker/ResultDelegate.h b/src/modules/welcome/checker/ResultDelegate.h new file mode 100644 index 000000000..db770502e --- /dev/null +++ b/src/modules/welcome/checker/ResultDelegate.h @@ -0,0 +1,37 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2022 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +#ifndef WELCOME_CHECKER_RESULTDELEGATE_HH +#define WELCOME_CHECKER_RESULTDELEGATE_HH + +#include + +#include "modulesystem/RequirementsModel.h" + +/** + * @brief Class for drawing (un)satisfied requirements + */ +class ResultDelegate : public QStyledItemDelegate +{ +public: + using QStyledItemDelegate::QStyledItemDelegate; + ResultDelegate( QObject* parent, Calamares::RequirementsModel::Roles text ) + : QStyledItemDelegate( parent ) + , m_textRole( text ) + { + } + +protected: + QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const override; + void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const override; + + int m_textRole = Calamares::RequirementsModel::Name; +}; + +#endif // PROGRESSTREEDELEGATE_H diff --git a/src/modules/welcome/checker/ResultWidget.cpp b/src/modules/welcome/checker/ResultWidget.cpp deleted file mode 100644 index 6e34a6c36..000000000 --- a/src/modules/welcome/checker/ResultWidget.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#include "ResultWidget.h" - -#include "utils/CalamaresUtilsGui.h" -#include "utils/Logger.h" - -#include - -static inline void -setCondition( QLabel* label, CalamaresUtils::ImageType t ) -{ - label->setPixmap( - CalamaresUtils::defaultPixmap( t, CalamaresUtils::Original, QSize( label->height(), label->height() ) ) ); -} - -ResultWidget::ResultWidget( bool satisfied, bool required, QWidget* parent ) - : QWidget( parent ) -{ - QBoxLayout* mainLayout = new QHBoxLayout; - setLayout( mainLayout ); - - m_iconLabel = new QLabel( this ); - m_iconLabel->setFixedSize( CalamaresUtils::defaultIconSize() ); - m_iconLabel->setObjectName( "resultIcon" ); - mainLayout->addWidget( m_iconLabel ); - - m_textLabel = new QLabel( this ); - m_textLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); - m_textLabel->setObjectName( "resultText" ); - mainLayout->addWidget( m_textLabel ); - - if ( satisfied ) - { - setCondition( m_iconLabel, CalamaresUtils::StatusOk ); - } - else if ( required ) - { - setCondition( m_iconLabel, CalamaresUtils::StatusError ); - } - else - { - setCondition( m_iconLabel, CalamaresUtils::StatusWarning ); - } -} - - -void -ResultWidget::setText( const QString& text ) -{ - m_textLabel->setText( text ); -} diff --git a/src/modules/welcome/checker/ResultWidget.h b/src/modules/welcome/checker/ResultWidget.h deleted file mode 100644 index d77c0d9bb..000000000 --- a/src/modules/welcome/checker/ResultWidget.h +++ /dev/null @@ -1,42 +0,0 @@ -/* === This file is part of Calamares - === - * - * SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac - * SPDX-FileCopyrightText: 2017 Adriaan de Groot - * SPDX-License-Identifier: GPL-3.0-or-later - * - * Calamares is Free Software: see the License-Identifier above. - * - */ - -#ifndef CHECKER_RESULTWIDGET_H -#define CHECKER_RESULTWIDGET_H - -#include - -/** - * @brief Displays the results of a single check. - * - * Widget to insert into a ResultListWidget to display an iconic status - * (warning or failure when the check is not satisfied) along with - * descriptive test. - */ -class ResultWidget : public QWidget -{ - Q_OBJECT -public: - /** - * @brief Create widget with results of a check. - * - * Use setText() to set up the text of the widget. - */ - explicit ResultWidget( bool satisfied, bool required, QWidget* parent = nullptr ); - - /// @brief Set the displayed description of the check. - void setText( const QString& text ); - -private: - QLabel* m_textLabel; - QLabel* m_iconLabel; -}; - -#endif // CHECKER_RESULTWIDGET_H diff --git a/src/modules/welcome/checker/ResultsListWidget.cpp b/src/modules/welcome/checker/ResultsListWidget.cpp index a5d92b590..f07725484 100644 --- a/src/modules/welcome/checker/ResultsListWidget.cpp +++ b/src/modules/welcome/checker/ResultsListWidget.cpp @@ -10,7 +10,7 @@ #include "ResultsListWidget.h" -#include "ResultWidget.h" +#include "ResultDelegate.h" #include "Branding.h" #include "Settings.h" @@ -18,183 +18,70 @@ #include "utils/Logger.h" #include "utils/Retranslator.h" #include "widgets/FixedAspectRatioLabel.h" +#include "widgets/WaitingWidget.h" #include #include #include #include +#include #include -/** @brief Add widgets to @p layout for the list @p checkEntries - * - * The @p resultWidgets is filled with pointers to the widgets; - * for each entry in @p checkEntries that satisfies @p predicate, - * a widget is created, otherwise a nullptr is added instead. - * - * Adds all the widgets to the given @p layout. - * - * Afterwards, @p resultWidgets has a length equal to @p checkEntries. - */ -static void -createResultWidgets( QLayout* layout, - QList< ResultWidget* >& resultWidgets, - const Calamares::RequirementsModel& model, - std::function< bool( const Calamares::RequirementsModel&, QModelIndex ) > predicate ) -{ - resultWidgets.clear(); - resultWidgets.reserve( model.count() ); - for ( auto i = 0; i < model.count(); i++ ) - { - const auto& index = model.index( i ); - if ( !predicate( model, index ) ) - { - resultWidgets.append( nullptr ); - continue; - } - - const QString checkName = model.data( index, Calamares::RequirementsModel::Name ).toString(); - const bool is_satisfied = model.data( index, Calamares::RequirementsModel::Satisfied ).toBool(); - const bool is_mandatory = model.data( index, Calamares::RequirementsModel::Mandatory ).toBool(); - ResultWidget* ciw = new ResultWidget( is_satisfied, is_mandatory ); - ciw->setObjectName( checkName ); - - layout->addWidget( ciw ); - ciw->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); - - ciw->setAutoFillBackground( true ); - QPalette pal( ciw->palette() ); - QColor bgColor = pal.window().color(); - int bgHue = ( is_satisfied ) ? bgColor.hue() : ( is_mandatory ) ? 0 : 60; - bgColor.setHsv( bgHue, 64, bgColor.value() ); - pal.setColor( QPalette::Window, bgColor ); - ciw->setPalette( pal ); - - resultWidgets.append( ciw ); - } -} - -/** @brief A "details" dialog for the results-list - * - * This displays the same RequirementsList as ResultsListWidget, - * but the *details* part rather than the show description. - * - * This is an internal-to-the-widget class. - */ -class ResultsListDialog : public QDialog -{ - Q_OBJECT -public: - /** @brief Create a dialog for the given @p checkEntries list of requirements. - * - * The list must continue to exist for the lifetime of the dialog, - * or UB happens. - */ - ResultsListDialog( const Calamares::RequirementsModel& model, QWidget* parent ); - ~ResultsListDialog() override; - -private: - QLabel* m_title; - QList< ResultWidget* > m_resultWidgets; ///< One widget for each entry with details available - const Calamares::RequirementsModel& m_model; - - void retranslate(); -}; - -ResultsListDialog::ResultsListDialog( const Calamares::RequirementsModel& model, QWidget* parent ) - : QDialog( parent ) - , m_model( model ) -{ - auto* mainLayout = new QVBoxLayout; - auto* entriesLayout = new QVBoxLayout; - - m_title = new QLabel( this ); - m_title->setObjectName( "resultDialogTitle" ); - - createResultWidgets( entriesLayout, - m_resultWidgets, - model, - []( const Calamares::RequirementsModel& m, QModelIndex i ) - { return m.data( i, Calamares::RequirementsModel::HasDetails ).toBool(); } ); - - QDialogButtonBox* buttonBox = new QDialogButtonBox( QDialogButtonBox::Close, Qt::Horizontal, this ); - buttonBox->setObjectName( "resultDialogButtons" ); - - mainLayout->addWidget( m_title ); - mainLayout->addLayout( entriesLayout ); - mainLayout->addWidget( buttonBox ); - - setLayout( mainLayout ); - - connect( buttonBox, &QDialogButtonBox::clicked, this, &QDialog::close ); - - CALAMARES_RETRANSLATE_SLOT( &ResultsListDialog::retranslate ); -} - -ResultsListDialog::~ResultsListDialog() {} - -void -ResultsListDialog::retranslate() -{ - m_title->setText( tr( "For best results, please ensure that this computer:" ) ); - setWindowTitle( tr( "System requirements" ) ); - - for ( auto i = 0; i < m_model.count(); i++ ) - { - if ( m_resultWidgets[ i ] ) - { - m_resultWidgets[ i ]->setText( - m_model.data( m_model.index( i ), Calamares::RequirementsModel::Details ).toString() ); - } - } -} - - ResultsListWidget::ResultsListWidget( Config* config, QWidget* parent ) : QWidget( parent ) , m_config( config ) { setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); - QBoxLayout* mainLayout = new QVBoxLayout; - QBoxLayout* entriesLayout = new QVBoxLayout; - + auto mainLayout = new QVBoxLayout; setLayout( mainLayout ); - int paddingSize = qBound( 32, CalamaresUtils::defaultFontHeight() * 4, 128 ); + QHBoxLayout* explanationLayout = new QHBoxLayout; + m_explanation = new QLabel( m_config->warningMessage() ); + m_explanation->setWordWrap( true ); + m_explanation->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); + m_explanation->setOpenExternalLinks( false ); + m_explanation->setObjectName( "resultsExplanation" ); + explanationLayout->addWidget( m_explanation ); + m_countdown = new CountdownWaitingWidget; + m_countdown->setToolTip( tr( "Checking requirements again in a few seconds ..." ) ); + m_countdown->start(); + explanationLayout->addWidget( m_countdown ); - QHBoxLayout* spacerLayout = new QHBoxLayout; - mainLayout->addLayout( spacerLayout ); - spacerLayout->addSpacing( paddingSize ); - spacerLayout->addLayout( entriesLayout ); - spacerLayout->addSpacing( paddingSize ); - CalamaresUtils::unmarginLayout( spacerLayout ); + mainLayout->addLayout( explanationLayout ); + mainLayout->addSpacing( CalamaresUtils::defaultFontHeight() / 2 ); - auto* explanation = new QLabel( m_config->warningMessage() ); - explanation->setWordWrap( true ); - explanation->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); - explanation->setOpenExternalLinks( false ); - explanation->setObjectName( "resultsExplanation" ); - entriesLayout->addWidget( explanation ); + auto* listview = new QListView( this ); + listview->setSelectionMode( QAbstractItemView::NoSelection ); + listview->setDragDropMode( QAbstractItemView::NoDragDrop ); + listview->setAcceptDrops( false ); + listview->setItemDelegate( new ResultDelegate( this, Calamares::RequirementsModel::NegatedText ) ); + listview->setModel( config->unsatisfiedRequirements() ); + m_centralWidget = listview; + m_centralLayout = mainLayout; - connect( config, &Config::warningMessageChanged, explanation, &QLabel::setText ); - connect( explanation, &QLabel::linkActivated, this, &ResultsListWidget::linkClicked ); + mainLayout->addWidget( listview ); + mainLayout->addStretch(); + connect( config, &Config::warningMessageChanged, m_explanation, &QLabel::setText ); +} + +void +ResultsListWidget::requirementsChanged() +{ // Check that all are satisfied (gives warnings if not) and // all *mandatory* entries are satisfied (gives errors if not). - const bool requirementsSatisfied = config->requirementsModel()->satisfiedRequirements(); - auto isUnSatisfied = []( const Calamares::RequirementsModel& m, QModelIndex i ) - { return !m.data( i, Calamares::RequirementsModel::Satisfied ).toBool(); }; + const bool requirementsSatisfied = m_config->requirementsModel()->satisfiedRequirements(); - createResultWidgets( entriesLayout, m_resultWidgets, *( config->requirementsModel() ), isUnSatisfied ); + if ( requirementsSatisfied ) + { + m_countdown->stop(); + m_countdown->hide(); + + delete m_centralWidget; + m_centralWidget = nullptr; - if ( !requirementsSatisfied ) - { - entriesLayout->insertSpacing( 1, CalamaresUtils::defaultFontHeight() / 2 ); - mainLayout->addStretch(); - } - else - { if ( !Calamares::Branding::instance()->imagePath( Calamares::Branding::ProductWelcome ).isEmpty() ) { QPixmap theImage @@ -218,41 +105,10 @@ ResultsListWidget::ResultsListWidget( Config* config, QWidget* parent ) imageLabel->setAlignment( Qt::AlignCenter ); imageLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); imageLabel->setObjectName( "welcomeLogo" ); - mainLayout->addWidget( imageLabel ); + // This specifically isn't assigned to m_centralWidget + m_centralLayout->addWidget( imageLabel ); } } - explanation->setAlignment( Qt::AlignCenter ); - } - - CALAMARES_RETRANSLATE_SLOT( &ResultsListWidget::retranslate ); -} - - -void -ResultsListWidget::linkClicked( const QString& link ) -{ - if ( link == "#details" ) - { - auto* dialog = new ResultsListDialog( *( m_config->requirementsModel() ), this ); - dialog->exec(); - dialog->deleteLater(); + m_explanation->setAlignment( Qt::AlignCenter ); } } - -void -ResultsListWidget::retranslate() -{ - const auto& model = *( m_config->requirementsModel() ); - for ( auto i = 0; i < model.count(); i++ ) - { - if ( m_resultWidgets[ i ] ) - { - m_resultWidgets[ i ]->setText( - model.data( model.index( i ), Calamares::RequirementsModel::NegatedText ).toString() ); - } - } -} - -#include "utils/moc-warnings.h" - -#include "ResultsListWidget.moc" diff --git a/src/modules/welcome/checker/ResultsListWidget.h b/src/modules/welcome/checker/ResultsListWidget.h index 5e96b74a0..3bbed1090 100644 --- a/src/modules/welcome/checker/ResultsListWidget.h +++ b/src/modules/welcome/checker/ResultsListWidget.h @@ -11,13 +11,15 @@ #ifndef CHECKER_RESULTSLISTWIDGET_H #define CHECKER_RESULTSLISTWIDGET_H -#include "ResultWidget.h" - #include "Config.h" #include +class CountdownWaitingWidget; + +class QBoxLayout; class QLabel; + class ResultsListWidget : public QWidget { Q_OBJECT @@ -25,12 +27,20 @@ public: explicit ResultsListWidget( Config* config, QWidget* parent ); private: - /// @brief A link in the explanatory text has been clicked - void linkClicked( const QString& link ); - void retranslate(); + /// @brief The model of requirements changed + void requirementsChanged(); - QList< ResultWidget* > m_resultWidgets; ///< One widget for each unsatisfied entry Config* m_config = nullptr; + + // UI parts, which need updating when the model changes + QLabel* m_explanation = nullptr; + CountdownWaitingWidget* m_countdown = nullptr; + // There is a central widget, which can be: + // - a list widget showing failed requirements + // - nullptr (when displaying a pretty label for language / splash purposes) + // it is placed in the central layout. + QWidget* m_centralWidget = nullptr; + QBoxLayout* m_centralLayout = nullptr; }; #endif // CHECKER_RESULTSLISTWIDGET_H diff --git a/src/modules/welcome/welcome.conf b/src/modules/welcome/welcome.conf index 6e11817bf..b86231c3f 100644 --- a/src/modules/welcome/welcome.conf +++ b/src/modules/welcome/welcome.conf @@ -64,6 +64,14 @@ requirements: # the host system satisfying the condition. # # This sample file lists all the conditions that are known. + # + # Note that the last three checks are for testing-purposes only, + # and shouldn't be used in production (they are only available + # when building Calamares in development mode): + # - *false* is a check that is always false (unsatisfied) + # - *true* is a check that is always true (satisfied) + # - *snark* is a check that is only satisfied once it has been checked + # at least three times ("what I tell you three times is true"). check: - storage - ram @@ -71,6 +79,9 @@ requirements: - internet - root - screen + - false + - true + - snark # List conditions that **must** be satisfied (from the list # of conditions, above) for installation to proceed. # If any of these conditions are not met, the user cannot diff --git a/src/modules/welcomeq/CMakeLists.txt b/src/modules/welcomeq/CMakeLists.txt index b6f950dad..7afdf638c 100644 --- a/src/modules/welcomeq/CMakeLists.txt +++ b/src/modules/welcomeq/CMakeLists.txt @@ -7,34 +7,31 @@ # This is a re-write of the welcome module using QML view steps # instead of widgets. -if( NOT WITH_QML ) +if(NOT WITH_QML) calamares_skip_module( "welcomeq (QML is not supported in this build)" ) return() endif() -set( _welcome ${CMAKE_CURRENT_SOURCE_DIR}/../welcome ) +set(_welcome ${CMAKE_CURRENT_SOURCE_DIR}/../welcome) -include_directories( ${_welcome} ) +include_directories(${_welcome}) # DUPLICATED WITH WELCOME MODULE -find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED DBus Network ) +find_package(Qt5 ${QT_VERSION} CONFIG REQUIRED DBus Network) -find_package( LIBPARTED ) -if ( LIBPARTED_FOUND ) - set( PARTMAN_SRC ${_welcome}/checker/partman_devices.c ) - set( CHECKER_LINK_LIBRARIES ${LIBPARTED_LIBRARY} ) +find_package(LIBPARTED) +if(LIBPARTED_FOUND) + set(PARTMAN_SRC ${_welcome}/checker/partman_devices.c) + set(CHECKER_LINK_LIBRARIES ${LIBPARTED_LIBRARY}) else() - set( PARTMAN_SRC ) - set( CHECKER_LINK_LIBRARIES ) - add_definitions( -DWITHOUT_LIBPARTED ) + set(PARTMAN_SRC) + set(CHECKER_LINK_LIBRARIES) + add_definitions(-DWITHOUT_LIBPARTED) endif() -set( CHECKER_SOURCES - ${_welcome}/checker/GeneralRequirements.cpp - ${PARTMAN_SRC} -) +set(CHECKER_SOURCES ${_welcome}/checker/GeneralRequirements.cpp ${PARTMAN_SRC}) -calamares_add_plugin( welcomeq +calamares_add_plugin(welcomeq TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES diff --git a/src/modules/zfs/CMakeLists.txt b/src/modules/zfs/CMakeLists.txt index 2feb911d0..07764a360 100644 --- a/src/modules/zfs/CMakeLists.txt +++ b/src/modules/zfs/CMakeLists.txt @@ -3,11 +3,10 @@ # SPDX-FileCopyrightText: 2020 Adriaan de Groot # SPDX-License-Identifier: BSD-2-Clause # -calamares_add_plugin( zfs +calamares_add_plugin(zfs TYPE job EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES ZfsJob.cpp SHARED_LIB ) - diff --git a/src/qml/calamares/CMakeLists.txt b/src/qml/calamares/CMakeLists.txt index d74e79ea0..07e376bfa 100644 --- a/src/qml/calamares/CMakeLists.txt +++ b/src/qml/calamares/CMakeLists.txt @@ -12,29 +12,31 @@ # Iterate over all the subdirectories which have a qmldir file, copy them over to the build dir, # and install them into share/calamares/qml/calamares -file( GLOB SUBDIRECTORIES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*" ) -foreach( SUBDIRECTORY ${SUBDIRECTORIES} ) - if( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}" - AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/qmldir" ) - - set( QML_DIR share/calamares/qml ) - set( QML_MODULE_DESTINATION ${QML_DIR}/calamares/${SUBDIRECTORY} ) +file(GLOB SUBDIRECTORIES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*") +foreach(SUBDIRECTORY ${SUBDIRECTORIES}) + if( + IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}" + AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/qmldir" + ) + set(QML_DIR share/calamares/qml) + set(QML_MODULE_DESTINATION ${QML_DIR}/calamares/${SUBDIRECTORY}) # We glob all the files inside the subdirectory, and we make sure they are # synced with the bindir structure and installed. - file( GLOB QML_MODULE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY} "${SUBDIRECTORY}/*" ) - foreach( QML_MODULE_FILE ${QML_MODULE_FILES} ) - if( NOT IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/${QML_MODULE_FILE} ) - configure_file( ${SUBDIRECTORY}/${QML_MODULE_FILE} ${SUBDIRECTORY}/${QML_MODULE_FILE} COPYONLY ) + file(GLOB QML_MODULE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY} "${SUBDIRECTORY}/*") + foreach(QML_MODULE_FILE ${QML_MODULE_FILES}) + if(NOT IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/${QML_MODULE_FILE}) + configure_file(${SUBDIRECTORY}/${QML_MODULE_FILE} ${SUBDIRECTORY}/${QML_MODULE_FILE} COPYONLY) - install( FILES ${CMAKE_CURRENT_BINARY_DIR}/${SUBDIRECTORY}/${QML_MODULE_FILE} - DESTINATION ${QML_MODULE_DESTINATION} ) + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/${SUBDIRECTORY}/${QML_MODULE_FILE} + DESTINATION ${QML_MODULE_DESTINATION} + ) endif() endforeach() - message( "-- ${BoldYellow}Configured QML module: ${BoldRed}calamares.${SUBDIRECTORY}${ColorReset}" ) - + message("-- ${BoldYellow}Configured QML module: ${BoldRed}calamares.${SUBDIRECTORY}${ColorReset}") endif() endforeach() -message( "" ) +message("")